@cortexkit/aft 0.46.0 → 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 +1772 -689
- 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,116 +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, Priority, 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
|
-
(function(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 || (FrameType = {}));
|
|
4415
|
-
FRAME_TYPE_MAX = FrameType.Goodbye;
|
|
4416
|
-
(function(Priority2) {
|
|
4417
|
-
Priority2[Priority2["Passive"] = 0] = "Passive";
|
|
4418
|
-
Priority2[Priority2["Interactive"] = 1] = "Interactive";
|
|
4419
|
-
Priority2[Priority2["Background"] = 2] = "Background";
|
|
4420
|
-
})(Priority || (Priority = {}));
|
|
4421
|
-
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
|
+
}
|
|
4422
4863
|
};
|
|
4423
4864
|
});
|
|
4424
4865
|
|
|
4425
|
-
// ../../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
|
|
4426
4867
|
import net from "node:net";
|
|
4427
4868
|
|
|
4428
4869
|
class SubcSocket {
|
|
@@ -4471,6 +4912,24 @@ class SubcSocket {
|
|
|
4471
4912
|
});
|
|
4472
4913
|
});
|
|
4473
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
|
+
}
|
|
4474
4933
|
readExact(n, deadlineMs) {
|
|
4475
4934
|
if (this.waiter) {
|
|
4476
4935
|
return Promise.reject(new Error("concurrent readExact is not supported"));
|
|
@@ -4593,6 +5052,7 @@ class SubcSocket {
|
|
|
4593
5052
|
}
|
|
4594
5053
|
var SocketClosedError, SocketTimeoutError, SocketWriteNotQueuedError, SocketWriteQueuedError;
|
|
4595
5054
|
var init_socket = __esm(() => {
|
|
5055
|
+
init_envelope();
|
|
4596
5056
|
SocketClosedError = class SocketClosedError extends Error {
|
|
4597
5057
|
};
|
|
4598
5058
|
SocketTimeoutError = class SocketTimeoutError extends Error {
|
|
@@ -4613,7 +5073,7 @@ var init_socket = __esm(() => {
|
|
|
4613
5073
|
};
|
|
4614
5074
|
});
|
|
4615
5075
|
|
|
4616
|
-
// ../../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
|
|
4617
5077
|
import { promises as fs2 } from "node:fs";
|
|
4618
5078
|
import { debuglog } from "node:util";
|
|
4619
5079
|
|
|
@@ -4623,7 +5083,11 @@ class SubcClient {
|
|
|
4623
5083
|
opts;
|
|
4624
5084
|
nextCorr = 1n;
|
|
4625
5085
|
pending = new Map;
|
|
5086
|
+
lateResponses = new Map;
|
|
4626
5087
|
routes = new Map;
|
|
5088
|
+
liveRoutes = new Map;
|
|
5089
|
+
connectionToken = newConnectionToken();
|
|
5090
|
+
ingressEpochDropCount = 0;
|
|
4627
5091
|
closedErr = null;
|
|
4628
5092
|
closeStarted = false;
|
|
4629
5093
|
reconnecting = null;
|
|
@@ -4651,40 +5115,71 @@ class SubcClient {
|
|
|
4651
5115
|
}
|
|
4652
5116
|
async routeOpen(target, identity, opts = {}) {
|
|
4653
5117
|
const consumerIdentity = routeOpenConsumerIdentity(opts);
|
|
5118
|
+
const consumerCapabilities = opts.consumerCapabilities;
|
|
4654
5119
|
const body = this.encode({
|
|
4655
5120
|
op: "route.open",
|
|
4656
5121
|
target,
|
|
4657
5122
|
identity,
|
|
4658
|
-
...consumerIdentity ? { consumer_identity: consumerIdentity } : {}
|
|
5123
|
+
...consumerIdentity ? { consumer_identity: consumerIdentity } : {},
|
|
5124
|
+
...consumerCapabilities !== undefined ? { consumer_capabilities: consumerCapabilities } : {}
|
|
4659
5125
|
});
|
|
4660
|
-
|
|
4661
|
-
const
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
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;
|
|
4666
5156
|
}
|
|
4667
|
-
async request(
|
|
5157
|
+
async request(handle, body, opts = {}) {
|
|
5158
|
+
this.assertLiveHandle(handle);
|
|
4668
5159
|
const bytes = body instanceof Uint8Array ? body : this.encode(body);
|
|
4669
5160
|
const priority = opts.priority ?? Priority.Interactive;
|
|
4670
|
-
const
|
|
5161
|
+
const admission = opts.admissionClass ?? AdmissionClass.Normal;
|
|
5162
|
+
const reply = await this.send(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress);
|
|
4671
5163
|
return this.parseJson(reply);
|
|
4672
5164
|
}
|
|
4673
5165
|
async call(moduleId, method, params, opts = {}) {
|
|
4674
5166
|
const body = params === undefined ? { method } : { method, params };
|
|
4675
5167
|
let retriedUnknownChannel = false;
|
|
4676
5168
|
for (;; ) {
|
|
4677
|
-
const
|
|
5169
|
+
const routeHandle = await this.cachedRouteHandle(moduleId, opts);
|
|
4678
5170
|
try {
|
|
4679
|
-
return await this.managedRequest(
|
|
5171
|
+
return await this.managedRequest(routeHandle, body, opts);
|
|
4680
5172
|
} catch (err) {
|
|
4681
5173
|
if (!(err instanceof SubcCallError))
|
|
4682
5174
|
throw this.terminalCallError("managed call failed", err);
|
|
4683
5175
|
if (err.code === "unknown_channel" && !retriedUnknownChannel && !this.closeStarted) {
|
|
4684
5176
|
retriedUnknownChannel = true;
|
|
4685
|
-
this.
|
|
5177
|
+
this.evictRouteHandle(routeHandle);
|
|
4686
5178
|
continue;
|
|
4687
5179
|
}
|
|
5180
|
+
if (err.code === "unknown_channel" && retriedUnknownChannel) {
|
|
5181
|
+
this.evictRouteHandle(routeHandle);
|
|
5182
|
+
}
|
|
4688
5183
|
if (err.kind === "not_sent") {
|
|
4689
5184
|
try {
|
|
4690
5185
|
await this.reconnectAfterDrop(err);
|
|
@@ -4700,29 +5195,31 @@ class SubcClient {
|
|
|
4700
5195
|
}
|
|
4701
5196
|
}
|
|
4702
5197
|
}
|
|
4703
|
-
subscribe(
|
|
5198
|
+
subscribe(handle, body, onEvent, opts = {}) {
|
|
5199
|
+
this.assertLiveHandle(handle);
|
|
4704
5200
|
const bytes = body instanceof Uint8Array ? body : this.encode(body);
|
|
4705
5201
|
const priority = opts.priority ?? Priority.Interactive;
|
|
4706
|
-
const
|
|
4707
|
-
const
|
|
5202
|
+
const admission = opts.admissionClass ?? AdmissionClass.Normal;
|
|
5203
|
+
const corr = this.allocateCorr();
|
|
5204
|
+
const key = pendingKey(handle, corr);
|
|
4708
5205
|
const closed = new Promise((resolve7, reject) => {
|
|
4709
5206
|
if (this.closedErr) {
|
|
4710
5207
|
reject(this.closedErr);
|
|
4711
5208
|
return;
|
|
4712
5209
|
}
|
|
4713
5210
|
this.pending.set(key, {
|
|
4714
|
-
|
|
5211
|
+
handle,
|
|
4715
5212
|
resolve: () => resolve7(),
|
|
4716
5213
|
reject,
|
|
4717
5214
|
onProgress: onEvent,
|
|
4718
5215
|
timer: null,
|
|
4719
5216
|
subscription: true
|
|
4720
5217
|
});
|
|
4721
|
-
const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false),
|
|
5218
|
+
const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), handle.channel, handle.epoch, corr, bytes);
|
|
4722
5219
|
this.sock.write(encodeFrame(frame), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS).catch((err) => {
|
|
4723
|
-
const
|
|
4724
|
-
if (
|
|
4725
|
-
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)));
|
|
4726
5223
|
});
|
|
4727
5224
|
});
|
|
4728
5225
|
let cancelled = false;
|
|
@@ -4730,45 +5227,77 @@ class SubcClient {
|
|
|
4730
5227
|
if (cancelled)
|
|
4731
5228
|
return;
|
|
4732
5229
|
cancelled = true;
|
|
4733
|
-
|
|
4734
|
-
this.sock.write(encodeFrame(cancel), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS).catch(() => {});
|
|
5230
|
+
this.cancel(handle, corr, priority);
|
|
4735
5231
|
};
|
|
4736
5232
|
return { unsubscribe, closed };
|
|
4737
5233
|
}
|
|
4738
|
-
|
|
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 = {}) {
|
|
4739
5274
|
const key = routeCacheKey(target, identity, routeOpenConsumerIdentity(opts));
|
|
4740
5275
|
const cached = this.routes.get(key);
|
|
4741
5276
|
if (!cached)
|
|
4742
5277
|
return;
|
|
4743
5278
|
cached.closed = true;
|
|
4744
5279
|
this.routes.delete(key);
|
|
4745
|
-
const
|
|
4746
|
-
cached.
|
|
4747
|
-
if (
|
|
4748
|
-
await this.
|
|
5280
|
+
const handle = cached.handle;
|
|
5281
|
+
cached.handle = null;
|
|
5282
|
+
if (handle)
|
|
5283
|
+
await this.closeRoute(handle, opts);
|
|
4749
5284
|
}
|
|
4750
|
-
async closeRouteChannel(
|
|
4751
|
-
|
|
4752
|
-
return;
|
|
4753
|
-
if (opts.drain) {
|
|
4754
|
-
await this.drainUnaryOnChannel(channel);
|
|
4755
|
-
}
|
|
4756
|
-
this.failChannel(channel, new SubcError("route closed by closeRoute", "route_closed"));
|
|
4757
|
-
this.sendRouteGoodbye(channel);
|
|
5285
|
+
async closeRouteChannel(handle, opts = {}) {
|
|
5286
|
+
await this.closeRoute(handle, opts);
|
|
4758
5287
|
}
|
|
4759
5288
|
close() {
|
|
4760
5289
|
this.closeStarted = true;
|
|
4761
5290
|
this.fail(new SubcError("client closed"));
|
|
4762
5291
|
this.sock.close();
|
|
4763
5292
|
}
|
|
4764
|
-
|
|
5293
|
+
drainUnaryOnHandle(handle) {
|
|
4765
5294
|
const waiters = [];
|
|
4766
5295
|
for (const pending of this.pending.values()) {
|
|
4767
|
-
if (pending.
|
|
5296
|
+
if (pending.handle === handle && !pending.subscription) {
|
|
4768
5297
|
waiters.push(new Promise((resolve7) => {
|
|
4769
|
-
const
|
|
5298
|
+
const previous = pending.onSettle;
|
|
4770
5299
|
pending.onSettle = () => {
|
|
4771
|
-
|
|
5300
|
+
previous?.();
|
|
4772
5301
|
resolve7();
|
|
4773
5302
|
};
|
|
4774
5303
|
}));
|
|
@@ -4778,11 +5307,21 @@ class SubcClient {
|
|
|
4778
5307
|
return;
|
|
4779
5308
|
});
|
|
4780
5309
|
}
|
|
4781
|
-
sendRouteGoodbye(
|
|
4782
|
-
|
|
5310
|
+
sendRouteGoodbye(handle, closeOnQueueFailure = false) {
|
|
5311
|
+
this.assertLiveConnection(handle);
|
|
5312
|
+
if (this.closedErr) {
|
|
5313
|
+
if (closeOnQueueFailure)
|
|
5314
|
+
this.closeConnectionAfterCleanupFailure();
|
|
4783
5315
|
return;
|
|
4784
|
-
|
|
4785
|
-
|
|
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
|
+
});
|
|
4786
5325
|
}
|
|
4787
5326
|
static async openConnection(opts) {
|
|
4788
5327
|
const conn = await readConnectionFile(opts.connectionFile);
|
|
@@ -4797,37 +5336,48 @@ class SubcClient {
|
|
|
4797
5336
|
}
|
|
4798
5337
|
return { sock, conn };
|
|
4799
5338
|
}
|
|
4800
|
-
async controlRpc(body) {
|
|
4801
|
-
return this.send(
|
|
5339
|
+
async controlRpc(body, acceptFrame, onLateResponse) {
|
|
5340
|
+
return this.send(null, body, Priority.Interactive, AdmissionClass.Normal, undefined, undefined, acceptFrame, onLateResponse);
|
|
4802
5341
|
}
|
|
4803
|
-
send(
|
|
5342
|
+
send(handle, body, priority, admission, timeoutMs, onProgress, acceptFrame, onLateResponse) {
|
|
5343
|
+
if (handle)
|
|
5344
|
+
this.assertLiveHandle(handle);
|
|
4804
5345
|
if (this.closedErr)
|
|
4805
5346
|
return Promise.reject(this.closedErr);
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
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);
|
|
4809
5357
|
return new Promise((resolve7, reject) => {
|
|
4810
5358
|
const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
4811
5359
|
const pending = {
|
|
4812
|
-
|
|
5360
|
+
handle,
|
|
4813
5361
|
resolve: resolve7,
|
|
4814
5362
|
reject,
|
|
4815
5363
|
onProgress,
|
|
4816
|
-
timer: null
|
|
5364
|
+
timer: null,
|
|
5365
|
+
acceptFrame,
|
|
5366
|
+
onLateResponse
|
|
4817
5367
|
};
|
|
4818
|
-
pending.timer = setTimeout(() =>
|
|
4819
|
-
this.arbitrateTimeout(key, pending, channel, corr, ms);
|
|
4820
|
-
}, ms);
|
|
5368
|
+
pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, channel, corr, ms), ms);
|
|
4821
5369
|
this.pending.set(key, pending);
|
|
4822
|
-
this.sock.write(encodeFrame(frame), Date.now() + ms).catch((
|
|
4823
|
-
const
|
|
4824
|
-
if (
|
|
4825
|
-
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)));
|
|
4826
5374
|
});
|
|
4827
5375
|
});
|
|
4828
5376
|
}
|
|
4829
5377
|
arbitrateTimeout(key, pending, channel, corr, ms) {
|
|
4830
5378
|
const settleAsTimeout = () => {
|
|
5379
|
+
if (pending.onLateResponse)
|
|
5380
|
+
this.lateResponses.set(key, pending.onLateResponse);
|
|
4831
5381
|
this.rejectPending(key, pending, new SubcError(this.timeoutMessage(channel, corr, ms), REQUEST_DEADLINE_MARKER));
|
|
4832
5382
|
};
|
|
4833
5383
|
const graceDeadline = Date.now() + this.opts.timeoutArbitrationGraceMs;
|
|
@@ -4843,59 +5393,67 @@ class SubcClient {
|
|
|
4843
5393
|
};
|
|
4844
5394
|
setImmediate(arbitrate);
|
|
4845
5395
|
}
|
|
4846
|
-
async managedRequest(
|
|
5396
|
+
async managedRequest(handle, body, opts) {
|
|
4847
5397
|
const bytes = body instanceof Uint8Array ? body : this.encode(body);
|
|
4848
5398
|
const priority = opts.priority ?? Priority.Interactive;
|
|
5399
|
+
const admission = opts.admissionClass ?? AdmissionClass.Normal;
|
|
4849
5400
|
try {
|
|
4850
|
-
const reply = await this.sendManaged(
|
|
5401
|
+
const reply = await this.sendManaged(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress);
|
|
4851
5402
|
return this.parseJson(reply);
|
|
4852
|
-
} catch (
|
|
4853
|
-
if (
|
|
4854
|
-
throw
|
|
4855
|
-
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);
|
|
4856
5407
|
}
|
|
4857
5408
|
}
|
|
4858
|
-
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
|
+
}
|
|
4859
5415
|
if (this.closedErr) {
|
|
4860
5416
|
return Promise.reject(this.notSentCallError("request was not sent because the subc connection was already closed", this.closedErr));
|
|
4861
5417
|
}
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
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);
|
|
4865
5426
|
let handedToSocket = false;
|
|
4866
|
-
const classifyFailure = (
|
|
4867
|
-
if (!handedToSocket)
|
|
4868
|
-
return this.notSentCallError("request bytes were not queued to the subc socket",
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
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);
|
|
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);
|
|
4872
5432
|
}
|
|
4873
|
-
return this.outcomeUnknownCallError("connection dropped before the managed call returned a response",
|
|
5433
|
+
return this.outcomeUnknownCallError("connection dropped before the managed call returned a response", error2);
|
|
4874
5434
|
};
|
|
4875
5435
|
return new Promise((resolve7, reject) => {
|
|
4876
5436
|
const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
4877
5437
|
const pending = {
|
|
4878
|
-
|
|
5438
|
+
handle,
|
|
4879
5439
|
resolve: resolve7,
|
|
4880
5440
|
reject,
|
|
4881
5441
|
onProgress,
|
|
4882
5442
|
timer: null,
|
|
4883
5443
|
classifyFailure
|
|
4884
5444
|
};
|
|
4885
|
-
pending.timer = setTimeout(() =>
|
|
4886
|
-
this.arbitrateTimeout(key, pending, channel, corr, ms);
|
|
4887
|
-
}, ms);
|
|
5445
|
+
pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, handle.channel, corr, ms), ms);
|
|
4888
5446
|
this.pending.set(key, pending);
|
|
4889
5447
|
const write = this.sock.writeTracked(encodeFrame(frame), Date.now() + ms);
|
|
4890
5448
|
handedToSocket = write.queued;
|
|
4891
|
-
write.completed.catch((
|
|
4892
|
-
const
|
|
4893
|
-
if (
|
|
4894
|
-
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)));
|
|
4895
5453
|
});
|
|
4896
5454
|
});
|
|
4897
5455
|
}
|
|
4898
|
-
async
|
|
5456
|
+
async cachedRouteHandle(moduleId, opts) {
|
|
4899
5457
|
const identity = opts.identity ?? this.opts.identity;
|
|
4900
5458
|
if (!identity) {
|
|
4901
5459
|
throw new SubcCallError("terminal", "managed call requires a BindIdentity in SubcClient.connect({ identity }) or call(..., { identity })", "missing_identity");
|
|
@@ -4911,15 +5469,13 @@ class SubcClient {
|
|
|
4911
5469
|
target,
|
|
4912
5470
|
identity,
|
|
4913
5471
|
consumerIdentity,
|
|
4914
|
-
|
|
4915
|
-
generation: 0,
|
|
5472
|
+
handle: null,
|
|
4916
5473
|
opening: null
|
|
4917
5474
|
};
|
|
4918
5475
|
this.routes.set(key, cached);
|
|
4919
5476
|
}
|
|
4920
|
-
if (cached.
|
|
4921
|
-
return cached.
|
|
4922
|
-
}
|
|
5477
|
+
if (cached.handle && this.isLiveHandle(cached.handle))
|
|
5478
|
+
return cached.handle;
|
|
4923
5479
|
if (!cached.opening) {
|
|
4924
5480
|
cached.opening = this.openCachedRoute(cached).finally(() => {
|
|
4925
5481
|
cached.opening = null;
|
|
@@ -4936,44 +5492,43 @@ class SubcClient {
|
|
|
4936
5492
|
throw this.routeClosedDuringOpen();
|
|
4937
5493
|
try {
|
|
4938
5494
|
await this.ensureConnectedForManaged();
|
|
4939
|
-
} catch (
|
|
4940
|
-
throw this.notSentRecoveryError("route.open could not run because reconnect failed",
|
|
4941
|
-
}
|
|
4942
|
-
if (cached.channel !== null && cached.generation === this.generation && !this.closedErr) {
|
|
4943
|
-
return cached.channel;
|
|
5495
|
+
} catch (error2) {
|
|
5496
|
+
throw this.notSentRecoveryError("route.open could not run because reconnect failed", error2);
|
|
4944
5497
|
}
|
|
5498
|
+
if (cached.handle && this.isLiveHandle(cached.handle))
|
|
5499
|
+
return cached.handle;
|
|
4945
5500
|
try {
|
|
4946
|
-
const
|
|
5501
|
+
const handle = await this.routeOpen(cached.target, cached.identity, {
|
|
4947
5502
|
consumerIdentity: cached.consumerIdentity ?? null
|
|
4948
5503
|
});
|
|
4949
5504
|
if (cached.closed) {
|
|
4950
|
-
this.
|
|
5505
|
+
this.liveRoutes.delete(handle.channel);
|
|
5506
|
+
this.sendRouteGoodbye(handle);
|
|
4951
5507
|
throw this.routeClosedDuringOpen();
|
|
4952
5508
|
}
|
|
4953
|
-
cached.
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
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)) {
|
|
4960
5515
|
try {
|
|
4961
|
-
await this.reconnectAfterDrop(
|
|
4962
|
-
} catch (
|
|
4963
|
-
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);
|
|
4964
5519
|
}
|
|
4965
5520
|
continue;
|
|
4966
5521
|
}
|
|
4967
|
-
if (!this.closeStarted &&
|
|
5522
|
+
if (!this.closeStarted && error2 instanceof SubcError && isRetryableRouteOpenCode(error2.code)) {
|
|
4968
5523
|
routeRetryAttempt += 1;
|
|
4969
5524
|
if (routeRetryAttempt < this.opts.reconnectBackoff.maxAttempts && Date.now() < routeRetryDeadline) {
|
|
4970
5525
|
await this.opts.sleep(routeRetryDelay);
|
|
4971
5526
|
routeRetryDelay = Math.min(routeRetryDelay * 2, this.opts.reconnectBackoff.capMs);
|
|
4972
5527
|
continue;
|
|
4973
5528
|
}
|
|
4974
|
-
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);
|
|
4975
5530
|
}
|
|
4976
|
-
throw this.terminalCallError(`route.open failed for module ${cached.moduleId}`,
|
|
5531
|
+
throw this.terminalCallError(`route.open failed for module ${cached.moduleId}`, error2);
|
|
4977
5532
|
}
|
|
4978
5533
|
}
|
|
4979
5534
|
}
|
|
@@ -5036,25 +5591,27 @@ class SubcClient {
|
|
|
5036
5591
|
this.currentConn = opened.conn;
|
|
5037
5592
|
this.closedErr = null;
|
|
5038
5593
|
this.generation += 1;
|
|
5594
|
+
this.connectionToken = newConnectionToken();
|
|
5595
|
+
this.liveRoutes.clear();
|
|
5596
|
+
this.lateResponses.clear();
|
|
5597
|
+
this.nextCorr = 1n;
|
|
5039
5598
|
this.readLoop(opened.sock, this.generation);
|
|
5040
5599
|
}
|
|
5041
5600
|
async reopenCachedRoutes() {
|
|
5042
|
-
for (const cached of this.routes.values())
|
|
5043
|
-
cached.
|
|
5044
|
-
cached.generation = 0;
|
|
5045
|
-
}
|
|
5601
|
+
for (const cached of this.routes.values())
|
|
5602
|
+
cached.handle = null;
|
|
5046
5603
|
for (const cached of this.routes.values()) {
|
|
5047
5604
|
if (cached.closed)
|
|
5048
5605
|
continue;
|
|
5049
|
-
const
|
|
5606
|
+
const handle = await this.routeOpen(cached.target, cached.identity, {
|
|
5050
5607
|
consumerIdentity: cached.consumerIdentity ?? null
|
|
5051
5608
|
});
|
|
5052
5609
|
if (cached.closed) {
|
|
5053
|
-
this.
|
|
5610
|
+
this.liveRoutes.delete(handle.channel);
|
|
5611
|
+
this.sendRouteGoodbye(handle);
|
|
5054
5612
|
continue;
|
|
5055
5613
|
}
|
|
5056
|
-
cached.
|
|
5057
|
-
cached.generation = this.generation;
|
|
5614
|
+
cached.handle = handle;
|
|
5058
5615
|
}
|
|
5059
5616
|
}
|
|
5060
5617
|
timeoutMessage(channel, corr, ms) {
|
|
@@ -5068,28 +5625,37 @@ class SubcClient {
|
|
|
5068
5625
|
async readLoop(sock, generation) {
|
|
5069
5626
|
try {
|
|
5070
5627
|
for (;; ) {
|
|
5071
|
-
|
|
5072
|
-
|
|
5628
|
+
this.readerActive = false;
|
|
5629
|
+
const frame = await sock.readFrame(Number.POSITIVE_INFINITY, { afterHeaderMs: BODY_READ_TIMEOUT_MS }, () => {
|
|
5630
|
+
this.readerActive = true;
|
|
5631
|
+
});
|
|
5073
5632
|
try {
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
if (this.sock === sock && this.generation === generation) {
|
|
5077
|
-
this.dispatch({ header, body });
|
|
5078
|
-
}
|
|
5633
|
+
if (this.sock === sock && this.generation === generation)
|
|
5634
|
+
this.dispatch(frame);
|
|
5079
5635
|
} finally {
|
|
5080
5636
|
this.readerActive = false;
|
|
5081
5637
|
}
|
|
5082
5638
|
}
|
|
5083
|
-
} catch (
|
|
5639
|
+
} catch (error2) {
|
|
5084
5640
|
if (this.sock === sock && this.generation === generation) {
|
|
5085
|
-
this.fail(
|
|
5641
|
+
this.fail(error2 instanceof Error ? error2 : new SubcError(String(error2)));
|
|
5642
|
+
}
|
|
5643
|
+
}
|
|
5644
|
+
}
|
|
5645
|
+
dispatch(frame) {
|
|
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;
|
|
5086
5652
|
}
|
|
5087
5653
|
}
|
|
5088
|
-
|
|
5089
|
-
dispatch(frame) {
|
|
5090
|
-
const key = `${frame.header.channel}:${frame.header.corr}`;
|
|
5654
|
+
const key = pendingKey(handle, frame.header.corr);
|
|
5091
5655
|
const pending = this.pending.get(key);
|
|
5092
5656
|
if (pending) {
|
|
5657
|
+
if (pending.acceptFrame && !pending.acceptFrame(frame))
|
|
5658
|
+
return;
|
|
5093
5659
|
switch (frame.header.ty) {
|
|
5094
5660
|
case FrameType.Push:
|
|
5095
5661
|
case FrameType.StreamData:
|
|
@@ -5106,15 +5672,22 @@ class SubcClient {
|
|
|
5106
5672
|
return;
|
|
5107
5673
|
}
|
|
5108
5674
|
}
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
this.
|
|
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);
|
|
5112
5679
|
return;
|
|
5113
5680
|
}
|
|
5114
|
-
if (frame.header.ty === FrameType.
|
|
5115
|
-
|
|
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);
|
|
5116
5686
|
return;
|
|
5117
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
|
+
}
|
|
5118
5691
|
}
|
|
5119
5692
|
settle(key, pending, run) {
|
|
5120
5693
|
if (this.pending.get(key) !== pending)
|
|
@@ -5137,18 +5710,16 @@ class SubcClient {
|
|
|
5137
5710
|
return new SubcError(Buffer.from(frame.body).toString("utf8") || "subc error");
|
|
5138
5711
|
}
|
|
5139
5712
|
}
|
|
5140
|
-
|
|
5713
|
+
evictRouteHandle(handle) {
|
|
5141
5714
|
for (const cached of this.routes.values()) {
|
|
5142
|
-
if (cached.
|
|
5143
|
-
cached.
|
|
5144
|
-
}
|
|
5715
|
+
if (cached.handle && sameRouteHandle(cached.handle, handle))
|
|
5716
|
+
cached.handle = null;
|
|
5145
5717
|
}
|
|
5146
5718
|
}
|
|
5147
|
-
|
|
5719
|
+
failHandle(handle, error2) {
|
|
5148
5720
|
for (const [key, pending] of this.pending) {
|
|
5149
|
-
if (pending.
|
|
5150
|
-
this.rejectPending(key, pending,
|
|
5151
|
-
}
|
|
5721
|
+
if (pending.handle && sameRouteHandle(pending.handle, handle))
|
|
5722
|
+
this.rejectPending(key, pending, error2);
|
|
5152
5723
|
}
|
|
5153
5724
|
}
|
|
5154
5725
|
fail(err) {
|
|
@@ -5176,6 +5747,44 @@ class SubcClient {
|
|
|
5176
5747
|
return this.notSentCallError(message, cause);
|
|
5177
5748
|
return this.terminalCallError(message, cause);
|
|
5178
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
|
+
}
|
|
5179
5788
|
encode(value) {
|
|
5180
5789
|
return new Uint8Array(Buffer.from(JSON.stringify(value), "utf8"));
|
|
5181
5790
|
}
|
|
@@ -5245,11 +5854,15 @@ function causeMessage(cause) {
|
|
|
5245
5854
|
return "";
|
|
5246
5855
|
return `: ${cause instanceof Error ? cause.message : String(cause)}`;
|
|
5247
5856
|
}
|
|
5857
|
+
function pendingKey(handle, corr) {
|
|
5858
|
+
return handle ? `${handle.channel}:${handle.epoch}:${corr}` : `0:0:${corr}`;
|
|
5859
|
+
}
|
|
5248
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;
|
|
5249
5861
|
var init_client = __esm(() => {
|
|
5250
5862
|
init_auth();
|
|
5251
5863
|
init_connection_file();
|
|
5252
5864
|
init_envelope();
|
|
5865
|
+
init_route_handle();
|
|
5253
5866
|
init_socket();
|
|
5254
5867
|
debug = debuglog("subc-client");
|
|
5255
5868
|
EMPTY_BODY = new Uint8Array(0);
|
|
@@ -5279,7 +5892,7 @@ var init_client = __esm(() => {
|
|
|
5279
5892
|
};
|
|
5280
5893
|
});
|
|
5281
5894
|
|
|
5282
|
-
// ../../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
|
|
5283
5896
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
5284
5897
|
|
|
5285
5898
|
class AsyncPermitPool {
|
|
@@ -5328,6 +5941,11 @@ class SubcProvider {
|
|
|
5328
5941
|
closeStarted = false;
|
|
5329
5942
|
closedErr = null;
|
|
5330
5943
|
inflight = new Map;
|
|
5944
|
+
pending = new Map;
|
|
5945
|
+
liveRoutes = new Map;
|
|
5946
|
+
connectionToken = newConnectionToken();
|
|
5947
|
+
nextCorr = 1n;
|
|
5948
|
+
ingressEpochDropCount = 0;
|
|
5331
5949
|
requestGate = new AsyncPermitPool(DEFAULT_PROVIDER_HANDLER_CAPACITY);
|
|
5332
5950
|
reconnecting = null;
|
|
5333
5951
|
generation = 1;
|
|
@@ -5347,12 +5965,55 @@ class SubcProvider {
|
|
|
5347
5965
|
this.readLoop(sock, this.generation);
|
|
5348
5966
|
this.enqueueConnectionState({ state: "connected", epoch: this.connectionEpoch });
|
|
5349
5967
|
}
|
|
5968
|
+
get droppedIngressFrames() {
|
|
5969
|
+
return this.ingressEpochDropCount;
|
|
5970
|
+
}
|
|
5350
5971
|
get conn() {
|
|
5351
5972
|
return this.currentConn;
|
|
5352
5973
|
}
|
|
5353
5974
|
currentEpoch() {
|
|
5354
5975
|
return this.connectionEpoch;
|
|
5355
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
|
+
}
|
|
5356
6017
|
static async connect(opts) {
|
|
5357
6018
|
if (opts.manifest.protocol_ver !== PROTOCOL_VERSION) {
|
|
5358
6019
|
throw new SubcProviderError(`manifest protocol_ver ${opts.manifest.protocol_ver} does not match client protocol ${PROTOCOL_VERSION}`, "invalid_manifest");
|
|
@@ -5367,7 +6028,7 @@ class SubcProvider {
|
|
|
5367
6028
|
this.cancelRestoredDebounce();
|
|
5368
6029
|
const sock = this.sock;
|
|
5369
6030
|
try {
|
|
5370
|
-
await sendFrame(sock, buildFrame(FrameType.Goodbye, controlFlags(), 0, 0n, new Uint8Array(0)));
|
|
6031
|
+
await sendFrame(sock, buildFrame(FrameType.Goodbye, controlFlags(), 0, 0, 0n, new Uint8Array(0)));
|
|
5371
6032
|
} catch {} finally {
|
|
5372
6033
|
sock.close();
|
|
5373
6034
|
this.finishClosed();
|
|
@@ -5375,12 +6036,13 @@ class SubcProvider {
|
|
|
5375
6036
|
}
|
|
5376
6037
|
await this.closed;
|
|
5377
6038
|
}
|
|
5378
|
-
static async openConnection(opts) {
|
|
6039
|
+
static async openConnection(opts, onSocket) {
|
|
5379
6040
|
const conn = await readConnectionFile(opts.connectionFile);
|
|
5380
6041
|
const deadline = Date.now() + (opts.handshakeTimeoutMs ?? DEFAULT_HANDSHAKE_TIMEOUT_MS2);
|
|
5381
6042
|
const endpoint = conn.endpoints[0];
|
|
5382
6043
|
const sock = await SubcSocket.connect(endpoint.host, endpoint.port, deadline);
|
|
5383
6044
|
try {
|
|
6045
|
+
onSocket?.(sock);
|
|
5384
6046
|
await authenticateClient(sock, conn, deadline);
|
|
5385
6047
|
await sendFrame(sock, buildHelloFrame(opts));
|
|
5386
6048
|
const ack = await expectHelloAck(sock, deadline);
|
|
@@ -5393,19 +6055,17 @@ class SubcProvider {
|
|
|
5393
6055
|
async readLoop(sock, generation) {
|
|
5394
6056
|
try {
|
|
5395
6057
|
for (;; ) {
|
|
5396
|
-
const
|
|
5397
|
-
const
|
|
5398
|
-
const body = header.len === 0 ? new Uint8Array(0) : await sock.readExact(header.len, Date.now() + BODY_READ_TIMEOUT_MS2);
|
|
5399
|
-
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);
|
|
5400
6060
|
if (!keepGoing) {
|
|
5401
6061
|
if (this.sock === sock && this.generation === generation)
|
|
5402
6062
|
this.closeStarted = true;
|
|
5403
6063
|
break;
|
|
5404
6064
|
}
|
|
5405
6065
|
}
|
|
5406
|
-
} catch (
|
|
6066
|
+
} catch (error2) {
|
|
5407
6067
|
if (this.sock === sock && this.generation === generation && !this.closeStarted) {
|
|
5408
|
-
this.handleUnexpectedDrop(sock, generation,
|
|
6068
|
+
this.handleUnexpectedDrop(sock, generation, error2 instanceof Error ? error2 : new SubcProviderError(String(error2)));
|
|
5409
6069
|
return;
|
|
5410
6070
|
}
|
|
5411
6071
|
} finally {
|
|
@@ -5417,28 +6077,58 @@ class SubcProvider {
|
|
|
5417
6077
|
}
|
|
5418
6078
|
}
|
|
5419
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
|
+
}
|
|
5420
6108
|
switch (frame.header.ty) {
|
|
5421
6109
|
case FrameType.Ping:
|
|
5422
6110
|
if (frame.header.channel === 0) {
|
|
5423
|
-
await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver, FrameType.Pong, frame.header.flags, 0, frame.header.corr, new Uint8Array(0)));
|
|
6111
|
+
await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver, FrameType.Pong, frame.header.flags, 0, 0, frame.header.corr, new Uint8Array(0)));
|
|
5424
6112
|
}
|
|
5425
6113
|
return true;
|
|
5426
6114
|
case FrameType.Goodbye:
|
|
5427
|
-
if (
|
|
6115
|
+
if (!handle)
|
|
5428
6116
|
return false;
|
|
5429
|
-
this.
|
|
5430
|
-
|
|
6117
|
+
this.liveRoutes.delete(handle.channel);
|
|
6118
|
+
this.abortHandle(handle);
|
|
6119
|
+
await this.opts.onRouteGone?.(handle);
|
|
5431
6120
|
return true;
|
|
5432
6121
|
case FrameType.Cancel:
|
|
5433
|
-
|
|
6122
|
+
if (handle)
|
|
6123
|
+
this.inflight.get(routeKey(handle, frame.header.corr))?.abort();
|
|
5434
6124
|
return true;
|
|
5435
6125
|
case FrameType.Request:
|
|
5436
6126
|
if (frame.header.channel === 0) {
|
|
5437
6127
|
await this.handleControlRequest(frame, sock, generation);
|
|
5438
|
-
} else {
|
|
5439
|
-
this.handleDataRequest(frame, sock, generation).catch((
|
|
6128
|
+
} else if (handle) {
|
|
6129
|
+
this.handleDataRequest(frame, handle, sock, generation).catch((error2) => {
|
|
5440
6130
|
if (!this.closeStarted && this.sock === sock && this.generation === generation) {
|
|
5441
|
-
console.warn("SubcProvider handler failed after its request was dispatched",
|
|
6131
|
+
console.warn("SubcProvider handler failed after its request was dispatched", error2);
|
|
5442
6132
|
}
|
|
5443
6133
|
});
|
|
5444
6134
|
}
|
|
@@ -5447,19 +6137,28 @@ class SubcProvider {
|
|
|
5447
6137
|
return true;
|
|
5448
6138
|
}
|
|
5449
6139
|
}
|
|
5450
|
-
|
|
5451
|
-
const prefix = `${
|
|
6140
|
+
abortHandle(handle) {
|
|
6141
|
+
const prefix = `${handle.channel}:${handle.epoch}:`;
|
|
5452
6142
|
for (const [key, controller] of this.inflight) {
|
|
5453
6143
|
if (key.startsWith(prefix))
|
|
5454
6144
|
controller.abort();
|
|
5455
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
|
+
}
|
|
5456
6153
|
}
|
|
5457
|
-
abortGeneration(
|
|
5458
|
-
|
|
5459
|
-
for (const [key,
|
|
5460
|
-
|
|
5461
|
-
|
|
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"));
|
|
5462
6160
|
}
|
|
6161
|
+
this.liveRoutes.clear();
|
|
5463
6162
|
}
|
|
5464
6163
|
abortAllInflight() {
|
|
5465
6164
|
for (const controller of this.inflight.values())
|
|
@@ -5468,9 +6167,9 @@ class SubcProvider {
|
|
|
5468
6167
|
async handleControlRequest(frame, sock, generation) {
|
|
5469
6168
|
const request = parseJson(frame.body);
|
|
5470
6169
|
if (request.op === HEALTH_CHECK_OP) {
|
|
5471
|
-
this.handleHealthRequest(frame, sock, generation).catch((
|
|
6170
|
+
this.handleHealthRequest(frame, sock, generation).catch((error2) => {
|
|
5472
6171
|
if (!this.closeStarted && this.sock === sock && this.generation === generation) {
|
|
5473
|
-
console.warn("SubcProvider health handler failed after its request was dispatched",
|
|
6172
|
+
console.warn("SubcProvider health handler failed after its request was dispatched", error2);
|
|
5474
6173
|
}
|
|
5475
6174
|
});
|
|
5476
6175
|
return;
|
|
@@ -5478,47 +6177,93 @@ class SubcProvider {
|
|
|
5478
6177
|
if (request.op !== "route.bind") {
|
|
5479
6178
|
throw new SubcProviderError(`unsupported module control request ${request.op ?? "<missing op>"}`);
|
|
5480
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);
|
|
5481
6193
|
const bindRequest = {
|
|
5482
|
-
|
|
6194
|
+
handle: tentative,
|
|
5483
6195
|
target: request.target,
|
|
5484
6196
|
identity: request.identity,
|
|
5485
|
-
principal: request.principal
|
|
6197
|
+
principal: request.principal,
|
|
6198
|
+
consumer_capabilities: request.consumer_capabilities
|
|
5486
6199
|
};
|
|
5487
|
-
|
|
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
|
+
}
|
|
5488
6211
|
const rejection = bindRejection(decision);
|
|
5489
6212
|
if (rejection) {
|
|
5490
|
-
|
|
6213
|
+
try {
|
|
6214
|
+
await this.sendError(frame, rejection.code, rejection.message, controlFlags(), sock, generation);
|
|
6215
|
+
} finally {
|
|
6216
|
+
await this.opts.onRouteGone?.(tentative);
|
|
6217
|
+
}
|
|
6218
|
+
return;
|
|
6219
|
+
}
|
|
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);
|
|
5491
6228
|
return;
|
|
5492
6229
|
}
|
|
5493
|
-
|
|
6230
|
+
this.liveRoutes.set(tentative.channel, tentative);
|
|
6231
|
+
await this.opts.onBound?.(tentative);
|
|
5494
6232
|
}
|
|
5495
|
-
async handleDataRequest(frame, sock, generation) {
|
|
5496
|
-
const {
|
|
5497
|
-
const key = routeKey(
|
|
6233
|
+
async handleDataRequest(frame, handle, sock, generation) {
|
|
6234
|
+
const { corr, ver } = frame.header;
|
|
6235
|
+
const key = routeKey(handle, corr);
|
|
5498
6236
|
const controller = new AbortController;
|
|
5499
6237
|
this.inflight.set(key, controller);
|
|
5500
|
-
const
|
|
5501
|
-
|
|
6238
|
+
const context = {
|
|
6239
|
+
handle,
|
|
5502
6240
|
signal: controller.signal,
|
|
5503
6241
|
currentEpoch: () => this.connectionEpoch,
|
|
5504
|
-
emit: async (eventBody) => {
|
|
6242
|
+
emit: async (eventBody, options = {}) => {
|
|
6243
|
+
this.assertLiveHandle(handle);
|
|
5505
6244
|
if (controller.signal.aborted)
|
|
5506
6245
|
return;
|
|
5507
|
-
await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.StreamData,
|
|
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));
|
|
5508
6247
|
}
|
|
5509
6248
|
};
|
|
5510
6249
|
const releasePermit = await (this.requestGate ?? new AsyncPermitPool(DEFAULT_PROVIDER_HANDLER_CAPACITY)).acquire();
|
|
6250
|
+
const dataFlags = buildFlags(false, Priority.Interactive, false);
|
|
5511
6251
|
try {
|
|
5512
|
-
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);
|
|
5513
6256
|
if (body === undefined) {
|
|
5514
|
-
await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.StreamEnd, dataFlags, channel, corr, new Uint8Array(0)));
|
|
6257
|
+
await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.StreamEnd, dataFlags, handle.channel, handle.epoch, corr, new Uint8Array(0)));
|
|
5515
6258
|
} else if (body instanceof Uint8Array) {
|
|
5516
|
-
await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.Response, dataFlags, channel, corr, body));
|
|
6259
|
+
await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.Response, dataFlags, handle.channel, handle.epoch, corr, body));
|
|
5517
6260
|
} else {
|
|
5518
6261
|
throw new SubcProviderError("provider handler must return a Uint8Array or void", "invalid_handler_response");
|
|
5519
6262
|
}
|
|
5520
|
-
} catch (
|
|
5521
|
-
|
|
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);
|
|
5522
6267
|
} finally {
|
|
5523
6268
|
releasePermit();
|
|
5524
6269
|
if (this.inflight.get(key) === controller)
|
|
@@ -5526,8 +6271,8 @@ class SubcProvider {
|
|
|
5526
6271
|
}
|
|
5527
6272
|
}
|
|
5528
6273
|
async handleHealthRequest(frame, sock, generation) {
|
|
5529
|
-
const {
|
|
5530
|
-
const key =
|
|
6274
|
+
const { corr, ver } = frame.header;
|
|
6275
|
+
const key = `control:${generation}:${corr}`;
|
|
5531
6276
|
const controller = new AbortController;
|
|
5532
6277
|
this.inflight.set(key, controller);
|
|
5533
6278
|
const releasePermit = await (this.requestGate ?? new AsyncPermitPool(DEFAULT_PROVIDER_HANDLER_CAPACITY)).acquire();
|
|
@@ -5535,14 +6280,14 @@ class SubcProvider {
|
|
|
5535
6280
|
if (controller.signal.aborted)
|
|
5536
6281
|
return;
|
|
5537
6282
|
const report = await this.opts.health();
|
|
5538
|
-
await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.Response, controlFlags(),
|
|
6283
|
+
await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.Response, controlFlags(), 0, 0, corr, encodeJson({
|
|
5539
6284
|
op: HEALTH_CHECK_OP,
|
|
5540
6285
|
status: report.status,
|
|
5541
6286
|
...report.detail === undefined ? {} : { detail: report.detail },
|
|
5542
6287
|
...report.metrics === undefined ? {} : { metrics: report.metrics }
|
|
5543
6288
|
})));
|
|
5544
|
-
} catch (
|
|
5545
|
-
await this.sendError(frame,
|
|
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);
|
|
5546
6291
|
} finally {
|
|
5547
6292
|
releasePermit();
|
|
5548
6293
|
if (this.inflight.get(key) === controller)
|
|
@@ -5550,7 +6295,7 @@ class SubcProvider {
|
|
|
5550
6295
|
}
|
|
5551
6296
|
}
|
|
5552
6297
|
async sendError(frame, code, message, flags, sock, generation) {
|
|
5553
|
-
await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver, FrameType.Error, flags, frame.header.channel, frame.header.corr, encodeJson({ code, message })));
|
|
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 })));
|
|
5554
6299
|
}
|
|
5555
6300
|
async sendOn(sock, generation, frame) {
|
|
5556
6301
|
if (this.sock !== sock || this.generation !== generation || this.closeStarted || this.closedErr)
|
|
@@ -5558,42 +6303,79 @@ class SubcProvider {
|
|
|
5558
6303
|
await sendFrame(sock, frame);
|
|
5559
6304
|
}
|
|
5560
6305
|
handleUnexpectedDrop(sock, generation, cause) {
|
|
6306
|
+
if (this.closeStarted || this.sock !== sock || this.generation !== generation)
|
|
6307
|
+
return;
|
|
5561
6308
|
this.cancelRestoredDebounce();
|
|
5562
6309
|
this.abortGeneration(generation);
|
|
5563
6310
|
this.generation += 1;
|
|
5564
6311
|
sock.close();
|
|
5565
|
-
this.
|
|
5566
|
-
this.scheduleReconnectAfterDrop(cause);
|
|
6312
|
+
this.scheduleReconnectAfterDrop(cause, this.generation, sock);
|
|
5567
6313
|
}
|
|
5568
|
-
scheduleReconnectAfterDrop(
|
|
5569
|
-
if (this.closeStarted
|
|
6314
|
+
scheduleReconnectAfterDrop(cause, generation, droppedSocket) {
|
|
6315
|
+
if (this.closeStarted)
|
|
5570
6316
|
return;
|
|
5571
|
-
const
|
|
5572
|
-
|
|
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) {
|
|
5573
6334
|
this.failFatal(err instanceof Error ? err : new SubcProviderError(String(err)));
|
|
6335
|
+
}
|
|
5574
6336
|
}).finally(() => {
|
|
5575
|
-
if (this.
|
|
6337
|
+
if (this.isCurrentReconnect(cycle))
|
|
5576
6338
|
this.reconnecting = null;
|
|
5577
6339
|
});
|
|
5578
|
-
this.reconnecting = promise;
|
|
5579
6340
|
}
|
|
5580
|
-
async reconnectWithRetry(
|
|
6341
|
+
async reconnectWithRetry(cycle) {
|
|
5581
6342
|
let attempt = 0;
|
|
5582
6343
|
let delay = this.opts.reconnectBackoff.baseMs;
|
|
5583
6344
|
for (;; ) {
|
|
6345
|
+
if (!this.isCurrentReconnect(cycle))
|
|
6346
|
+
return;
|
|
5584
6347
|
if (this.closeStarted)
|
|
5585
6348
|
throw new SubcProviderError("provider closed");
|
|
6349
|
+
cycle.socket = null;
|
|
6350
|
+
cycle.socketDied = false;
|
|
5586
6351
|
attempt += 1;
|
|
5587
|
-
this.
|
|
6352
|
+
this.enqueueReconnectState(cycle, attempt);
|
|
5588
6353
|
try {
|
|
5589
|
-
const opened = await SubcProvider.openConnection(this.opts)
|
|
5590
|
-
|
|
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) {
|
|
5591
6362
|
opened.sock.close();
|
|
5592
|
-
|
|
6363
|
+
if (this.closeStarted)
|
|
6364
|
+
throw new SubcProviderError("provider closed");
|
|
6365
|
+
return;
|
|
5593
6366
|
}
|
|
5594
|
-
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);
|
|
5595
6373
|
return;
|
|
5596
6374
|
} catch (err) {
|
|
6375
|
+
if (!this.isCurrentReconnect(cycle))
|
|
6376
|
+
return;
|
|
6377
|
+
if (cycle.socket)
|
|
6378
|
+
cycle.socketDied = true;
|
|
5597
6379
|
if (this.closeStarted)
|
|
5598
6380
|
throw err;
|
|
5599
6381
|
if (!isProviderReconnectTransient(err))
|
|
@@ -5603,16 +6385,29 @@ class SubcProvider {
|
|
|
5603
6385
|
}
|
|
5604
6386
|
}
|
|
5605
6387
|
}
|
|
5606
|
-
|
|
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) {
|
|
5607
6400
|
this.sock.close();
|
|
5608
6401
|
this.sock = opened.sock;
|
|
5609
6402
|
this.currentConn = opened.conn;
|
|
5610
6403
|
this.storage = opened.ack.storage;
|
|
5611
6404
|
this.closedErr = null;
|
|
5612
6405
|
this.connectionEpoch += 1;
|
|
5613
|
-
|
|
6406
|
+
this.connectionToken = newConnectionToken();
|
|
6407
|
+
this.liveRoutes.clear();
|
|
6408
|
+
this.nextCorr = 1n;
|
|
5614
6409
|
this.readLoop(opened.sock, generation);
|
|
5615
|
-
|
|
6410
|
+
return this.connectionEpoch;
|
|
5616
6411
|
}
|
|
5617
6412
|
scheduleRestored(generation, epoch) {
|
|
5618
6413
|
if (!this.opts.onConnectionState)
|
|
@@ -5620,7 +6415,7 @@ class SubcProvider {
|
|
|
5620
6415
|
const token = ++this.restoredDebounceToken;
|
|
5621
6416
|
this.opts.sleep(this.opts.restoredDebounceMs).then(() => {
|
|
5622
6417
|
if (token === this.restoredDebounceToken && !this.closeStarted && this.sock && this.generation === generation && this.connectionEpoch === epoch) {
|
|
5623
|
-
this.enqueueConnectionState({ state: "restored", epoch });
|
|
6418
|
+
this.enqueueConnectionState({ state: "restored", epoch }, generation);
|
|
5624
6419
|
}
|
|
5625
6420
|
}).catch((err) => {
|
|
5626
6421
|
if (token === this.restoredDebounceToken && !this.closeStarted) {
|
|
@@ -5631,10 +6426,10 @@ class SubcProvider {
|
|
|
5631
6426
|
cancelRestoredDebounce() {
|
|
5632
6427
|
this.restoredDebounceToken += 1;
|
|
5633
6428
|
}
|
|
5634
|
-
enqueueConnectionState(event) {
|
|
6429
|
+
enqueueConnectionState(event, generation, reconnect) {
|
|
5635
6430
|
if (!this.opts.onConnectionState)
|
|
5636
6431
|
return;
|
|
5637
|
-
this.stateQueue.push(event);
|
|
6432
|
+
this.stateQueue.push({ event, generation, reconnect });
|
|
5638
6433
|
if (!this.drainingStateQueue)
|
|
5639
6434
|
this.drainConnectionStateQueue();
|
|
5640
6435
|
}
|
|
@@ -5644,7 +6439,12 @@ class SubcProvider {
|
|
|
5644
6439
|
this.drainingStateQueue = true;
|
|
5645
6440
|
try {
|
|
5646
6441
|
while (this.stateQueue.length > 0) {
|
|
5647
|
-
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;
|
|
5648
6448
|
try {
|
|
5649
6449
|
await this.opts.onConnectionState?.(event);
|
|
5650
6450
|
this.stateQueue.shift();
|
|
@@ -5664,6 +6464,24 @@ class SubcProvider {
|
|
|
5664
6464
|
this.drainConnectionStateQueue();
|
|
5665
6465
|
}
|
|
5666
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
|
+
}
|
|
5667
6485
|
failFatal(err) {
|
|
5668
6486
|
if (!this.closedErr)
|
|
5669
6487
|
this.closedErr = err;
|
|
@@ -5677,8 +6495,16 @@ class SubcProvider {
|
|
|
5677
6495
|
this.resolveClosed();
|
|
5678
6496
|
}
|
|
5679
6497
|
}
|
|
5680
|
-
function routeKey(
|
|
5681
|
-
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
|
+
}
|
|
5682
6508
|
}
|
|
5683
6509
|
function launchNonce(opts) {
|
|
5684
6510
|
const nonce = opts.launchNonce ?? process.env[SUBC_LAUNCH_NONCE_ENV2];
|
|
@@ -5693,6 +6519,7 @@ function normalizeProviderConnectOptions(opts) {
|
|
|
5693
6519
|
handshakeTimeoutMs: opts.handshakeTimeoutMs,
|
|
5694
6520
|
controlOps: opts.controlOps,
|
|
5695
6521
|
onBind: opts.onBind,
|
|
6522
|
+
onBound: opts.onBound,
|
|
5696
6523
|
onRouteGone: opts.onRouteGone,
|
|
5697
6524
|
reconnectBackoff: opts.reconnectBackoff ?? DEFAULT_RECONNECT_BACKOFF,
|
|
5698
6525
|
sleep: opts.sleep ?? ((ms) => new Promise((resolve7) => setTimeout(resolve7, ms))),
|
|
@@ -5710,7 +6537,7 @@ function normalizedControlOps(controlOps) {
|
|
|
5710
6537
|
}
|
|
5711
6538
|
function buildHelloFrame(opts) {
|
|
5712
6539
|
const nonce = launchNonce(opts);
|
|
5713
|
-
return buildFrame(FrameType.Hello, controlFlags(), 0, HELLO_CORR, encodeJson({
|
|
6540
|
+
return buildFrame(FrameType.Hello, controlFlags(), 0, 0, HELLO_CORR, encodeJson({
|
|
5714
6541
|
manifest: normalizeManifest(opts.manifest),
|
|
5715
6542
|
protocol_ver: PROTOCOL_VERSION,
|
|
5716
6543
|
control_ops: normalizedControlOps(opts.controlOps),
|
|
@@ -5749,14 +6576,17 @@ async function sendFrame(sock, frame) {
|
|
|
5749
6576
|
await sock.write(encodeFrame(frame), Date.now() + WRITE_TIMEOUT_MS);
|
|
5750
6577
|
}
|
|
5751
6578
|
async function expectHelloAck(sock, deadline) {
|
|
5752
|
-
const
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
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
|
+
}
|
|
5758
6588
|
case FrameType.Error: {
|
|
5759
|
-
const error2 = parseJson(body);
|
|
6589
|
+
const error2 = parseJson(frame.body);
|
|
5760
6590
|
throw new SubcProviderError(`subc rejected HELLO: ${error2.code ?? "unknown"} — ${error2.message ?? "subc error"}`, error2.code);
|
|
5761
6591
|
}
|
|
5762
6592
|
default:
|
|
@@ -5903,6 +6733,7 @@ var init_provider = __esm(() => {
|
|
|
5903
6733
|
init_client();
|
|
5904
6734
|
init_connection_file();
|
|
5905
6735
|
init_envelope();
|
|
6736
|
+
init_route_handle();
|
|
5906
6737
|
init_socket();
|
|
5907
6738
|
SubcProviderError = class SubcProviderError extends Error {
|
|
5908
6739
|
code;
|
|
@@ -5913,9 +6744,10 @@ var init_provider = __esm(() => {
|
|
|
5913
6744
|
};
|
|
5914
6745
|
});
|
|
5915
6746
|
|
|
5916
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
6747
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.5.0/node_modules/@cortexkit/subc-client/dist/index.js
|
|
5917
6748
|
var init_dist = __esm(() => {
|
|
5918
6749
|
init_client();
|
|
6750
|
+
init_route_handle();
|
|
5919
6751
|
init_connection_file();
|
|
5920
6752
|
init_envelope();
|
|
5921
6753
|
init_auth();
|
|
@@ -5932,15 +6764,17 @@ class BgSubscription {
|
|
|
5932
6764
|
identity;
|
|
5933
6765
|
acquireClient;
|
|
5934
6766
|
dropClient;
|
|
6767
|
+
consumerIdentity;
|
|
5935
6768
|
onNudge;
|
|
5936
6769
|
sleep;
|
|
5937
6770
|
stopped = false;
|
|
5938
6771
|
current = null;
|
|
5939
6772
|
loop;
|
|
5940
|
-
constructor(identity, acquireClient, dropClient, onNudge, sleep2) {
|
|
6773
|
+
constructor(identity, acquireClient, dropClient, consumerIdentity, onNudge, sleep2) {
|
|
5941
6774
|
this.identity = identity;
|
|
5942
6775
|
this.acquireClient = acquireClient;
|
|
5943
6776
|
this.dropClient = dropClient;
|
|
6777
|
+
this.consumerIdentity = consumerIdentity;
|
|
5944
6778
|
this.onNudge = onNudge;
|
|
5945
6779
|
this.sleep = sleep2;
|
|
5946
6780
|
this.loop = this.run();
|
|
@@ -5969,9 +6803,9 @@ class BgSubscription {
|
|
|
5969
6803
|
}
|
|
5970
6804
|
if (this.stopped)
|
|
5971
6805
|
return;
|
|
5972
|
-
let
|
|
6806
|
+
let route;
|
|
5973
6807
|
try {
|
|
5974
|
-
|
|
6808
|
+
route = await client.routeOpen({ kind: "tool_provider", module_id: AFT_MODULE_ID }, this.identity, { consumerIdentity: this.consumerIdentity });
|
|
5975
6809
|
} catch (err) {
|
|
5976
6810
|
if (isConsumerReconnectTransient(err))
|
|
5977
6811
|
this.dropClient(client);
|
|
@@ -5979,12 +6813,12 @@ class BgSubscription {
|
|
|
5979
6813
|
continue;
|
|
5980
6814
|
}
|
|
5981
6815
|
if (this.stopped) {
|
|
5982
|
-
safeCloseRoute(client,
|
|
6816
|
+
safeCloseRoute(client, route);
|
|
5983
6817
|
return;
|
|
5984
6818
|
}
|
|
5985
6819
|
const subscribedAt = Date.now();
|
|
5986
6820
|
try {
|
|
5987
|
-
const sub = client.subscribe(
|
|
6821
|
+
const sub = client.subscribe(route, { op: "bg_events" }, () => {
|
|
5988
6822
|
if (!this.stopped)
|
|
5989
6823
|
this.onNudge();
|
|
5990
6824
|
});
|
|
@@ -6004,7 +6838,7 @@ class BgSubscription {
|
|
|
6004
6838
|
attempt = 0;
|
|
6005
6839
|
} finally {
|
|
6006
6840
|
this.current = null;
|
|
6007
|
-
safeCloseRoute(client,
|
|
6841
|
+
safeCloseRoute(client, route);
|
|
6008
6842
|
}
|
|
6009
6843
|
await this.backoff(attempt++);
|
|
6010
6844
|
}
|
|
@@ -6017,12 +6851,12 @@ class BgSubscription {
|
|
|
6017
6851
|
function isRecord(value) {
|
|
6018
6852
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6019
6853
|
}
|
|
6020
|
-
function
|
|
6021
|
-
return err instanceof SubcError && err.code === "unknown_channel";
|
|
6854
|
+
function isRouteProvenAbsentError(err) {
|
|
6855
|
+
return err instanceof SubcError && err.code === "unknown_channel" || err instanceof StaleRouteHandleError;
|
|
6022
6856
|
}
|
|
6023
|
-
function safeCloseRoute(client,
|
|
6857
|
+
function safeCloseRoute(client, route) {
|
|
6024
6858
|
try {
|
|
6025
|
-
client.closeRouteChannel(
|
|
6859
|
+
client.closeRouteChannel(route).catch(() => {
|
|
6026
6860
|
return;
|
|
6027
6861
|
});
|
|
6028
6862
|
} catch {}
|
|
@@ -6106,6 +6940,7 @@ class SubcTransportPool {
|
|
|
6106
6940
|
harness;
|
|
6107
6941
|
connectionFile;
|
|
6108
6942
|
handshakeTimeoutMs;
|
|
6943
|
+
consumerIdentity;
|
|
6109
6944
|
connectFn;
|
|
6110
6945
|
onBgEventsNudge;
|
|
6111
6946
|
bgBackoffSleep;
|
|
@@ -6119,6 +6954,7 @@ class SubcTransportPool {
|
|
|
6119
6954
|
this.connectionFile = options.connectionFile;
|
|
6120
6955
|
this.harness = options.harness;
|
|
6121
6956
|
this.handshakeTimeoutMs = options.handshakeTimeoutMs;
|
|
6957
|
+
this.consumerIdentity = options.consumerIdentity;
|
|
6122
6958
|
this.connectFn = options.connect ?? ((opts) => SubcClient.connect(opts));
|
|
6123
6959
|
this.onBgEventsNudge = options.onBgEventsNudge;
|
|
6124
6960
|
this.bgBackoffSleep = options.bgBackoffSleep ?? ((ms) => new Promise((resolve7) => setTimeout(resolve7, ms)));
|
|
@@ -6141,6 +6977,11 @@ class SubcTransportPool {
|
|
|
6141
6977
|
return null;
|
|
6142
6978
|
return this.transports.get(key) ?? null;
|
|
6143
6979
|
}
|
|
6980
|
+
activeBridges() {
|
|
6981
|
+
if (!this.client || this.shuttingDown)
|
|
6982
|
+
return [];
|
|
6983
|
+
return [...this.transports.values()];
|
|
6984
|
+
}
|
|
6144
6985
|
async toolCall(projectRoot, runtime, name, rawArgs = {}, options) {
|
|
6145
6986
|
return this.getBridge(projectRoot).toolCall(runtime.sessionID, name, rawArgs, options);
|
|
6146
6987
|
}
|
|
@@ -6171,7 +7012,7 @@ class SubcTransportPool {
|
|
|
6171
7012
|
throw new RouteTornDownError("subc session closed");
|
|
6172
7013
|
}
|
|
6173
7014
|
try {
|
|
6174
|
-
const opened = await this.
|
|
7015
|
+
const opened = await this.routeHandle(client, identity, record);
|
|
6175
7016
|
if (!this.isCurrentSession(key, record)) {
|
|
6176
7017
|
throw new RouteTornDownError("subc session closed");
|
|
6177
7018
|
}
|
|
@@ -6197,29 +7038,29 @@ class SubcTransportPool {
|
|
|
6197
7038
|
if (isConsumerReconnectTransient(err)) {
|
|
6198
7039
|
this.transportFailures = 0;
|
|
6199
7040
|
this.dropClient(client);
|
|
6200
|
-
} else if (!
|
|
7041
|
+
} else if (!isRouteProvenAbsentError(err) && ++this.transportFailures >= MAX_CONSECUTIVE_TRANSPORT_FAILURES) {
|
|
6201
7042
|
this.transportFailures = 0;
|
|
6202
7043
|
this.dropClient(client);
|
|
6203
7044
|
}
|
|
6204
7045
|
}
|
|
6205
7046
|
};
|
|
6206
|
-
const requestOnRoute = async (
|
|
6207
|
-
const reply = await client.request(
|
|
7047
|
+
const requestOnRoute = async (route2) => {
|
|
7048
|
+
const reply = await client.request(route2, body, { timeoutMs, onProgress });
|
|
6208
7049
|
if (this.isCurrentSession(key, record) && this.client === client) {
|
|
6209
7050
|
this.transportFailures = 0;
|
|
6210
7051
|
}
|
|
6211
7052
|
this.ensureBgSubscription(identity, record);
|
|
6212
7053
|
return reply;
|
|
6213
7054
|
};
|
|
6214
|
-
let {
|
|
7055
|
+
let { route, entry } = await openRoute();
|
|
6215
7056
|
try {
|
|
6216
|
-
return await requestOnRoute(
|
|
7057
|
+
return await requestOnRoute(route);
|
|
6217
7058
|
} catch (err) {
|
|
6218
|
-
if (
|
|
7059
|
+
if (isRouteProvenAbsentError(err) && this.isCurrentSession(key, record) && this.client === client) {
|
|
6219
7060
|
clearRouteEntry(entry);
|
|
6220
|
-
({
|
|
7061
|
+
({ route, entry } = await openRoute());
|
|
6221
7062
|
try {
|
|
6222
|
-
return await requestOnRoute(
|
|
7063
|
+
return await requestOnRoute(route);
|
|
6223
7064
|
} catch (retryErr) {
|
|
6224
7065
|
handleRequestFailure(retryErr, entry);
|
|
6225
7066
|
throw retryErr;
|
|
@@ -6261,24 +7102,26 @@ class SubcTransportPool {
|
|
|
6261
7102
|
});
|
|
6262
7103
|
return this.connecting;
|
|
6263
7104
|
}
|
|
6264
|
-
async
|
|
7105
|
+
async routeHandle(client, identity, record) {
|
|
6265
7106
|
const key = identityKey(identity);
|
|
6266
7107
|
const existing = record.routeEntry;
|
|
6267
|
-
if (existing?.
|
|
6268
|
-
return {
|
|
7108
|
+
if (existing?.handle != null)
|
|
7109
|
+
return { route: existing.handle, entry: existing };
|
|
6269
7110
|
if (existing?.opening)
|
|
6270
|
-
return {
|
|
6271
|
-
const entry = { client, opening: null,
|
|
6272
|
-
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) => {
|
|
6273
7116
|
if (!this.isCurrentSession(key, record) || record.routeEntry !== entry || entry.closed || this.client !== client) {
|
|
6274
|
-
safeCloseRoute(client,
|
|
7117
|
+
safeCloseRoute(client, route);
|
|
6275
7118
|
if (record.routeEntry === entry)
|
|
6276
7119
|
record.routeEntry = null;
|
|
6277
7120
|
throw new RouteTornDownError("subc route opened after teardown");
|
|
6278
7121
|
}
|
|
6279
|
-
entry.
|
|
7122
|
+
entry.handle = route;
|
|
6280
7123
|
entry.opening = null;
|
|
6281
|
-
return
|
|
7124
|
+
return route;
|
|
6282
7125
|
}).catch((err) => {
|
|
6283
7126
|
const current = this.isCurrentSession(key, record);
|
|
6284
7127
|
if (record.routeEntry === entry) {
|
|
@@ -6292,7 +7135,7 @@ class SubcTransportPool {
|
|
|
6292
7135
|
});
|
|
6293
7136
|
entry.opening = opening;
|
|
6294
7137
|
record.routeEntry = entry;
|
|
6295
|
-
return {
|
|
7138
|
+
return { route: await opening, entry };
|
|
6296
7139
|
}
|
|
6297
7140
|
ensureBgSubscription(identity, record) {
|
|
6298
7141
|
if (this.shuttingDown || !this.onBgEventsNudge)
|
|
@@ -6303,7 +7146,7 @@ class SubcTransportPool {
|
|
|
6303
7146
|
if (record.bgSub)
|
|
6304
7147
|
return;
|
|
6305
7148
|
const onNudge = () => this.onBgEventsNudge?.(identity.project_root, identity.session);
|
|
6306
|
-
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);
|
|
6307
7150
|
record.bgSub = sub;
|
|
6308
7151
|
}
|
|
6309
7152
|
dropClient(client) {
|
|
@@ -6324,9 +7167,13 @@ class SubcTransportPool {
|
|
|
6324
7167
|
}
|
|
6325
7168
|
}
|
|
6326
7169
|
setConfigureOverride(_key, _value) {}
|
|
7170
|
+
async reconfigure(_projectRoot, _overrides) {}
|
|
6327
7171
|
async replaceBinary(path2) {
|
|
6328
7172
|
return path2;
|
|
6329
7173
|
}
|
|
7174
|
+
isShutdown() {
|
|
7175
|
+
return this.shuttingDown;
|
|
7176
|
+
}
|
|
6330
7177
|
async shutdown() {
|
|
6331
7178
|
this.shuttingDown = true;
|
|
6332
7179
|
const subs = [];
|
|
@@ -6350,10 +7197,10 @@ class SubcTransportPool {
|
|
|
6350
7197
|
this.transports.clear();
|
|
6351
7198
|
await Promise.allSettled(subs.map((sub) => sub.stop()));
|
|
6352
7199
|
await Promise.allSettled(entries.map(async (entry) => {
|
|
6353
|
-
if (entry.
|
|
7200
|
+
if (entry.handle == null)
|
|
6354
7201
|
return;
|
|
6355
7202
|
try {
|
|
6356
|
-
await entry.client.closeRouteChannel(entry.
|
|
7203
|
+
await entry.client.closeRouteChannel(entry.handle);
|
|
6357
7204
|
} catch {}
|
|
6358
7205
|
}));
|
|
6359
7206
|
if (client) {
|
|
@@ -6382,9 +7229,9 @@ class SubcTransportPool {
|
|
|
6382
7229
|
entry.closed = true;
|
|
6383
7230
|
if (sub)
|
|
6384
7231
|
await sub.stop();
|
|
6385
|
-
if (entry?.
|
|
7232
|
+
if (entry?.handle != null) {
|
|
6386
7233
|
try {
|
|
6387
|
-
await entry.client.closeRouteChannel(entry.
|
|
7234
|
+
await entry.client.closeRouteChannel(entry.handle);
|
|
6388
7235
|
} catch {}
|
|
6389
7236
|
}
|
|
6390
7237
|
}
|
|
@@ -6485,18 +7332,25 @@ function formatReadFooter(agentSpecifiedRange, data, options) {
|
|
|
6485
7332
|
}
|
|
6486
7333
|
|
|
6487
7334
|
// ../aft-bridge/dist/transport-factory.js
|
|
6488
|
-
import { homedir as
|
|
6489
|
-
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";
|
|
6490
7337
|
function resolveConnectionFilePath(raw) {
|
|
6491
7338
|
const trimmed = raw.trim();
|
|
6492
7339
|
if (trimmed.startsWith("~")) {
|
|
6493
|
-
return
|
|
7340
|
+
return join10(homedir11(), trimmed.slice(1).replace(/^[/\\]/, ""));
|
|
6494
7341
|
}
|
|
6495
7342
|
if (isAbsolute5(trimmed))
|
|
6496
7343
|
return trimmed;
|
|
6497
|
-
return
|
|
7344
|
+
return join10(homedir11(), trimmed);
|
|
6498
7345
|
}
|
|
6499
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) {
|
|
6500
7354
|
const raw = opts.subcConnectionFile?.trim();
|
|
6501
7355
|
if (raw && raw.length > 0) {
|
|
6502
7356
|
const connectionFile = resolveConnectionFilePath(raw);
|
|
@@ -6507,6 +7361,7 @@ async function createAftTransportPool(opts) {
|
|
|
6507
7361
|
return new SubcTransportPool({
|
|
6508
7362
|
connectionFile,
|
|
6509
7363
|
harness: opts.harness,
|
|
7364
|
+
consumerIdentity: opts.subcConsumerIdentity,
|
|
6510
7365
|
onBgEventsNudge: opts.onBgEventsNudge
|
|
6511
7366
|
});
|
|
6512
7367
|
}
|
|
@@ -6514,6 +7369,7 @@ async function createAftTransportPool(opts) {
|
|
|
6514
7369
|
}
|
|
6515
7370
|
var init_transport_factory = __esm(() => {
|
|
6516
7371
|
init_pool();
|
|
7372
|
+
init_revivable_transport();
|
|
6517
7373
|
init_subc_transport();
|
|
6518
7374
|
});
|
|
6519
7375
|
|
|
@@ -6631,6 +7487,7 @@ __export(exports_dist, {
|
|
|
6631
7487
|
timeoutForCommand: () => timeoutForCommand,
|
|
6632
7488
|
tagStderrLine: () => tagStderrLine,
|
|
6633
7489
|
stripJsoncSymbols: () => stripJsoncSymbols,
|
|
7490
|
+
stripHarnessSpecificConfigKeys: () => stripHarnessSpecificConfigKeys,
|
|
6634
7491
|
statusBarLine: () => statusBarLine,
|
|
6635
7492
|
sleep: () => sleep,
|
|
6636
7493
|
shouldShowAnnouncement: () => shouldShowAnnouncement,
|
|
@@ -6645,6 +7502,8 @@ __export(exports_dist, {
|
|
|
6645
7502
|
resolveCortexKitProjectConfigPath: () => resolveCortexKitProjectConfigPath,
|
|
6646
7503
|
resolveCortexKitConfigPaths: () => resolveCortexKitConfigPaths,
|
|
6647
7504
|
resolveBashKillTimeout: () => resolveBashKillTimeout,
|
|
7505
|
+
resolveAftStorageRoot: () => resolveAftStorageRoot,
|
|
7506
|
+
resolveAftLogPath: () => resolveAftLogPath,
|
|
6648
7507
|
repairRootScopedStorageFile: () => repairRootScopedStorageFile,
|
|
6649
7508
|
readConfigTiers: () => readConfigTiers,
|
|
6650
7509
|
projectRootKeyHash: () => projectRootKeyHash,
|
|
@@ -6702,11 +7561,17 @@ __export(exports_dist, {
|
|
|
6702
7561
|
__onnxTest__: () => __test__,
|
|
6703
7562
|
SubcTransportPool: () => SubcTransportPool,
|
|
6704
7563
|
STATUS_BAR_HEARTBEAT_CALLS: () => STATUS_BAR_HEARTBEAT_CALLS,
|
|
7564
|
+
RotatingLogSink: () => RotatingLogSink,
|
|
7565
|
+
RevivableTransportPool: () => RevivableTransportPool,
|
|
6705
7566
|
PLATFORM_ASSET_MAP: () => PLATFORM_ASSET_MAP,
|
|
6706
7567
|
PLATFORM_ARCH_MAP: () => PLATFORM_ARCH_MAP,
|
|
6707
7568
|
PLAIN_CALLGRAPH_THEME: () => PLAIN_CALLGRAPH_THEME,
|
|
7569
|
+
PI_ONLY_KEYS: () => PI_ONLY_KEYS,
|
|
7570
|
+
OPENCODE_ONLY_KEYS: () => OPENCODE_ONLY_KEYS,
|
|
6708
7571
|
LONG_RUNNING_COMMAND_TIMEOUT_MS: () => LONG_RUNNING_COMMAND_TIMEOUT_MS,
|
|
6709
7572
|
HomeProjectRootError: () => HomeProjectRootError,
|
|
7573
|
+
DEFAULT_LOG_GENERATIONS: () => DEFAULT_LOG_GENERATIONS,
|
|
7574
|
+
DEFAULT_LOG_BYTES: () => DEFAULT_LOG_BYTES,
|
|
6710
7575
|
BridgeTransportTimeoutError: () => BridgeTransportTimeoutError,
|
|
6711
7576
|
BridgePool: () => BridgePool,
|
|
6712
7577
|
BinaryBridge: () => BinaryBridge
|
|
@@ -6717,8 +7582,10 @@ var init_dist2 = __esm(() => {
|
|
|
6717
7582
|
init_bridge();
|
|
6718
7583
|
init_callgraph_format();
|
|
6719
7584
|
init_command_timeouts();
|
|
7585
|
+
init_config_keys();
|
|
6720
7586
|
init_config_tiers();
|
|
6721
7587
|
init_downloader();
|
|
7588
|
+
init_durable_log();
|
|
6722
7589
|
init_migration();
|
|
6723
7590
|
init_npm_resolver();
|
|
6724
7591
|
init_onnx_runtime();
|
|
@@ -6727,70 +7594,70 @@ var init_dist2 = __esm(() => {
|
|
|
6727
7594
|
init_pool();
|
|
6728
7595
|
init_project_identity();
|
|
6729
7596
|
init_resolver();
|
|
7597
|
+
init_revivable_transport();
|
|
6730
7598
|
init_subc_transport();
|
|
6731
7599
|
init_transport_factory();
|
|
6732
7600
|
});
|
|
6733
7601
|
|
|
6734
7602
|
// src/lib/paths.ts
|
|
6735
|
-
import { homedir as
|
|
6736
|
-
import { join as
|
|
7603
|
+
import { homedir as homedir12 } from "node:os";
|
|
7604
|
+
import { join as join11 } from "node:path";
|
|
6737
7605
|
function getAftBinaryCacheDir() {
|
|
6738
7606
|
if (process.env.AFT_CACHE_DIR) {
|
|
6739
|
-
return
|
|
7607
|
+
return join11(process.env.AFT_CACHE_DIR, "bin");
|
|
6740
7608
|
}
|
|
6741
7609
|
if (process.platform === "win32") {
|
|
6742
7610
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
6743
|
-
const base2 = localAppData ||
|
|
6744
|
-
return
|
|
7611
|
+
const base2 = localAppData || join11(homedir12(), "AppData", "Local");
|
|
7612
|
+
return join11(base2, "aft", "bin");
|
|
6745
7613
|
}
|
|
6746
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
6747
|
-
return
|
|
7614
|
+
const base = process.env.XDG_CACHE_HOME || join11(homedir12(), ".cache");
|
|
7615
|
+
return join11(base, "aft", "bin");
|
|
6748
7616
|
}
|
|
6749
7617
|
function getAftBinaryName() {
|
|
6750
7618
|
return process.platform === "win32" ? "aft.exe" : "aft";
|
|
6751
7619
|
}
|
|
6752
7620
|
function getAftLspPackagesDir() {
|
|
6753
7621
|
if (process.env.AFT_CACHE_DIR) {
|
|
6754
|
-
return
|
|
7622
|
+
return join11(process.env.AFT_CACHE_DIR, "lsp-packages");
|
|
6755
7623
|
}
|
|
6756
7624
|
if (process.platform === "win32") {
|
|
6757
7625
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
6758
|
-
const base2 = localAppData ||
|
|
6759
|
-
return
|
|
7626
|
+
const base2 = localAppData || join11(homedir12(), "AppData", "Local");
|
|
7627
|
+
return join11(base2, "aft", "lsp-packages");
|
|
6760
7628
|
}
|
|
6761
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
6762
|
-
return
|
|
7629
|
+
const base = process.env.XDG_CACHE_HOME || join11(homedir12(), ".cache");
|
|
7630
|
+
return join11(base, "aft", "lsp-packages");
|
|
6763
7631
|
}
|
|
6764
7632
|
function getAftLspBinariesDir() {
|
|
6765
7633
|
if (process.env.AFT_CACHE_DIR) {
|
|
6766
|
-
return
|
|
7634
|
+
return join11(process.env.AFT_CACHE_DIR, "lsp-binaries");
|
|
6767
7635
|
}
|
|
6768
7636
|
if (process.platform === "win32") {
|
|
6769
7637
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
6770
|
-
const base2 = localAppData ||
|
|
6771
|
-
return
|
|
7638
|
+
const base2 = localAppData || join11(homedir12(), "AppData", "Local");
|
|
7639
|
+
return join11(base2, "aft", "lsp-binaries");
|
|
6772
7640
|
}
|
|
6773
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
6774
|
-
return
|
|
7641
|
+
const base = process.env.XDG_CACHE_HOME || join11(homedir12(), ".cache");
|
|
7642
|
+
return join11(base, "aft", "lsp-binaries");
|
|
6775
7643
|
}
|
|
6776
|
-
function
|
|
7644
|
+
function homeDir4() {
|
|
6777
7645
|
if (process.platform === "win32")
|
|
6778
|
-
return process.env.USERPROFILE || process.env.HOME ||
|
|
6779
|
-
return process.env.HOME ||
|
|
7646
|
+
return process.env.USERPROFILE || process.env.HOME || homedir12();
|
|
7647
|
+
return process.env.HOME || homedir12();
|
|
6780
7648
|
}
|
|
6781
|
-
function
|
|
7649
|
+
function dataHome3() {
|
|
6782
7650
|
if (process.env.XDG_DATA_HOME)
|
|
6783
7651
|
return process.env.XDG_DATA_HOME;
|
|
6784
7652
|
if (process.platform === "win32") {
|
|
6785
|
-
return process.env.LOCALAPPDATA || process.env.APPDATA ||
|
|
7653
|
+
return process.env.LOCALAPPDATA || process.env.APPDATA || join11(homeDir4(), "AppData", "Local");
|
|
6786
7654
|
}
|
|
6787
|
-
return
|
|
7655
|
+
return join11(homeDir4(), ".local", "share");
|
|
6788
7656
|
}
|
|
6789
7657
|
function getCortexKitStorageRoot() {
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
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");
|
|
6794
7661
|
}
|
|
6795
7662
|
var init_paths2 = () => {};
|
|
6796
7663
|
|
|
@@ -6798,8 +7665,8 @@ var init_paths2 = () => {};
|
|
|
6798
7665
|
import { execSync as execSync2, spawnSync as spawnSync3 } from "node:child_process";
|
|
6799
7666
|
import { existsSync as existsSync7 } from "node:fs";
|
|
6800
7667
|
import { createRequire as createRequire2 } from "node:module";
|
|
6801
|
-
import { homedir as
|
|
6802
|
-
import { join as
|
|
7668
|
+
import { homedir as homedir13 } from "node:os";
|
|
7669
|
+
import { join as join12 } from "node:path";
|
|
6803
7670
|
async function loadPluginVersion() {
|
|
6804
7671
|
try {
|
|
6805
7672
|
const bridge = await Promise.resolve().then(() => (init_dist2(), exports_dist));
|
|
@@ -6921,7 +7788,7 @@ function aftBinaryCandidates(preferredVersion) {
|
|
|
6921
7788
|
const candidates = [];
|
|
6922
7789
|
if (preferredVersion) {
|
|
6923
7790
|
const tag = preferredVersion.startsWith("v") ? preferredVersion : `v${preferredVersion}`;
|
|
6924
|
-
pushCandidate(candidates,
|
|
7791
|
+
pushCandidate(candidates, join12(getAftBinaryCacheDir(), tag, getAftBinaryName()));
|
|
6925
7792
|
}
|
|
6926
7793
|
const key = platformKey2();
|
|
6927
7794
|
if (key) {
|
|
@@ -6944,7 +7811,7 @@ function aftBinaryCandidates(preferredVersion) {
|
|
|
6944
7811
|
}
|
|
6945
7812
|
}
|
|
6946
7813
|
} catch {}
|
|
6947
|
-
pushCandidate(candidates,
|
|
7814
|
+
pushCandidate(candidates, join12(homedir13(), ".cargo", "bin", getAftBinaryName()));
|
|
6948
7815
|
return candidates;
|
|
6949
7816
|
}
|
|
6950
7817
|
function findAftBinary(preferredVersion) {
|
|
@@ -6960,21 +7827,21 @@ var init_binary_probe = __esm(async () => {
|
|
|
6960
7827
|
|
|
6961
7828
|
// src/lib/fs-util.ts
|
|
6962
7829
|
import { existsSync as existsSync8, readdirSync as readdirSync3, statSync as statSync5 } from "node:fs";
|
|
6963
|
-
import { join as
|
|
7830
|
+
import { join as join13 } from "node:path";
|
|
6964
7831
|
function dirSize(path2) {
|
|
6965
7832
|
if (!existsSync8(path2)) {
|
|
6966
7833
|
return 0;
|
|
6967
7834
|
}
|
|
6968
|
-
const
|
|
6969
|
-
if (
|
|
6970
|
-
return
|
|
7835
|
+
const stat2 = statSync5(path2);
|
|
7836
|
+
if (stat2.isFile()) {
|
|
7837
|
+
return stat2.size;
|
|
6971
7838
|
}
|
|
6972
|
-
if (!
|
|
7839
|
+
if (!stat2.isDirectory()) {
|
|
6973
7840
|
return 0;
|
|
6974
7841
|
}
|
|
6975
7842
|
let total = 0;
|
|
6976
7843
|
for (const entry of readdirSync3(path2)) {
|
|
6977
|
-
total += dirSize(
|
|
7844
|
+
total += dirSize(join13(path2, entry));
|
|
6978
7845
|
}
|
|
6979
7846
|
return total;
|
|
6980
7847
|
}
|
|
@@ -14597,10 +15464,10 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
14597
15464
|
replacer = null;
|
|
14598
15465
|
indent = EMPTY;
|
|
14599
15466
|
};
|
|
14600
|
-
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;
|
|
14601
15468
|
var join_content = (inside, value, gap) => {
|
|
14602
15469
|
const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
|
|
14603
|
-
return
|
|
15470
|
+
return join14(comment, inside, gap);
|
|
14604
15471
|
};
|
|
14605
15472
|
var stringify_string = (holder, key, value) => {
|
|
14606
15473
|
const raw = get_raw_string_literal(holder, key);
|
|
@@ -14622,13 +15489,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
14622
15489
|
if (i !== 0) {
|
|
14623
15490
|
inside += COMMA;
|
|
14624
15491
|
}
|
|
14625
|
-
const before =
|
|
15492
|
+
const before = join14(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
|
|
14626
15493
|
inside += before || LF + deeper_gap;
|
|
14627
15494
|
inside += stringify(i, value, deeper_gap) || STR_NULL;
|
|
14628
15495
|
inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
|
|
14629
15496
|
after_comma = process_comments(value, AFTER(i), deeper_gap);
|
|
14630
15497
|
}
|
|
14631
|
-
inside +=
|
|
15498
|
+
inside += join14(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
14632
15499
|
return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
|
|
14633
15500
|
};
|
|
14634
15501
|
var object_stringify = (value, gap) => {
|
|
@@ -14649,13 +15516,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
14649
15516
|
inside += COMMA;
|
|
14650
15517
|
}
|
|
14651
15518
|
first = false;
|
|
14652
|
-
const before =
|
|
15519
|
+
const before = join14(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
|
|
14653
15520
|
inside += before || LF + deeper_gap;
|
|
14654
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);
|
|
14655
15522
|
after_comma = process_comments(value, AFTER(key), deeper_gap);
|
|
14656
15523
|
};
|
|
14657
15524
|
keys.forEach(iteratee);
|
|
14658
|
-
inside +=
|
|
15525
|
+
inside += join14(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
14659
15526
|
return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
|
|
14660
15527
|
};
|
|
14661
15528
|
function stringify(key, holder, gap) {
|
|
@@ -14749,7 +15616,7 @@ var require_src2 = __commonJS((exports, module) => {
|
|
|
14749
15616
|
|
|
14750
15617
|
// src/lib/jsonc.ts
|
|
14751
15618
|
import { existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
|
|
14752
|
-
import { dirname as
|
|
15619
|
+
import { dirname as dirname6 } from "node:path";
|
|
14753
15620
|
function detectJsoncFile(configDir, baseName) {
|
|
14754
15621
|
const jsoncPath = `${configDir}/${baseName}.jsonc`;
|
|
14755
15622
|
const jsonPath = `${configDir}/${baseName}.json`;
|
|
@@ -14777,7 +15644,7 @@ function readJsoncFile(path2) {
|
|
|
14777
15644
|
}
|
|
14778
15645
|
}
|
|
14779
15646
|
function writeJsoncFile(path2, value, format = "json") {
|
|
14780
|
-
mkdirSync6(
|
|
15647
|
+
mkdirSync6(dirname6(path2), { recursive: true });
|
|
14781
15648
|
const serialized = format === "jsonc" ? import_comment_json.stringify(value, null, 2) : JSON.stringify(value, null, 2);
|
|
14782
15649
|
writeFileSync4(path2, `${serialized}
|
|
14783
15650
|
`);
|
|
@@ -14837,25 +15704,25 @@ var init_self_version = () => {};
|
|
|
14837
15704
|
// src/adapters/opencode.ts
|
|
14838
15705
|
import { execSync as execSync3 } from "node:child_process";
|
|
14839
15706
|
import { existsSync as existsSync10, readFileSync as readFileSync8, rmSync as rmSync4, statSync as statSync6 } from "node:fs";
|
|
14840
|
-
import { homedir as
|
|
14841
|
-
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";
|
|
14842
15709
|
import { fileURLToPath } from "node:url";
|
|
14843
15710
|
function getOpenCodeConfigDir() {
|
|
14844
15711
|
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
14845
15712
|
if (envDir)
|
|
14846
15713
|
return resolve7(envDir);
|
|
14847
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
14848
|
-
return
|
|
15714
|
+
const xdg = process.env.XDG_CONFIG_HOME || join14(homedir14(), ".config");
|
|
15715
|
+
return join14(xdg, "opencode");
|
|
14849
15716
|
}
|
|
14850
15717
|
function getOpenCodeCacheDir() {
|
|
14851
15718
|
const xdg = process.env.XDG_CACHE_HOME;
|
|
14852
15719
|
if (xdg)
|
|
14853
|
-
return
|
|
15720
|
+
return join14(xdg, "opencode");
|
|
14854
15721
|
if (process.platform === "win32") {
|
|
14855
|
-
const localAppData = process.env.LOCALAPPDATA ??
|
|
14856
|
-
return
|
|
15722
|
+
const localAppData = process.env.LOCALAPPDATA ?? join14(homedir14(), "AppData", "Local");
|
|
15723
|
+
return join14(localAppData, "opencode");
|
|
14857
15724
|
}
|
|
14858
|
-
return
|
|
15725
|
+
return join14(homedir14(), ".cache", "opencode");
|
|
14859
15726
|
}
|
|
14860
15727
|
function hasOpenCodeCli() {
|
|
14861
15728
|
try {
|
|
@@ -14868,12 +15735,12 @@ function hasOpenCodeCli() {
|
|
|
14868
15735
|
function openCodeDesktopAppExists() {
|
|
14869
15736
|
const candidates = [];
|
|
14870
15737
|
if (process.platform === "darwin") {
|
|
14871
|
-
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"));
|
|
14872
15739
|
} else if (process.platform === "win32") {
|
|
14873
|
-
const localAppData = process.env.LOCALAPPDATA ??
|
|
14874
|
-
candidates.push(
|
|
15740
|
+
const localAppData = process.env.LOCALAPPDATA ?? join14(homedir14(), "AppData", "Local");
|
|
15741
|
+
candidates.push(join14(localAppData, "Programs", "opencode"), join14(localAppData, "opencode"));
|
|
14875
15742
|
} else {
|
|
14876
|
-
candidates.push("/opt/OpenCode", "/usr/lib/opencode",
|
|
15743
|
+
candidates.push("/opt/OpenCode", "/usr/lib/opencode", join14(homedir14(), ".local", "share", "applications", "opencode.desktop"));
|
|
14877
15744
|
}
|
|
14878
15745
|
return candidates.some((p) => {
|
|
14879
15746
|
try {
|
|
@@ -14902,15 +15769,15 @@ function pathPointsToOurPlugin(entry) {
|
|
|
14902
15769
|
try {
|
|
14903
15770
|
if (!existsSync10(fsPath))
|
|
14904
15771
|
return false;
|
|
14905
|
-
let searchDir = statSync6(fsPath).isDirectory() ? fsPath :
|
|
15772
|
+
let searchDir = statSync6(fsPath).isDirectory() ? fsPath : dirname7(fsPath);
|
|
14906
15773
|
let pkgJsonPath = null;
|
|
14907
15774
|
while (true) {
|
|
14908
|
-
const candidate =
|
|
15775
|
+
const candidate = join14(searchDir, "package.json");
|
|
14909
15776
|
if (existsSync10(candidate)) {
|
|
14910
15777
|
pkgJsonPath = candidate;
|
|
14911
15778
|
break;
|
|
14912
15779
|
}
|
|
14913
|
-
const parent =
|
|
15780
|
+
const parent = dirname7(searchDir);
|
|
14914
15781
|
if (parent === searchDir || searchDir === parse(searchDir).root)
|
|
14915
15782
|
break;
|
|
14916
15783
|
searchDir = parent;
|
|
@@ -15076,10 +15943,10 @@ class OpenCodeAdapter {
|
|
|
15076
15943
|
};
|
|
15077
15944
|
}
|
|
15078
15945
|
getPluginCacheInfo() {
|
|
15079
|
-
const path2 =
|
|
15946
|
+
const path2 = join14(getOpenCodeCacheDir(), "packages", PLUGIN_ENTRY);
|
|
15080
15947
|
let cached;
|
|
15081
15948
|
try {
|
|
15082
|
-
const installedPkgPath =
|
|
15949
|
+
const installedPkgPath = join14(path2, "node_modules", "@cortexkit", "aft-opencode", "package.json");
|
|
15083
15950
|
if (existsSync10(installedPkgPath)) {
|
|
15084
15951
|
const pkg = JSON.parse(readFileSync8(installedPkgPath, "utf-8"));
|
|
15085
15952
|
cached = typeof pkg.version === "string" ? pkg.version : undefined;
|
|
@@ -15098,7 +15965,7 @@ class OpenCodeAdapter {
|
|
|
15098
15965
|
return getCortexKitStorageRoot();
|
|
15099
15966
|
}
|
|
15100
15967
|
getLogFile() {
|
|
15101
|
-
return
|
|
15968
|
+
return resolveAftLogPath("aft-plugin.log");
|
|
15102
15969
|
}
|
|
15103
15970
|
getInstallHint() {
|
|
15104
15971
|
return "Install OpenCode: https://opencode.ai/docs/install";
|
|
@@ -15140,11 +16007,11 @@ class OpenCodeAdapter {
|
|
|
15140
16007
|
describeStorageSubtrees() {
|
|
15141
16008
|
const storage = this.getStorageDir();
|
|
15142
16009
|
return {
|
|
15143
|
-
index: dirSize(
|
|
15144
|
-
semantic: dirSize(
|
|
15145
|
-
backups: dirSize(
|
|
15146
|
-
url_cache: dirSize(
|
|
15147
|
-
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"))
|
|
15148
16015
|
};
|
|
15149
16016
|
}
|
|
15150
16017
|
}
|
|
@@ -15161,15 +16028,15 @@ var init_opencode = __esm(() => {
|
|
|
15161
16028
|
// src/adapters/pi.ts
|
|
15162
16029
|
import { execSync as execSync4, spawnSync as spawnSync4 } from "node:child_process";
|
|
15163
16030
|
import { existsSync as existsSync11, readFileSync as readFileSync9 } from "node:fs";
|
|
15164
|
-
import { homedir as
|
|
15165
|
-
import { join as
|
|
16031
|
+
import { homedir as homedir15 } from "node:os";
|
|
16032
|
+
import { join as join15 } from "node:path";
|
|
15166
16033
|
function getPiAgentDir() {
|
|
15167
16034
|
const envHome = process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME;
|
|
15168
|
-
const home = envHome && envHome.length > 0 ? envHome :
|
|
15169
|
-
return
|
|
16035
|
+
const home = envHome && envHome.length > 0 ? envHome : homedir15();
|
|
16036
|
+
return join15(home, ".pi", "agent");
|
|
15170
16037
|
}
|
|
15171
16038
|
function readPiExtensionIndex() {
|
|
15172
|
-
const settingsPath =
|
|
16039
|
+
const settingsPath = join15(getPiAgentDir(), "settings.json");
|
|
15173
16040
|
if (existsSync11(settingsPath)) {
|
|
15174
16041
|
try {
|
|
15175
16042
|
const raw = readFileSync9(settingsPath, "utf-8");
|
|
@@ -15183,10 +16050,10 @@ function readPiExtensionIndex() {
|
|
|
15183
16050
|
} catch {}
|
|
15184
16051
|
}
|
|
15185
16052
|
const candidates = [
|
|
15186
|
-
|
|
15187
|
-
|
|
15188
|
-
|
|
15189
|
-
|
|
16053
|
+
join15(getPiAgentDir(), "extensions.json"),
|
|
16054
|
+
join15(getPiAgentDir(), "extensions.jsonc"),
|
|
16055
|
+
join15(getPiAgentDir(), "config.json"),
|
|
16056
|
+
join15(getPiAgentDir(), "config.jsonc")
|
|
15190
16057
|
];
|
|
15191
16058
|
for (const path2 of candidates) {
|
|
15192
16059
|
if (!existsSync11(path2))
|
|
@@ -15222,14 +16089,14 @@ function piEntryMatchesAft(entry) {
|
|
|
15222
16089
|
} else if (entry.startsWith("/")) {
|
|
15223
16090
|
resolved = entry;
|
|
15224
16091
|
} else if (entry.length > 0) {
|
|
15225
|
-
resolved =
|
|
16092
|
+
resolved = join15(getPiAgentDir(), entry);
|
|
15226
16093
|
}
|
|
15227
16094
|
if (!resolved)
|
|
15228
16095
|
return false;
|
|
15229
16096
|
try {
|
|
15230
16097
|
if (!existsSync11(resolved))
|
|
15231
16098
|
return false;
|
|
15232
|
-
const pkgPath =
|
|
16099
|
+
const pkgPath = join15(resolved, "package.json");
|
|
15233
16100
|
if (!existsSync11(pkgPath))
|
|
15234
16101
|
return false;
|
|
15235
16102
|
const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
|
|
@@ -15281,7 +16148,7 @@ class PiAdapter {
|
|
|
15281
16148
|
const aftConfigExists = existsSync11(aftConfigPath);
|
|
15282
16149
|
return {
|
|
15283
16150
|
configDir,
|
|
15284
|
-
harnessConfig: index.path ??
|
|
16151
|
+
harnessConfig: index.path ?? join15(configDir, "extensions.json"),
|
|
15285
16152
|
harnessConfigFormat: index.path ? "json" : "none",
|
|
15286
16153
|
aftConfig: aftConfigPath,
|
|
15287
16154
|
aftConfigFormat: aftConfigExists ? "jsonc" : "none"
|
|
@@ -15326,8 +16193,8 @@ class PiAdapter {
|
|
|
15326
16193
|
}
|
|
15327
16194
|
getPluginCacheInfo() {
|
|
15328
16195
|
const candidates = [
|
|
15329
|
-
|
|
15330
|
-
|
|
16196
|
+
join15(getPiAgentDir(), "node_modules", "@cortexkit", "aft-pi", "package.json"),
|
|
16197
|
+
join15(getPiAgentDir(), "extensions", "node_modules", "@cortexkit", "aft-pi", "package.json")
|
|
15331
16198
|
];
|
|
15332
16199
|
for (const candidate of candidates) {
|
|
15333
16200
|
if (!existsSync11(candidate))
|
|
@@ -15344,7 +16211,7 @@ class PiAdapter {
|
|
|
15344
16211
|
} catch {}
|
|
15345
16212
|
}
|
|
15346
16213
|
return {
|
|
15347
|
-
path:
|
|
16214
|
+
path: join15(getPiAgentDir(), "extensions"),
|
|
15348
16215
|
exists: false
|
|
15349
16216
|
};
|
|
15350
16217
|
}
|
|
@@ -15352,7 +16219,7 @@ class PiAdapter {
|
|
|
15352
16219
|
return getCortexKitStorageRoot();
|
|
15353
16220
|
}
|
|
15354
16221
|
getLogFile() {
|
|
15355
|
-
return
|
|
16222
|
+
return resolveAftLogPath("aft-plugin.log");
|
|
15356
16223
|
}
|
|
15357
16224
|
getInstallHint() {
|
|
15358
16225
|
return "Install Pi: https://github.com/badlogic/pi-mono";
|
|
@@ -15366,11 +16233,11 @@ class PiAdapter {
|
|
|
15366
16233
|
describeStorageSubtrees() {
|
|
15367
16234
|
const storage = this.getStorageDir();
|
|
15368
16235
|
return {
|
|
15369
|
-
index: dirSize(
|
|
15370
|
-
semantic: dirSize(
|
|
15371
|
-
backups: dirSize(
|
|
15372
|
-
url_cache: dirSize(
|
|
15373
|
-
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"))
|
|
15374
16241
|
};
|
|
15375
16242
|
}
|
|
15376
16243
|
}
|
|
@@ -17394,28 +18261,30 @@ var init_aft_bridge = () => {};
|
|
|
17394
18261
|
// src/commands/lsp.ts
|
|
17395
18262
|
var exports_lsp = {};
|
|
17396
18263
|
__export(exports_lsp, {
|
|
18264
|
+
typescriptPackageWarning: () => typescriptPackageWarning,
|
|
17397
18265
|
runLspDoctor: () => runLspDoctor,
|
|
17398
18266
|
renderLspInspection: () => renderLspInspection,
|
|
17399
18267
|
printLspDoctorHelp: () => printLspDoctorHelp,
|
|
17400
18268
|
findProjectRootForFile: () => findProjectRootForFile
|
|
17401
18269
|
});
|
|
17402
18270
|
import { existsSync as existsSync12, readdirSync as readdirSync4, statSync as statSync7 } from "node:fs";
|
|
17403
|
-
import {
|
|
18271
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
18272
|
+
import { dirname as dirname8, join as join16, resolve as resolve8 } from "node:path";
|
|
17404
18273
|
function findProjectRootForFile(filePath, fallbackCwd = process.cwd()) {
|
|
17405
18274
|
const resolvedFile = resolve8(fallbackCwd, filePath);
|
|
17406
|
-
let dir =
|
|
18275
|
+
let dir = dirname8(resolvedFile);
|
|
17407
18276
|
try {
|
|
17408
18277
|
if (existsSync12(resolvedFile) && statSync7(resolvedFile).isDirectory()) {
|
|
17409
18278
|
dir = resolvedFile;
|
|
17410
18279
|
}
|
|
17411
18280
|
} catch {
|
|
17412
|
-
dir =
|
|
18281
|
+
dir = dirname8(resolvedFile);
|
|
17413
18282
|
}
|
|
17414
18283
|
while (true) {
|
|
17415
|
-
if (PROJECT_ROOT_MARKERS.some((marker) => existsSync12(
|
|
18284
|
+
if (PROJECT_ROOT_MARKERS.some((marker) => existsSync12(join16(dir, marker)))) {
|
|
17416
18285
|
return dir;
|
|
17417
18286
|
}
|
|
17418
|
-
const parent =
|
|
18287
|
+
const parent = dirname8(dir);
|
|
17419
18288
|
if (parent === dir)
|
|
17420
18289
|
return resolve8(fallbackCwd);
|
|
17421
18290
|
dir = parent;
|
|
@@ -17471,7 +18340,12 @@ async function runLspDoctor(options) {
|
|
|
17471
18340
|
log2.error(inspect.message ?? inspect.code ?? "lsp_inspect failed");
|
|
17472
18341
|
return 1;
|
|
17473
18342
|
}
|
|
17474
|
-
|
|
18343
|
+
const inspection = inspect;
|
|
18344
|
+
const typescriptWarning = typescriptPackageWarning(inspection);
|
|
18345
|
+
console.log(renderLspInspection(file, {
|
|
18346
|
+
...inspection,
|
|
18347
|
+
...typescriptWarning ? { typescript_package_warning: typescriptWarning } : {}
|
|
18348
|
+
}));
|
|
17475
18349
|
return 0;
|
|
17476
18350
|
}
|
|
17477
18351
|
function renderLspInspection(inputFile, response) {
|
|
@@ -17507,6 +18381,10 @@ function renderLspInspection(inputFile, response) {
|
|
|
17507
18381
|
lines.push(` Action: ${installHint(server.binary_name)}`);
|
|
17508
18382
|
}
|
|
17509
18383
|
}
|
|
18384
|
+
if (response.typescript_package_warning) {
|
|
18385
|
+
lines.push("");
|
|
18386
|
+
lines.push(`Warning: ${response.typescript_package_warning}`);
|
|
18387
|
+
}
|
|
17510
18388
|
const diagnostics = response.diagnostics ?? [];
|
|
17511
18389
|
lines.push("");
|
|
17512
18390
|
lines.push(`Diagnostics (${response.diagnostics_count ?? diagnostics.length} found):`);
|
|
@@ -17535,8 +18413,8 @@ function parseFileArg(argv) {
|
|
|
17535
18413
|
function buildConfigureParams(adapter, projectRoot) {
|
|
17536
18414
|
const userConfigPath = adapter.detectConfigPaths().aftConfig;
|
|
17537
18415
|
const dir = adapter.kind === "pi" ? ".pi" : ".opencode";
|
|
17538
|
-
const projectJsonc =
|
|
17539
|
-
const projectJson =
|
|
18416
|
+
const projectJsonc = join16(projectRoot, dir, "aft.jsonc");
|
|
18417
|
+
const projectJson = join16(projectRoot, dir, "aft.json");
|
|
17540
18418
|
const projectConfigPath = existsSync12(projectJsonc) ? projectJsonc : projectJson;
|
|
17541
18419
|
return {
|
|
17542
18420
|
id: "doctor-lsp-configure",
|
|
@@ -17550,10 +18428,10 @@ function buildConfigureParams(adapter, projectRoot) {
|
|
|
17550
18428
|
function inferLspPathsExtra(_lsp) {
|
|
17551
18429
|
const paths = new Set;
|
|
17552
18430
|
for (const entry of childDirs(getAftLspPackagesDir())) {
|
|
17553
|
-
paths.add(
|
|
18431
|
+
paths.add(join16(entry, "node_modules", ".bin"));
|
|
17554
18432
|
}
|
|
17555
18433
|
for (const entry of childDirs(getAftLspBinariesDir())) {
|
|
17556
|
-
paths.add(
|
|
18434
|
+
paths.add(join16(entry, "bin"));
|
|
17557
18435
|
}
|
|
17558
18436
|
return [...paths];
|
|
17559
18437
|
}
|
|
@@ -17561,7 +18439,7 @@ function childDirs(path2) {
|
|
|
17561
18439
|
if (!existsSync12(path2))
|
|
17562
18440
|
return [];
|
|
17563
18441
|
try {
|
|
17564
|
-
return readdirSync4(path2).map((entry) =>
|
|
18442
|
+
return readdirSync4(path2).map((entry) => join16(path2, entry)).filter((entry) => {
|
|
17565
18443
|
try {
|
|
17566
18444
|
return statSync7(entry).isDirectory();
|
|
17567
18445
|
} catch {
|
|
@@ -17596,6 +18474,18 @@ function formatSpawnStatus(server) {
|
|
|
17596
18474
|
function formatList(values) {
|
|
17597
18475
|
return values.length === 0 ? "(none)" : values.join(", ");
|
|
17598
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
|
+
}
|
|
17599
18489
|
function installHint(binaryName) {
|
|
17600
18490
|
if (binaryName === "ty")
|
|
17601
18491
|
return "Install with `uv tool install ty` or `pip install ty`.";
|
|
@@ -17639,7 +18529,7 @@ __export(exports_doctor_filters, {
|
|
|
17639
18529
|
printDoctorFiltersHelp: () => printDoctorFiltersHelp
|
|
17640
18530
|
});
|
|
17641
18531
|
import { existsSync as existsSync13 } from "node:fs";
|
|
17642
|
-
import { homedir as
|
|
18532
|
+
import { homedir as homedir16 } from "node:os";
|
|
17643
18533
|
import { relative as relative3, resolve as resolve9 } from "node:path";
|
|
17644
18534
|
function printDoctorFiltersHelp() {
|
|
17645
18535
|
console.log("Usage: aft doctor filters [--show <name>] [trust|untrust]");
|
|
@@ -17857,7 +18747,7 @@ function truncate(value) {
|
|
|
17857
18747
|
return value.length <= 80 ? value : `${value.slice(0, 77)}…`;
|
|
17858
18748
|
}
|
|
17859
18749
|
function formatHome(path2) {
|
|
17860
|
-
const home =
|
|
18750
|
+
const home = homedir16();
|
|
17861
18751
|
return path2.startsWith(home) ? `~${path2.slice(home.length)}` : path2;
|
|
17862
18752
|
}
|
|
17863
18753
|
function formatProjectPath(path2, projectRoot) {
|
|
@@ -17881,7 +18771,7 @@ var init_doctor_filters = __esm(async () => {
|
|
|
17881
18771
|
|
|
17882
18772
|
// src/lib/binary-cache.ts
|
|
17883
18773
|
import { existsSync as existsSync14, readdirSync as readdirSync5, statSync as statSync8 } from "node:fs";
|
|
17884
|
-
import { join as
|
|
18774
|
+
import { join as join17 } from "node:path";
|
|
17885
18775
|
function getBinaryCacheInfo(activeVersion) {
|
|
17886
18776
|
const path2 = getAftBinaryCacheDir();
|
|
17887
18777
|
if (!existsSync14(path2)) {
|
|
@@ -17894,7 +18784,7 @@ function getBinaryCacheInfo(activeVersion) {
|
|
|
17894
18784
|
}
|
|
17895
18785
|
const versions = readdirSync5(path2).filter((entry) => {
|
|
17896
18786
|
try {
|
|
17897
|
-
return statSync8(
|
|
18787
|
+
return statSync8(join17(path2, entry)).isDirectory();
|
|
17898
18788
|
} catch {
|
|
17899
18789
|
return false;
|
|
17900
18790
|
}
|
|
@@ -17915,7 +18805,7 @@ var init_binary_cache = __esm(() => {
|
|
|
17915
18805
|
|
|
17916
18806
|
// src/lib/sanitize.ts
|
|
17917
18807
|
import { realpathSync as realpathSync3 } from "node:fs";
|
|
17918
|
-
import { homedir as
|
|
18808
|
+
import { homedir as homedir17, userInfo } from "node:os";
|
|
17919
18809
|
function escapeRegex(value) {
|
|
17920
18810
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
17921
18811
|
}
|
|
@@ -17946,7 +18836,7 @@ function redactSecrets(content) {
|
|
|
17946
18836
|
}
|
|
17947
18837
|
function sanitizeContent(content) {
|
|
17948
18838
|
const username = userInfo().username;
|
|
17949
|
-
const home =
|
|
18839
|
+
const home = homedir17();
|
|
17950
18840
|
let sanitized = redactSecrets(content);
|
|
17951
18841
|
const cwd = process.cwd();
|
|
17952
18842
|
for (const candidate of new Set([cwd, safeRealpath(cwd)])) {
|
|
@@ -17993,11 +18883,9 @@ var init_sanitize = __esm(() => {
|
|
|
17993
18883
|
|
|
17994
18884
|
// src/lib/bridge-tool-failures.ts
|
|
17995
18885
|
import { closeSync as closeSync5, existsSync as existsSync15, openSync as openSync5, readSync as readSync2, statSync as statSync9 } from "node:fs";
|
|
17996
|
-
import { tmpdir as tmpdir3 } from "node:os";
|
|
17997
|
-
import { join as join17 } from "node:path";
|
|
17998
18886
|
function resolveBridgePluginLogPath() {
|
|
17999
18887
|
const isTestEnv = process.env.BUN_TEST === "1" || false;
|
|
18000
|
-
return
|
|
18888
|
+
return resolveAftLogPath(isTestEnv ? "aft-plugin-test.log" : "aft-plugin.log");
|
|
18001
18889
|
}
|
|
18002
18890
|
function tailLogFileBytes(path2, maxBytes) {
|
|
18003
18891
|
if (!existsSync15(path2) || maxBytes <= 0)
|
|
@@ -18128,31 +19016,156 @@ function buildRecentAftToolFailuresSectionFromLog(logPath = resolveBridgePluginL
|
|
|
18128
19016
|
}
|
|
18129
19017
|
var BRIDGE_LOG_TAIL_BYTES, MAX_TOOL_FAILURE_CLASSES = 30, SESSION_TAG_PATTERN, STRUCTURED_CODE_PATTERN;
|
|
18130
19018
|
var init_bridge_tool_failures = __esm(() => {
|
|
19019
|
+
init_dist2();
|
|
18131
19020
|
init_sanitize();
|
|
18132
19021
|
BRIDGE_LOG_TAIL_BYTES = 2 * 1024 * 1024;
|
|
18133
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;
|
|
18134
19023
|
STRUCTURED_CODE_PATTERN = /"code"\s*:\s*"([^"]+)"/;
|
|
18135
19024
|
});
|
|
18136
19025
|
|
|
18137
|
-
// src/lib/
|
|
18138
|
-
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";
|
|
18139
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";
|
|
18140
19153
|
function inspectDir(path2) {
|
|
18141
|
-
if (!
|
|
19154
|
+
if (!existsSync17(path2)) {
|
|
18142
19155
|
return { entries: [], totalSize: 0 };
|
|
18143
19156
|
}
|
|
18144
19157
|
const entries = [];
|
|
18145
19158
|
let totalSize = 0;
|
|
18146
19159
|
let names;
|
|
18147
19160
|
try {
|
|
18148
|
-
names =
|
|
19161
|
+
names = readdirSync7(path2);
|
|
18149
19162
|
} catch {
|
|
18150
19163
|
return { entries: [], totalSize: 0 };
|
|
18151
19164
|
}
|
|
18152
19165
|
for (const name of names) {
|
|
18153
|
-
const full =
|
|
19166
|
+
const full = join19(path2, name);
|
|
18154
19167
|
try {
|
|
18155
|
-
if (!
|
|
19168
|
+
if (!statSync11(full).isDirectory())
|
|
18156
19169
|
continue;
|
|
18157
19170
|
const size = dirSize(full);
|
|
18158
19171
|
entries.push({
|
|
@@ -18208,8 +19221,8 @@ var init_lsp_cache = __esm(() => {
|
|
|
18208
19221
|
});
|
|
18209
19222
|
|
|
18210
19223
|
// src/lib/onnx.ts
|
|
18211
|
-
import { existsSync as
|
|
18212
|
-
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";
|
|
18213
19226
|
function getOnnxLibraryName() {
|
|
18214
19227
|
if (process.platform === "darwin")
|
|
18215
19228
|
return "libonnxruntime.dylib";
|
|
@@ -18249,9 +19262,20 @@ function pathEntriesForPlatform2() {
|
|
|
18249
19262
|
return isAbsolute6(entry) || win322.isAbsolute(entry);
|
|
18250
19263
|
});
|
|
18251
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
|
+
}
|
|
18252
19276
|
function directoryContainsLibrary2(dir, libName) {
|
|
18253
19277
|
try {
|
|
18254
|
-
const entries =
|
|
19278
|
+
const entries = readdirSync8(dir);
|
|
18255
19279
|
if (process.platform === "win32") {
|
|
18256
19280
|
const expected = libName.toLowerCase();
|
|
18257
19281
|
return entries.some((entry) => entry.toLowerCase() === expected);
|
|
@@ -18261,6 +19285,24 @@ function directoryContainsLibrary2(dir, libName) {
|
|
|
18261
19285
|
return false;
|
|
18262
19286
|
}
|
|
18263
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
|
+
}
|
|
18264
19306
|
function findSystemOnnxRuntime2() {
|
|
18265
19307
|
const libName = getOnnxLibraryName();
|
|
18266
19308
|
const searchPaths = [];
|
|
@@ -18272,21 +19314,21 @@ function findSystemOnnxRuntime2() {
|
|
|
18272
19314
|
searchPaths.push(...pathEntriesForPlatform2());
|
|
18273
19315
|
const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
|
|
18274
19316
|
const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
18275
|
-
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"), ...(() => {
|
|
18276
19318
|
const nugetPaths = [];
|
|
18277
19319
|
const userProfile = process.env.USERPROFILE ?? "";
|
|
18278
19320
|
if (!userProfile)
|
|
18279
19321
|
return nugetPaths;
|
|
18280
|
-
const nugetPackageDir =
|
|
18281
|
-
if (!
|
|
19322
|
+
const nugetPackageDir = join20(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
|
|
19323
|
+
if (!existsSync18(nugetPackageDir))
|
|
18282
19324
|
return nugetPaths;
|
|
18283
19325
|
try {
|
|
18284
|
-
for (const entry of
|
|
19326
|
+
for (const entry of readdirSync8(nugetPackageDir, { withFileTypes: true })) {
|
|
18285
19327
|
if (!entry.isDirectory())
|
|
18286
19328
|
continue;
|
|
18287
19329
|
if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
|
|
18288
19330
|
continue;
|
|
18289
|
-
nugetPaths.push(
|
|
19331
|
+
nugetPaths.push(join20(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join20(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
|
|
18290
19332
|
}
|
|
18291
19333
|
} catch {}
|
|
18292
19334
|
return nugetPaths;
|
|
@@ -18306,6 +19348,8 @@ function findSystemOnnxRuntime2() {
|
|
|
18306
19348
|
continue;
|
|
18307
19349
|
const version = detectOrtVersion(dir);
|
|
18308
19350
|
if (!version) {
|
|
19351
|
+
if (isWindowsSystem32Directory2(dir))
|
|
19352
|
+
continue;
|
|
18309
19353
|
unknownVersionPaths.push(dir);
|
|
18310
19354
|
continue;
|
|
18311
19355
|
}
|
|
@@ -18316,12 +19360,12 @@ function findSystemOnnxRuntime2() {
|
|
|
18316
19360
|
return unknownVersionPaths[0] ?? null;
|
|
18317
19361
|
}
|
|
18318
19362
|
function findCachedOnnxRuntime(storageDir) {
|
|
18319
|
-
const ortDir =
|
|
19363
|
+
const ortDir = join20(storageDir, "onnxruntime", ONNX_RUNTIME_VERSION);
|
|
18320
19364
|
const libName = getOnnxLibraryName();
|
|
18321
|
-
if (
|
|
19365
|
+
if (existsSync18(join20(ortDir, libName)))
|
|
18322
19366
|
return ortDir;
|
|
18323
|
-
const libSubdir =
|
|
18324
|
-
if (
|
|
19367
|
+
const libSubdir = join20(ortDir, "lib");
|
|
19368
|
+
if (existsSync18(join20(libSubdir, libName)))
|
|
18325
19369
|
return libSubdir;
|
|
18326
19370
|
return null;
|
|
18327
19371
|
}
|
|
@@ -18342,11 +19386,11 @@ function parseOrtVersionFromDirectoryPath(value) {
|
|
|
18342
19386
|
return null;
|
|
18343
19387
|
}
|
|
18344
19388
|
function detectOrtVersion(libDir) {
|
|
18345
|
-
if (!
|
|
19389
|
+
if (!existsSync18(libDir))
|
|
18346
19390
|
return null;
|
|
18347
19391
|
const libName = getOnnxLibraryName();
|
|
18348
19392
|
try {
|
|
18349
|
-
const entries =
|
|
19393
|
+
const entries = readdirSync8(libDir);
|
|
18350
19394
|
const barePrefix = libName.replace(/\.(so|dylib|dll)$/, "");
|
|
18351
19395
|
const expectedPrefix = process.platform === "win32" ? barePrefix.toLowerCase() : barePrefix;
|
|
18352
19396
|
for (const entry of entries) {
|
|
@@ -18357,8 +19401,8 @@ function detectOrtVersion(libDir) {
|
|
|
18357
19401
|
if (version)
|
|
18358
19402
|
return version;
|
|
18359
19403
|
}
|
|
18360
|
-
const base =
|
|
18361
|
-
if (
|
|
19404
|
+
const base = join20(libDir, libName);
|
|
19405
|
+
if (existsSync18(base)) {
|
|
18362
19406
|
try {
|
|
18363
19407
|
const real = realpathSync4(base);
|
|
18364
19408
|
const version = parseOrtVersionFromPath(real) ?? parseOrtVersionFromDirectoryPath(real);
|
|
@@ -18393,10 +19437,10 @@ import {
|
|
|
18393
19437
|
accessSync,
|
|
18394
19438
|
closeSync as closeSync6,
|
|
18395
19439
|
constants,
|
|
18396
|
-
existsSync as
|
|
19440
|
+
existsSync as existsSync19,
|
|
18397
19441
|
openSync as openSync6,
|
|
18398
19442
|
readSync as readSync3,
|
|
18399
|
-
statSync as
|
|
19443
|
+
statSync as statSync12
|
|
18400
19444
|
} from "node:fs";
|
|
18401
19445
|
async function collectDiagnostics(adapters) {
|
|
18402
19446
|
const cliVersion = getSelfVersion();
|
|
@@ -18431,7 +19475,7 @@ async function diagnoseHarness(adapter) {
|
|
|
18431
19475
|
const logPath = adapter.getLogFile();
|
|
18432
19476
|
const pluginCache = adapter.getPluginCacheInfo();
|
|
18433
19477
|
const storageAccessible = (() => {
|
|
18434
|
-
if (!
|
|
19478
|
+
if (!existsSync19(storage))
|
|
18435
19479
|
return false;
|
|
18436
19480
|
try {
|
|
18437
19481
|
accessSync(storage, constants.R_OK | constants.W_OK);
|
|
@@ -18441,8 +19485,10 @@ async function diagnoseHarness(adapter) {
|
|
|
18441
19485
|
}
|
|
18442
19486
|
})();
|
|
18443
19487
|
const describeStorage = "describeStorageSubtrees" in adapter && typeof adapter.describeStorageSubtrees === "function" ? adapter.describeStorageSubtrees() : {};
|
|
19488
|
+
const legacyDuplication = summarizeLegacyPartitionDuplication(storage);
|
|
18444
19489
|
const semanticEnabled = aftEnabled && (aftConfigRead.value?.semantic_search === true || aftConfigRead.value?.experimental_semantic_search === true);
|
|
18445
19490
|
const systemOrtDir = findSystemOnnxRuntime2();
|
|
19491
|
+
const ignoredSystemOrtDir = systemOrtDir ? null : findIgnoredWindowsSystemOnnxRuntime();
|
|
18446
19492
|
const cachedOrtDir = findCachedOnnxRuntime(storage);
|
|
18447
19493
|
const systemVersion = systemOrtDir ? detectOrtVersion(systemOrtDir) : null;
|
|
18448
19494
|
const cachedVersion = cachedOrtDir ? detectOrtVersion(cachedOrtDir) : null;
|
|
@@ -18454,7 +19500,7 @@ async function diagnoseHarness(adapter) {
|
|
|
18454
19500
|
pluginRegistered: adapter.hasPluginEntry(),
|
|
18455
19501
|
configPaths,
|
|
18456
19502
|
aftConfig: {
|
|
18457
|
-
exists:
|
|
19503
|
+
exists: existsSync19(configPaths.aftConfig),
|
|
18458
19504
|
...aftConfigRead.error ? { parseError: aftConfigRead.error } : {},
|
|
18459
19505
|
enabled: aftEnabled,
|
|
18460
19506
|
...aftEnabledSource ? { enabledSource: aftEnabledSource } : {},
|
|
@@ -18463,15 +19509,18 @@ async function diagnoseHarness(adapter) {
|
|
|
18463
19509
|
pluginCache,
|
|
18464
19510
|
storageDir: {
|
|
18465
19511
|
path: storage,
|
|
18466
|
-
exists:
|
|
19512
|
+
exists: existsSync19(storage),
|
|
18467
19513
|
accessible: storageAccessible,
|
|
18468
|
-
sizesByKey: describeStorage
|
|
19514
|
+
sizesByKey: describeStorage,
|
|
19515
|
+
...legacyDuplication.totalPartitions > 0 ? { legacyDuplication } : {}
|
|
18469
19516
|
},
|
|
18470
19517
|
onnxRuntime: {
|
|
18471
19518
|
required: semanticEnabled,
|
|
18472
19519
|
systemPath: systemOrtDir,
|
|
18473
19520
|
systemVersion,
|
|
18474
19521
|
systemCompatible: systemVersion ? isOrtVersionCompatible(systemVersion) : null,
|
|
19522
|
+
ignoredSystemPath: ignoredSystemOrtDir,
|
|
19523
|
+
ignoredSystemReason: ignoredSystemOrtDir ? "version unreadable (Windows system copy) — ignored" : null,
|
|
18475
19524
|
cachedPath: cachedOrtDir,
|
|
18476
19525
|
cachedVersion,
|
|
18477
19526
|
cachedCompatible: cachedVersion ? isOrtVersionCompatible(cachedVersion) : null,
|
|
@@ -18481,8 +19530,8 @@ async function diagnoseHarness(adapter) {
|
|
|
18481
19530
|
},
|
|
18482
19531
|
logFile: {
|
|
18483
19532
|
path: logPath,
|
|
18484
|
-
exists:
|
|
18485
|
-
sizeKb:
|
|
19533
|
+
exists: existsSync19(logPath),
|
|
19534
|
+
sizeKb: existsSync19(logPath) ? Math.round(statSync12(logPath).size / 1024) : 0
|
|
18486
19535
|
}
|
|
18487
19536
|
};
|
|
18488
19537
|
}
|
|
@@ -18637,7 +19686,7 @@ function collectDiagnosticIssues(report) {
|
|
|
18637
19686
|
code: "onnx_missing",
|
|
18638
19687
|
severity: "medium",
|
|
18639
19688
|
scope: h2.displayName,
|
|
18640
|
-
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.",
|
|
18641
19690
|
remediation: `Run \`aft doctor --fix\` or install ONNX Runtime manually (${h2.onnxRuntime.installHint}).`
|
|
18642
19691
|
});
|
|
18643
19692
|
}
|
|
@@ -18678,14 +19727,14 @@ function formatDiagnosticIssuesSection(report) {
|
|
|
18678
19727
|
return lines;
|
|
18679
19728
|
}
|
|
18680
19729
|
function tailLogFile(path2, lines) {
|
|
18681
|
-
if (!
|
|
19730
|
+
if (!existsSync19(path2))
|
|
18682
19731
|
return "";
|
|
18683
19732
|
if (lines <= 0)
|
|
18684
19733
|
return "";
|
|
18685
19734
|
const chunkSize = 64 * 1024;
|
|
18686
19735
|
let fd = null;
|
|
18687
19736
|
try {
|
|
18688
|
-
const size =
|
|
19737
|
+
const size = statSync12(path2).size;
|
|
18689
19738
|
fd = openSync6(path2, "r");
|
|
18690
19739
|
const chunks = [];
|
|
18691
19740
|
let position = size;
|
|
@@ -18718,6 +19767,7 @@ var init_diagnostics = __esm(async () => {
|
|
|
18718
19767
|
init_dist2();
|
|
18719
19768
|
init_binary_cache();
|
|
18720
19769
|
init_jsonc();
|
|
19770
|
+
init_legacy_storage();
|
|
18721
19771
|
init_lsp_cache();
|
|
18722
19772
|
init_onnx();
|
|
18723
19773
|
init_sanitize();
|
|
@@ -18865,34 +19915,42 @@ var init_issue_body = __esm(() => {
|
|
|
18865
19915
|
});
|
|
18866
19916
|
|
|
18867
19917
|
// src/lib/onnx-fix.ts
|
|
18868
|
-
import { existsSync as
|
|
18869
|
-
import { join as
|
|
19918
|
+
import { existsSync as existsSync20, rmSync as rmSync6 } from "node:fs";
|
|
19919
|
+
import { join as join21 } from "node:path";
|
|
18870
19920
|
function findOnnxFixCandidates(report) {
|
|
18871
19921
|
const candidates = [];
|
|
18872
19922
|
for (const harness of report.harnesses) {
|
|
18873
19923
|
if (!harness.onnxRuntime.required)
|
|
18874
19924
|
continue;
|
|
18875
|
-
|
|
18876
|
-
continue;
|
|
18877
|
-
const storageOnnxDir = join20(harness.storageDir.path, "onnxruntime");
|
|
19925
|
+
const storageOnnxDir = join21(harness.storageDir.path, "onnxruntime");
|
|
18878
19926
|
const systemTooOld = harness.onnxRuntime.systemPath !== null && harness.onnxRuntime.systemCompatible === false;
|
|
18879
19927
|
const cachedTooOld = harness.onnxRuntime.cachedPath !== null && harness.onnxRuntime.cachedCompatible === false;
|
|
18880
19928
|
const hasCompatibleCached = harness.onnxRuntime.cachedCompatible === true;
|
|
18881
19929
|
if (cachedTooOld) {
|
|
18882
19930
|
candidates.push({
|
|
18883
19931
|
harness,
|
|
18884
|
-
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.`,
|
|
18885
19933
|
storageOnnxDir,
|
|
18886
|
-
storageOnnxBytes:
|
|
19934
|
+
storageOnnxBytes: existsSync20(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
|
|
18887
19935
|
});
|
|
18888
19936
|
continue;
|
|
18889
19937
|
}
|
|
18890
19938
|
if (systemTooOld && !hasCompatibleCached) {
|
|
18891
19939
|
candidates.push({
|
|
18892
19940
|
harness,
|
|
18893
|
-
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.`,
|
|
18894
19952
|
storageOnnxDir,
|
|
18895
|
-
storageOnnxBytes:
|
|
19953
|
+
storageOnnxBytes: existsSync20(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
|
|
18896
19954
|
});
|
|
18897
19955
|
}
|
|
18898
19956
|
}
|
|
@@ -18900,58 +19958,74 @@ function findOnnxFixCandidates(report) {
|
|
|
18900
19958
|
}
|
|
18901
19959
|
async function runOnnxFix(adapters, report, options = {}) {
|
|
18902
19960
|
const candidates = findOnnxFixCandidates(report);
|
|
18903
|
-
if (candidates.length === 0)
|
|
19961
|
+
if (candidates.length === 0)
|
|
18904
19962
|
return null;
|
|
18905
|
-
}
|
|
18906
|
-
|
|
18907
|
-
|
|
18908
|
-
|
|
18909
|
-
|
|
18910
|
-
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)})`);
|
|
18911
19968
|
} else {
|
|
18912
|
-
log2.info(
|
|
19969
|
+
log2.info(" no AFT-managed ONNX cache to delete");
|
|
18913
19970
|
}
|
|
18914
19971
|
}
|
|
18915
|
-
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");
|
|
18916
19973
|
const confirmFn = options.confirmFn ?? confirm2;
|
|
18917
19974
|
const proceed = options.yes ? true : await confirmFn("Proceed with the fixes above?", true);
|
|
18918
19975
|
if (!proceed) {
|
|
18919
19976
|
log2.info("Skipped — no changes made.");
|
|
18920
19977
|
return null;
|
|
18921
19978
|
}
|
|
18922
|
-
const result = { cleared: 0, bytesReclaimed: 0, errors: [] };
|
|
19979
|
+
const result = { cleared: 0, installed: 0, bytesReclaimed: 0, errors: [] };
|
|
18923
19980
|
const rmFn = options.rmFn ?? rmSync6;
|
|
18924
|
-
|
|
18925
|
-
|
|
18926
|
-
|
|
18927
|
-
|
|
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
|
+
}
|
|
18928
19995
|
}
|
|
18929
19996
|
try {
|
|
18930
|
-
|
|
18931
|
-
|
|
18932
|
-
|
|
18933
|
-
|
|
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}`);
|
|
18934
20007
|
} catch (err) {
|
|
18935
|
-
const message = err.message
|
|
18936
|
-
log2.error(`${
|
|
18937
|
-
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 });
|
|
18938
20011
|
}
|
|
18939
20012
|
}
|
|
18940
|
-
if (result.
|
|
18941
|
-
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");
|
|
18942
20015
|
}
|
|
18943
20016
|
return result;
|
|
18944
20017
|
}
|
|
18945
20018
|
var init_onnx_fix = __esm(() => {
|
|
20019
|
+
init_dist2();
|
|
18946
20020
|
init_fs_util();
|
|
18947
20021
|
init_prompts();
|
|
18948
20022
|
});
|
|
18949
20023
|
|
|
18950
20024
|
// src/lib/sessions.ts
|
|
18951
|
-
import { existsSync as
|
|
18952
|
-
import { createRequire as
|
|
18953
|
-
import { homedir as
|
|
18954
|
-
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";
|
|
18955
20029
|
function listRecentSessions(adapter) {
|
|
18956
20030
|
try {
|
|
18957
20031
|
if (adapter.kind === "opencode")
|
|
@@ -18980,12 +20054,12 @@ function mapOpenCodeSessionRows(rows) {
|
|
|
18980
20054
|
}).filter((session) => session !== null).sort((a3, b2) => b2.lastActivity - a3.lastActivity).slice(0, MAX_RECENT_SESSIONS);
|
|
18981
20055
|
}
|
|
18982
20056
|
function listRecentOpenCodeSessions() {
|
|
18983
|
-
const dbPath =
|
|
18984
|
-
if (!
|
|
20057
|
+
const dbPath = join22(getXdgDataHome(), "opencode", "opencode.db");
|
|
20058
|
+
if (!existsSync21(dbPath))
|
|
18985
20059
|
return [];
|
|
18986
20060
|
let db = null;
|
|
18987
20061
|
try {
|
|
18988
|
-
const require2 =
|
|
20062
|
+
const require2 = createRequire5(import.meta.url);
|
|
18989
20063
|
const sqlite = require2("node:sqlite");
|
|
18990
20064
|
db = new sqlite.DatabaseSync(dbPath, { readOnly: true });
|
|
18991
20065
|
const rows = db.prepare("SELECT id, title, time_updated FROM session ORDER BY time_updated DESC LIMIT 5").all();
|
|
@@ -19000,22 +20074,22 @@ function listRecentOpenCodeSessions() {
|
|
|
19000
20074
|
}
|
|
19001
20075
|
function getXdgDataHome() {
|
|
19002
20076
|
const xdgDataHome = process.env.XDG_DATA_HOME;
|
|
19003
|
-
return xdgDataHome && xdgDataHome.length > 0 ? xdgDataHome :
|
|
20077
|
+
return xdgDataHome && xdgDataHome.length > 0 ? xdgDataHome : join22(homedir18(), ".local", "share");
|
|
19004
20078
|
}
|
|
19005
20079
|
function listRecentPiSessions() {
|
|
19006
|
-
return listPiSessionsFromDir(
|
|
20080
|
+
return listPiSessionsFromDir(join22(getHomeDir(), ".pi", "agent", "sessions"));
|
|
19007
20081
|
}
|
|
19008
20082
|
function getHomeDir() {
|
|
19009
20083
|
const envHome = process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME;
|
|
19010
|
-
return envHome && envHome.length > 0 ? envHome :
|
|
20084
|
+
return envHome && envHome.length > 0 ? envHome : homedir18();
|
|
19011
20085
|
}
|
|
19012
20086
|
function listPiSessionsFromDir(sessionsDir) {
|
|
19013
20087
|
try {
|
|
19014
|
-
if (!
|
|
20088
|
+
if (!existsSync21(sessionsDir))
|
|
19015
20089
|
return [];
|
|
19016
20090
|
const files = collectJsonlFiles(sessionsDir).map((filePath) => {
|
|
19017
20091
|
try {
|
|
19018
|
-
const stats =
|
|
20092
|
+
const stats = statSync13(filePath);
|
|
19019
20093
|
return { filePath, mtimeMs: stats.mtimeMs };
|
|
19020
20094
|
} catch {
|
|
19021
20095
|
return null;
|
|
@@ -19044,12 +20118,12 @@ function collectJsonlFiles(root) {
|
|
|
19044
20118
|
continue;
|
|
19045
20119
|
let entries;
|
|
19046
20120
|
try {
|
|
19047
|
-
entries =
|
|
20121
|
+
entries = readdirSync9(dir, { withFileTypes: true });
|
|
19048
20122
|
} catch {
|
|
19049
20123
|
continue;
|
|
19050
20124
|
}
|
|
19051
20125
|
for (const entry of entries) {
|
|
19052
|
-
const path2 =
|
|
20126
|
+
const path2 = join22(dir, entry.name);
|
|
19053
20127
|
if (entry.isDirectory()) {
|
|
19054
20128
|
stack.push(path2);
|
|
19055
20129
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
@@ -19149,17 +20223,17 @@ __export(exports_doctor, {
|
|
|
19149
20223
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
19150
20224
|
import {
|
|
19151
20225
|
chmodSync as chmodSync4,
|
|
19152
|
-
existsSync as
|
|
20226
|
+
existsSync as existsSync22,
|
|
19153
20227
|
mkdirSync as mkdirSync7,
|
|
19154
20228
|
mkdtempSync,
|
|
19155
20229
|
readFileSync as readFileSync11,
|
|
19156
20230
|
realpathSync as realpathSync5,
|
|
19157
20231
|
rmSync as rmSync7,
|
|
19158
|
-
statSync as
|
|
20232
|
+
statSync as statSync14,
|
|
19159
20233
|
writeFileSync as writeFileSync5
|
|
19160
20234
|
} from "node:fs";
|
|
19161
|
-
import { tmpdir as
|
|
19162
|
-
import { join as
|
|
20235
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
20236
|
+
import { join as join23 } from "node:path";
|
|
19163
20237
|
async function runDoctor(options) {
|
|
19164
20238
|
if (options.issue) {
|
|
19165
20239
|
return runIssueFlow(options.argv);
|
|
@@ -19228,6 +20302,8 @@ async function runDoctor(options) {
|
|
|
19228
20302
|
}
|
|
19229
20303
|
if (h2.onnxRuntime.systemPath) {
|
|
19230
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}`);
|
|
19231
20307
|
}
|
|
19232
20308
|
if (!h2.onnxRuntime.cachedPath && !h2.onnxRuntime.systemPath) {
|
|
19233
20309
|
parts.push(`not installed — ${h2.onnxRuntime.installHint}`);
|
|
@@ -19324,7 +20400,7 @@ function clearOldBinaries() {
|
|
|
19324
20400
|
errors: [],
|
|
19325
20401
|
keptVersion: keepTag
|
|
19326
20402
|
};
|
|
19327
|
-
if (!
|
|
20403
|
+
if (!existsSync22(info.path)) {
|
|
19328
20404
|
log2.info(`Binary cache: nothing to clear at ${info.path}`);
|
|
19329
20405
|
return result;
|
|
19330
20406
|
}
|
|
@@ -19334,10 +20410,10 @@ function clearOldBinaries() {
|
|
|
19334
20410
|
return result;
|
|
19335
20411
|
}
|
|
19336
20412
|
for (const version of stale) {
|
|
19337
|
-
const dir =
|
|
20413
|
+
const dir = join23(info.path, version);
|
|
19338
20414
|
let bytes = 0;
|
|
19339
20415
|
try {
|
|
19340
|
-
bytes =
|
|
20416
|
+
bytes = statSync14(dir).isDirectory() ? dirSize(dir) : 0;
|
|
19341
20417
|
} catch {
|
|
19342
20418
|
bytes = 0;
|
|
19343
20419
|
}
|
|
@@ -19511,12 +20587,12 @@ function buildDoctorFixPlan(adapters, report) {
|
|
|
19511
20587
|
if (candidate.storageOnnxBytes > 0) {
|
|
19512
20588
|
items.push({
|
|
19513
20589
|
kind: "onnx",
|
|
19514
|
-
message: `Will
|
|
20590
|
+
message: `Will replace AFT-managed ONNX cache at ${candidate.storageOnnxDir} (${formatBytes(candidate.storageOnnxBytes)}) and download a compatible runtime`
|
|
19515
20591
|
});
|
|
19516
20592
|
} else {
|
|
19517
20593
|
items.push({
|
|
19518
20594
|
kind: "onnx",
|
|
19519
|
-
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}`
|
|
19520
20596
|
});
|
|
19521
20597
|
}
|
|
19522
20598
|
}
|
|
@@ -19648,7 +20724,8 @@ function logDoctorIssues(report) {
|
|
|
19648
20724
|
}
|
|
19649
20725
|
function formatDoctorStorageStatus(h2) {
|
|
19650
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"})`;
|
|
19651
|
-
|
|
20727
|
+
const legacyDuplication = formatLegacyDuplication(h2.storageDir.legacyDuplication);
|
|
20728
|
+
return `${state} (${[formatStorageSizes(h2.storageDir.sizesByKey), legacyDuplication].filter((part) => Boolean(part)).join("; ")})`;
|
|
19652
20729
|
}
|
|
19653
20730
|
async function confirmBinaryDownloadDespitePluginSkew(report, argv) {
|
|
19654
20731
|
const skews = findPluginCliVersionSkews(report);
|
|
@@ -19678,7 +20755,7 @@ function ensureStorageDirsForRegisteredPlugins(adapters) {
|
|
|
19678
20755
|
if (!adapter.isInstalled() || !adapter.hasPluginEntry())
|
|
19679
20756
|
continue;
|
|
19680
20757
|
const storageDir = adapter.getStorageDir();
|
|
19681
|
-
if (
|
|
20758
|
+
if (existsSync22(storageDir))
|
|
19682
20759
|
continue;
|
|
19683
20760
|
mkdirSync7(storageDir, { recursive: true });
|
|
19684
20761
|
summary.created += 1;
|
|
@@ -19760,6 +20837,12 @@ function formatStorageSizes(sizes) {
|
|
|
19760
20837
|
const parts = Object.entries(sizes).filter(([, size]) => size > 0).map(([key, size]) => `${key}: ${formatBytes(size)}`);
|
|
19761
20838
|
return parts.length > 0 ? parts.join(", ") : "empty";
|
|
19762
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
|
+
}
|
|
19763
20846
|
function isInteractiveTerminal() {
|
|
19764
20847
|
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
19765
20848
|
}
|
|
@@ -19791,11 +20874,11 @@ function deriveIssueTitleFromBody(body) {
|
|
|
19791
20874
|
function writeIssueReviewFile(body) {
|
|
19792
20875
|
let reviewDir = null;
|
|
19793
20876
|
try {
|
|
19794
|
-
reviewDir = mkdtempSync(
|
|
20877
|
+
reviewDir = mkdtempSync(join23(tmpdir2(), "aft-issue-"));
|
|
19795
20878
|
if (process.platform !== "win32") {
|
|
19796
20879
|
chmodSync4(reviewDir, 448);
|
|
19797
20880
|
}
|
|
19798
|
-
const outPath =
|
|
20881
|
+
const outPath = join23(reviewDir, "issue.md");
|
|
19799
20882
|
writeFileSync5(outPath, `${body}
|
|
19800
20883
|
`, { encoding: "utf8", mode: 384, flag: "wx" });
|
|
19801
20884
|
return { path: outPath, realPath: realpathSync5(outPath) };
|