@cortexkit/aft 0.46.0 → 0.47.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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 +1816 -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,18 +2531,61 @@ 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
|
}
|
|
2538
|
+
function decodeFileUrl(target) {
|
|
2539
|
+
if (!target.startsWith("file:"))
|
|
2540
|
+
return target;
|
|
2541
|
+
const rest = target.slice("file:".length);
|
|
2542
|
+
let pathPart;
|
|
2543
|
+
if (rest.startsWith("//")) {
|
|
2544
|
+
const after = rest.slice(2);
|
|
2545
|
+
const slash = after.indexOf("/");
|
|
2546
|
+
const authority = slash === -1 ? after : after.slice(0, slash);
|
|
2547
|
+
const p = slash === -1 ? "" : after.slice(slash);
|
|
2548
|
+
if (authority === "" || authority === "localhost")
|
|
2549
|
+
pathPart = p;
|
|
2550
|
+
else if (process.platform === "win32")
|
|
2551
|
+
pathPart = `//${authority}${p}`;
|
|
2552
|
+
else
|
|
2553
|
+
return target;
|
|
2554
|
+
} else if (rest.startsWith("/")) {
|
|
2555
|
+
pathPart = rest;
|
|
2556
|
+
} else {
|
|
2557
|
+
return target;
|
|
2558
|
+
}
|
|
2559
|
+
const bytes = [];
|
|
2560
|
+
for (let i = 0;i < pathPart.length; ) {
|
|
2561
|
+
if (pathPart[i] === "%" && i + 2 < pathPart.length) {
|
|
2562
|
+
const hex = pathPart.slice(i + 1, i + 3);
|
|
2563
|
+
if (/^[0-9a-fA-F]{2}$/.test(hex)) {
|
|
2564
|
+
bytes.push(Number.parseInt(hex, 16));
|
|
2565
|
+
i += 3;
|
|
2566
|
+
continue;
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
const cp = pathPart.codePointAt(i);
|
|
2570
|
+
const ch = String.fromCodePoint(cp);
|
|
2571
|
+
for (const b of Buffer.from(ch, "utf8"))
|
|
2572
|
+
bytes.push(b);
|
|
2573
|
+
i += ch.length;
|
|
2574
|
+
}
|
|
2575
|
+
const decoded = Buffer.from(bytes).toString("utf8");
|
|
2576
|
+
if (process.platform === "win32" && /^\/[A-Za-z]:/.test(decoded)) {
|
|
2577
|
+
return decoded.slice(1);
|
|
2578
|
+
}
|
|
2579
|
+
return decoded;
|
|
2580
|
+
}
|
|
2409
2581
|
var init_paths = () => {};
|
|
2410
2582
|
|
|
2411
2583
|
// ../aft-bridge/dist/resolver.js
|
|
2412
2584
|
import { execSync } from "node:child_process";
|
|
2413
2585
|
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
2586
|
import { createRequire } from "node:module";
|
|
2415
|
-
import { homedir as
|
|
2416
|
-
import { join as
|
|
2587
|
+
import { homedir as homedir7 } from "node:os";
|
|
2588
|
+
import { join as join6 } from "node:path";
|
|
2417
2589
|
function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
2418
2590
|
try {
|
|
2419
2591
|
const version = knownVersion ?? readBinaryVersion(npmBinaryPath);
|
|
@@ -2421,9 +2593,9 @@ function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
|
2421
2593
|
return null;
|
|
2422
2594
|
const tag = version.startsWith("v") ? version : `v${version}`;
|
|
2423
2595
|
const cacheDir = getCacheDir();
|
|
2424
|
-
const versionedDir =
|
|
2596
|
+
const versionedDir = join6(cacheDir, tag);
|
|
2425
2597
|
const ext = process.platform === "win32" ? ".exe" : "";
|
|
2426
|
-
const cachedPath =
|
|
2598
|
+
const cachedPath = join6(versionedDir, `aft${ext}`);
|
|
2427
2599
|
if (existsSync4(cachedPath)) {
|
|
2428
2600
|
const cachedVersion = readBinaryVersion(cachedPath);
|
|
2429
2601
|
if (cachedVersion === version)
|
|
@@ -2453,18 +2625,18 @@ function normalizeBareVersion(version) {
|
|
|
2453
2625
|
return version.startsWith("v") ? version.slice(1) : version;
|
|
2454
2626
|
}
|
|
2455
2627
|
function homeDirFromEnv(env) {
|
|
2456
|
-
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) ||
|
|
2628
|
+
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir7();
|
|
2457
2629
|
}
|
|
2458
2630
|
function cacheDirFromEnv(env) {
|
|
2459
2631
|
if (process.platform === "win32") {
|
|
2460
|
-
const base2 = env.LOCALAPPDATA || env.APPDATA ||
|
|
2461
|
-
return
|
|
2632
|
+
const base2 = env.LOCALAPPDATA || env.APPDATA || join6(homeDirFromEnv(env), "AppData", "Local");
|
|
2633
|
+
return join6(base2, "aft", "bin");
|
|
2462
2634
|
}
|
|
2463
|
-
const base = env.XDG_CACHE_HOME ||
|
|
2464
|
-
return
|
|
2635
|
+
const base = env.XDG_CACHE_HOME || join6(homeDirFromEnv(env), ".cache");
|
|
2636
|
+
return join6(base, "aft", "bin");
|
|
2465
2637
|
}
|
|
2466
2638
|
function cachedBinaryPathFromEnv(version, env, ext) {
|
|
2467
|
-
const binaryPath =
|
|
2639
|
+
const binaryPath = join6(cacheDirFromEnv(env), version, `aft${ext}`);
|
|
2468
2640
|
return existsSync4(binaryPath) ? binaryPath : null;
|
|
2469
2641
|
}
|
|
2470
2642
|
function isExpectedCachedBinary2(binaryPath, expectedVersion) {
|
|
@@ -2583,7 +2755,7 @@ function findBinarySync(expectedVersion) {
|
|
|
2583
2755
|
return usable;
|
|
2584
2756
|
}
|
|
2585
2757
|
} catch {}
|
|
2586
|
-
const cargoPath =
|
|
2758
|
+
const cargoPath = join6(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
|
|
2587
2759
|
if (existsSync4(cargoPath)) {
|
|
2588
2760
|
const usable = probeBinaryCandidate(cargoPath, "cargo", expectedVersion);
|
|
2589
2761
|
if (usable)
|
|
@@ -2631,28 +2803,28 @@ var init_resolver = __esm(() => {
|
|
|
2631
2803
|
// ../aft-bridge/dist/migration.js
|
|
2632
2804
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
2633
2805
|
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
|
|
2806
|
+
import { homedir as homedir8, tmpdir } from "node:os";
|
|
2807
|
+
import { basename, dirname as dirname3, join as join7, resolve as resolve4 } from "node:path";
|
|
2808
|
+
function dataHome2() {
|
|
2637
2809
|
if (process.env.XDG_DATA_HOME)
|
|
2638
2810
|
return process.env.XDG_DATA_HOME;
|
|
2639
2811
|
if (process.platform === "win32") {
|
|
2640
|
-
return process.env.LOCALAPPDATA || process.env.APPDATA ||
|
|
2812
|
+
return process.env.LOCALAPPDATA || process.env.APPDATA || join7(homeDir3(), "AppData", "Local");
|
|
2641
2813
|
}
|
|
2642
|
-
return
|
|
2814
|
+
return join7(homeDir3(), ".local", "share");
|
|
2643
2815
|
}
|
|
2644
|
-
function
|
|
2816
|
+
function homeDir3() {
|
|
2645
2817
|
if (process.platform === "win32")
|
|
2646
|
-
return process.env.USERPROFILE || process.env.HOME ||
|
|
2647
|
-
return process.env.HOME ||
|
|
2818
|
+
return process.env.USERPROFILE || process.env.HOME || homedir8();
|
|
2819
|
+
return process.env.HOME || homedir8();
|
|
2648
2820
|
}
|
|
2649
2821
|
function resolveLegacyStorageRoot(harness) {
|
|
2650
2822
|
if (harness === "pi")
|
|
2651
|
-
return
|
|
2652
|
-
return
|
|
2823
|
+
return join7(homeDir3(), ".pi", "agent", "aft");
|
|
2824
|
+
return join7(dataHome2(), "opencode", "storage", "plugin", "aft");
|
|
2653
2825
|
}
|
|
2654
2826
|
function resolveCortexKitStorageRoot() {
|
|
2655
|
-
return
|
|
2827
|
+
return join7(dataHome2(), "cortexkit", "aft");
|
|
2656
2828
|
}
|
|
2657
2829
|
function stripJsoncForParse(input) {
|
|
2658
2830
|
let out = "";
|
|
@@ -2781,8 +2953,8 @@ function acquireConfigMigrationLock(lockDir) {
|
|
|
2781
2953
|
}
|
|
2782
2954
|
}
|
|
2783
2955
|
function atomicCopyConfigFile(sourcePath, targetPath) {
|
|
2784
|
-
mkdirSync4(
|
|
2785
|
-
const tmpPath =
|
|
2956
|
+
mkdirSync4(dirname3(targetPath), { recursive: true });
|
|
2957
|
+
const tmpPath = join7(dirname3(targetPath), `.${basename(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
2786
2958
|
let fd = null;
|
|
2787
2959
|
try {
|
|
2788
2960
|
fd = openSync3(tmpPath, "wx", 384);
|
|
@@ -2803,8 +2975,8 @@ function atomicCopyConfigFile(sourcePath, targetPath) {
|
|
|
2803
2975
|
}
|
|
2804
2976
|
}
|
|
2805
2977
|
function atomicWriteConfigFile(targetPath, content) {
|
|
2806
|
-
mkdirSync4(
|
|
2807
|
-
const tmpPath =
|
|
2978
|
+
mkdirSync4(dirname3(targetPath), { recursive: true });
|
|
2979
|
+
const tmpPath = join7(dirname3(targetPath), `.${basename(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
2808
2980
|
let fd = null;
|
|
2809
2981
|
try {
|
|
2810
2982
|
fd = openSync3(tmpPath, "wx", 384);
|
|
@@ -2927,7 +3099,7 @@ function migrateAftConfigFile(opts) {
|
|
|
2927
3099
|
if (existingSources.length === 0) {
|
|
2928
3100
|
return { migrated: false, conflict: false, targetPath: opts.targetPath, warnings };
|
|
2929
3101
|
}
|
|
2930
|
-
mkdirSync4(
|
|
3102
|
+
mkdirSync4(dirname3(opts.targetPath), { recursive: true });
|
|
2931
3103
|
const release = acquireConfigMigrationLock(`${opts.targetPath}.lock`);
|
|
2932
3104
|
try {
|
|
2933
3105
|
const sources = existingSources.map((source) => ({
|
|
@@ -2984,13 +3156,13 @@ function spawnErrorLabel(error2) {
|
|
|
2984
3156
|
return [code, error2.message].filter(Boolean).join(": ");
|
|
2985
3157
|
}
|
|
2986
3158
|
function migrationLogPath(newRoot, harness, logger) {
|
|
2987
|
-
const desired =
|
|
3159
|
+
const desired = join7(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
|
|
2988
3160
|
try {
|
|
2989
|
-
mkdirSync4(
|
|
3161
|
+
mkdirSync4(dirname3(desired), { recursive: true });
|
|
2990
3162
|
return desired;
|
|
2991
3163
|
} catch (err) {
|
|
2992
|
-
const fallback =
|
|
2993
|
-
logger?.warn?.(`Failed to create AFT migration log directory ${
|
|
3164
|
+
const fallback = join7(tmpdir(), `aft-migration-${harness}-${Date.now()}.jsonl`);
|
|
3165
|
+
logger?.warn?.(`Failed to create AFT migration log directory ${dirname3(desired)}: ${err instanceof Error ? err.message : String(err)}. ` + `Using fallback log path ${fallback}.`);
|
|
2994
3166
|
return fallback;
|
|
2995
3167
|
}
|
|
2996
3168
|
}
|
|
@@ -3091,13 +3263,13 @@ var init_migration = __esm(() => {
|
|
|
3091
3263
|
// ../aft-bridge/dist/npm-resolver.js
|
|
3092
3264
|
import { execFileSync } from "node:child_process";
|
|
3093
3265
|
import { readdirSync, statSync as statSync3 } from "node:fs";
|
|
3094
|
-
import { homedir as
|
|
3095
|
-
import { delimiter, dirname as
|
|
3266
|
+
import { homedir as homedir9 } from "node:os";
|
|
3267
|
+
import { delimiter, dirname as dirname4, isAbsolute as isAbsolute3, join as join8 } from "node:path";
|
|
3096
3268
|
function defaultDeps() {
|
|
3097
3269
|
return {
|
|
3098
3270
|
platform: process.platform,
|
|
3099
3271
|
env: process.env,
|
|
3100
|
-
home:
|
|
3272
|
+
home: homedir9(),
|
|
3101
3273
|
execPath: process.execPath
|
|
3102
3274
|
};
|
|
3103
3275
|
}
|
|
@@ -3118,14 +3290,14 @@ function npmFromPath(deps) {
|
|
|
3118
3290
|
const dir = entry.trim().replace(/^"|"$/g, "");
|
|
3119
3291
|
if (!dir || !isAbsolute3(dir))
|
|
3120
3292
|
continue;
|
|
3121
|
-
if (isFile(
|
|
3293
|
+
if (isFile(join8(dir, name)))
|
|
3122
3294
|
return dir;
|
|
3123
3295
|
}
|
|
3124
3296
|
return null;
|
|
3125
3297
|
}
|
|
3126
3298
|
function npmAdjacentToNode(deps) {
|
|
3127
|
-
const dir =
|
|
3128
|
-
return isFile(
|
|
3299
|
+
const dir = dirname4(deps.execPath);
|
|
3300
|
+
return isFile(join8(dir, npmBinaryName(deps.platform))) ? dir : null;
|
|
3129
3301
|
}
|
|
3130
3302
|
function highestVersionedNodeBin(installsDir, name) {
|
|
3131
3303
|
let entries;
|
|
@@ -3134,8 +3306,8 @@ function highestVersionedNodeBin(installsDir, name) {
|
|
|
3134
3306
|
} catch {
|
|
3135
3307
|
return null;
|
|
3136
3308
|
}
|
|
3137
|
-
const candidates = entries.filter((v) => isFile(
|
|
3138
|
-
return candidates.length > 0 ?
|
|
3309
|
+
const candidates = entries.filter((v) => isFile(join8(installsDir, v, "bin", name))).sort((a, b) => compareVersionsDesc(a, b));
|
|
3310
|
+
return candidates.length > 0 ? join8(installsDir, candidates[0], "bin") : null;
|
|
3139
3311
|
}
|
|
3140
3312
|
function compareVersionsDesc(a, b) {
|
|
3141
3313
|
const pa = a.replace(/^v/, "").split(".").map((n) => Number.parseInt(n, 10));
|
|
@@ -3160,22 +3332,22 @@ function wellKnownNpmDirs(deps) {
|
|
|
3160
3332
|
const programFiles = env.ProgramFiles || "C:\\Program Files";
|
|
3161
3333
|
const appData = env.APPDATA;
|
|
3162
3334
|
const localAppData = env.LOCALAPPDATA;
|
|
3163
|
-
push(
|
|
3335
|
+
push(join8(programFiles, "nodejs"));
|
|
3164
3336
|
if (appData)
|
|
3165
|
-
push(
|
|
3337
|
+
push(join8(appData, "npm"));
|
|
3166
3338
|
if (localAppData)
|
|
3167
|
-
push(
|
|
3339
|
+
push(join8(localAppData, "Volta", "bin"));
|
|
3168
3340
|
if (env.NVM_SYMLINK)
|
|
3169
3341
|
push(env.NVM_SYMLINK);
|
|
3170
3342
|
} else {
|
|
3171
3343
|
if (env.NVM_BIN)
|
|
3172
3344
|
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",
|
|
3345
|
+
push(highestVersionedNodeBin(join8(home, ".nvm", "versions", "node"), name));
|
|
3346
|
+
push(highestVersionedNodeBin(join8(home, ".local", "share", "mise", "installs", "node"), name));
|
|
3347
|
+
push(highestVersionedNodeBin(join8(home, ".asdf", "installs", "nodejs"), name));
|
|
3348
|
+
push(join8(home, ".volta", "bin"));
|
|
3349
|
+
push(join8(home, ".asdf", "shims"));
|
|
3350
|
+
const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin", join8(home, ".local", "bin")]);
|
|
3179
3351
|
for (const dir of systemDirs)
|
|
3180
3352
|
push(dir);
|
|
3181
3353
|
}
|
|
@@ -3185,12 +3357,12 @@ function resolveNpm(deps = defaultDeps()) {
|
|
|
3185
3357
|
const name = npmBinaryName(deps.platform);
|
|
3186
3358
|
const onPath = npmFromPath(deps);
|
|
3187
3359
|
if (onPath)
|
|
3188
|
-
return { command:
|
|
3360
|
+
return { command: join8(onPath, name), binDir: onPath };
|
|
3189
3361
|
const adjacent = npmAdjacentToNode(deps);
|
|
3190
3362
|
if (adjacent)
|
|
3191
|
-
return { command:
|
|
3363
|
+
return { command: join8(adjacent, name), binDir: adjacent };
|
|
3192
3364
|
for (const dir of wellKnownNpmDirs(deps)) {
|
|
3193
|
-
const candidate =
|
|
3365
|
+
const candidate = join8(dir, name);
|
|
3194
3366
|
if (isFile(candidate))
|
|
3195
3367
|
return { command: candidate, binDir: dir };
|
|
3196
3368
|
}
|
|
@@ -3226,7 +3398,7 @@ var init_npm_resolver = () => {};
|
|
|
3226
3398
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
3227
3399
|
import { createHash as createHash3 } from "node:crypto";
|
|
3228
3400
|
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
|
|
3401
|
+
import { basename as basename2, dirname as dirname5, isAbsolute as isAbsolute4, join as join9, relative as relative2, resolve as resolve5, win32 } from "node:path";
|
|
3230
3402
|
import { Readable as Readable2 } from "node:stream";
|
|
3231
3403
|
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
3232
3404
|
function getPlatformInfo() {
|
|
@@ -3252,10 +3424,10 @@ function getManualInstallHint() {
|
|
|
3252
3424
|
}
|
|
3253
3425
|
async function ensureOnnxRuntime(storageDir) {
|
|
3254
3426
|
const info = getPlatformInfo();
|
|
3255
|
-
const ortVersionDir =
|
|
3427
|
+
const ortVersionDir = join9(storageDir, "onnxruntime", ORT_VERSION);
|
|
3256
3428
|
const libName = info?.libName ?? "libonnxruntime.dylib";
|
|
3257
3429
|
const resolvedOrtDir = resolveCachedOnnxRuntimeDir(ortVersionDir, libName);
|
|
3258
|
-
const libPath =
|
|
3430
|
+
const libPath = join9(resolvedOrtDir, libName);
|
|
3259
3431
|
if (existsSync6(libPath)) {
|
|
3260
3432
|
const meta = readOnnxInstalledMeta(ortVersionDir);
|
|
3261
3433
|
if (meta?.sha256) {
|
|
@@ -3285,9 +3457,9 @@ async function ensureOnnxRuntime(storageDir) {
|
|
|
3285
3457
|
warn(`ONNX Runtime auto-download not available for ${process.platform}/${process.arch}. Install manually: ${getManualInstallHint()}`);
|
|
3286
3458
|
return null;
|
|
3287
3459
|
}
|
|
3288
|
-
const onnxBaseDir =
|
|
3460
|
+
const onnxBaseDir = join9(storageDir, "onnxruntime");
|
|
3289
3461
|
mkdirSync5(onnxBaseDir, { recursive: true });
|
|
3290
|
-
const lockPath =
|
|
3462
|
+
const lockPath = join9(onnxBaseDir, ONNX_LOCK_FILE);
|
|
3291
3463
|
cleanupAbandonedStagingDirs(onnxBaseDir);
|
|
3292
3464
|
if (!acquireLock(lockPath)) {
|
|
3293
3465
|
warn(`ONNX Runtime install already in progress in another process (lock: ${lockPath}). Skipping.`);
|
|
@@ -3306,7 +3478,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
3306
3478
|
for (const entry of entries) {
|
|
3307
3479
|
if (!entry.startsWith(`${ORT_VERSION}.tmp.`))
|
|
3308
3480
|
continue;
|
|
3309
|
-
const stagingDir =
|
|
3481
|
+
const stagingDir = join9(onnxBaseDir, entry);
|
|
3310
3482
|
const parts = entry.split(".");
|
|
3311
3483
|
const pidStr = parts[parts.length - 2];
|
|
3312
3484
|
const pid = pidStr ? Number.parseInt(pidStr, 10) : NaN;
|
|
@@ -3343,7 +3515,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
3343
3515
|
}
|
|
3344
3516
|
function cleanupIncompleteTargetIfUnowned(ortDir) {
|
|
3345
3517
|
try {
|
|
3346
|
-
if (existsSync6(ortDir) && !existsSync6(
|
|
3518
|
+
if (existsSync6(ortDir) && !existsSync6(join9(ortDir, ONNX_INSTALLED_META_FILE))) {
|
|
3347
3519
|
log(`[onnx] removing half-populated install dir ${ortDir} (no meta file)`);
|
|
3348
3520
|
rmSync3(ortDir, { recursive: true, force: true });
|
|
3349
3521
|
}
|
|
@@ -3388,7 +3560,7 @@ function detectOnnxVersion(libDir, libName) {
|
|
|
3388
3560
|
if (version)
|
|
3389
3561
|
return version;
|
|
3390
3562
|
}
|
|
3391
|
-
const base =
|
|
3563
|
+
const base = join9(libDir, libName);
|
|
3392
3564
|
if (existsSync6(base)) {
|
|
3393
3565
|
try {
|
|
3394
3566
|
const real = realpathSync(base);
|
|
@@ -3427,6 +3599,17 @@ function pathEntriesForPlatform() {
|
|
|
3427
3599
|
return isAbsolute4(entry) || win32.isAbsolute(entry);
|
|
3428
3600
|
});
|
|
3429
3601
|
}
|
|
3602
|
+
function isWindowsSystem32Directory(dir) {
|
|
3603
|
+
if (process.platform !== "win32")
|
|
3604
|
+
return false;
|
|
3605
|
+
const normalizedDir = win32.resolve(dir).replace(/[\\/]+$/, "").toLowerCase();
|
|
3606
|
+
const windowsRoots = [process.env.SystemRoot, process.env.windir, "C:\\Windows"];
|
|
3607
|
+
return windowsRoots.some((root) => {
|
|
3608
|
+
if (!root)
|
|
3609
|
+
return false;
|
|
3610
|
+
return normalizedDir === win32.resolve(root, "System32").replace(/[\\/]+$/, "").toLowerCase();
|
|
3611
|
+
});
|
|
3612
|
+
}
|
|
3430
3613
|
function directoryContainsLibrary(dir, libName) {
|
|
3431
3614
|
try {
|
|
3432
3615
|
const entries = readdirSync2(dir);
|
|
@@ -3440,10 +3623,10 @@ function directoryContainsLibrary(dir, libName) {
|
|
|
3440
3623
|
}
|
|
3441
3624
|
}
|
|
3442
3625
|
function resolveCachedOnnxRuntimeDir(ortVersionDir, libName) {
|
|
3443
|
-
if (existsSync6(
|
|
3626
|
+
if (existsSync6(join9(ortVersionDir, libName)))
|
|
3444
3627
|
return ortVersionDir;
|
|
3445
|
-
const libSubdir =
|
|
3446
|
-
if (existsSync6(
|
|
3628
|
+
const libSubdir = join9(ortVersionDir, "lib");
|
|
3629
|
+
if (existsSync6(join9(libSubdir, libName)))
|
|
3447
3630
|
return libSubdir;
|
|
3448
3631
|
return ortVersionDir;
|
|
3449
3632
|
}
|
|
@@ -3458,12 +3641,12 @@ function findSystemOnnxRuntime(libName) {
|
|
|
3458
3641
|
} else if (process.platform === "win32") {
|
|
3459
3642
|
const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
|
|
3460
3643
|
const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
3461
|
-
searchPaths.push(
|
|
3644
|
+
searchPaths.push(join9(programFiles, "onnxruntime", "lib"), join9(programFiles, "Microsoft ONNX Runtime", "lib"), join9(programFiles, "Microsoft Machine Learning", "lib"), join9(programFilesX86, "onnxruntime", "lib"), ...(() => {
|
|
3462
3645
|
const nugetPaths = [];
|
|
3463
3646
|
const userProfile = process.env.USERPROFILE ?? "";
|
|
3464
3647
|
if (!userProfile)
|
|
3465
3648
|
return nugetPaths;
|
|
3466
|
-
const nugetPackageDir =
|
|
3649
|
+
const nugetPackageDir = join9(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
|
|
3467
3650
|
if (!existsSync6(nugetPackageDir))
|
|
3468
3651
|
return nugetPaths;
|
|
3469
3652
|
try {
|
|
@@ -3472,7 +3655,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
3472
3655
|
continue;
|
|
3473
3656
|
if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
|
|
3474
3657
|
continue;
|
|
3475
|
-
nugetPaths.push(
|
|
3658
|
+
nugetPaths.push(join9(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join9(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
|
|
3476
3659
|
}
|
|
3477
3660
|
} catch (err) {
|
|
3478
3661
|
warn(`Failed to scan NuGet ONNX Runtime cache ${nugetPackageDir}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -3494,7 +3677,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
3494
3677
|
});
|
|
3495
3678
|
const unknownVersionPaths = [];
|
|
3496
3679
|
for (const dir of uniquePaths) {
|
|
3497
|
-
const libPath =
|
|
3680
|
+
const libPath = join9(dir, libName);
|
|
3498
3681
|
if (process.platform === "win32") {
|
|
3499
3682
|
if (!directoryContainsLibrary(dir, libName))
|
|
3500
3683
|
continue;
|
|
@@ -3503,6 +3686,10 @@ function findSystemOnnxRuntime(libName) {
|
|
|
3503
3686
|
}
|
|
3504
3687
|
const version = detectOnnxVersion(dir, libName);
|
|
3505
3688
|
if (!version) {
|
|
3689
|
+
if (isWindowsSystem32Directory(dir)) {
|
|
3690
|
+
warn(`Skipping unversioned Windows system ONNX Runtime at ${dir}; falling through to AFT-managed download.`);
|
|
3691
|
+
continue;
|
|
3692
|
+
}
|
|
3506
3693
|
unknownVersionPaths.push(dir);
|
|
3507
3694
|
continue;
|
|
3508
3695
|
}
|
|
@@ -3530,7 +3717,7 @@ async function downloadFileWithCap(url, destPath) {
|
|
|
3530
3717
|
if (Number.isFinite(advertised) && advertised > MAX_DOWNLOAD_BYTES2) {
|
|
3531
3718
|
throw new Error(`Content-Length ${advertised} exceeds max ${MAX_DOWNLOAD_BYTES2}`);
|
|
3532
3719
|
}
|
|
3533
|
-
mkdirSync5(
|
|
3720
|
+
mkdirSync5(dirname5(destPath), { recursive: true });
|
|
3534
3721
|
let bytesWritten = 0;
|
|
3535
3722
|
const guard = new TransformStream({
|
|
3536
3723
|
transform(chunk, transformController) {
|
|
@@ -3560,11 +3747,11 @@ function validateExtractedTree(stagingRoot) {
|
|
|
3560
3747
|
const walk = (dir) => {
|
|
3561
3748
|
const entries = readdirSync2(dir);
|
|
3562
3749
|
for (const entry of entries) {
|
|
3563
|
-
const fullPath =
|
|
3750
|
+
const fullPath = join9(dir, entry);
|
|
3564
3751
|
const lst = lstatSync(fullPath);
|
|
3565
3752
|
if (lst.isSymbolicLink()) {
|
|
3566
3753
|
const linkTarget = readlinkSync(fullPath);
|
|
3567
|
-
const resolvedTarget = resolve5(
|
|
3754
|
+
const resolvedTarget = resolve5(dirname5(fullPath), linkTarget);
|
|
3568
3755
|
const rel2 = relative2(realRoot, resolvedTarget);
|
|
3569
3756
|
if (rel2.startsWith("..") || isAbsolute4(rel2) || win32.isAbsolute(rel2)) {
|
|
3570
3757
|
throw new Error(`extracted symlink ${fullPath} points outside staging root: ${linkTarget}`);
|
|
@@ -3595,7 +3782,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
3595
3782
|
const tmpDir = `${targetDir}.tmp.${process.pid}.${Date.now().toString(36)}`;
|
|
3596
3783
|
try {
|
|
3597
3784
|
mkdirSync5(tmpDir, { recursive: true });
|
|
3598
|
-
const archivePath =
|
|
3785
|
+
const archivePath = join9(tmpDir, `onnxruntime.${info.archiveType}`);
|
|
3599
3786
|
await downloadFileWithCap(url, archivePath);
|
|
3600
3787
|
const archiveSha256 = sha256File(archivePath);
|
|
3601
3788
|
log(`ONNX Runtime archive sha256=${archiveSha256}`);
|
|
@@ -3611,7 +3798,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
3611
3798
|
unlinkSync4(archivePath);
|
|
3612
3799
|
} catch {}
|
|
3613
3800
|
validateExtractedTree(tmpDir);
|
|
3614
|
-
const extractedDir =
|
|
3801
|
+
const extractedDir = join9(tmpDir, info.assetName, "lib");
|
|
3615
3802
|
if (!existsSync6(extractedDir)) {
|
|
3616
3803
|
throw new Error(`Expected directory not found: ${extractedDir}`);
|
|
3617
3804
|
}
|
|
@@ -3620,11 +3807,11 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
3620
3807
|
const realFiles = [];
|
|
3621
3808
|
const symlinks = [];
|
|
3622
3809
|
for (const libFile of libFiles) {
|
|
3623
|
-
const src =
|
|
3810
|
+
const src = join9(extractedDir, libFile);
|
|
3624
3811
|
try {
|
|
3625
|
-
const
|
|
3626
|
-
log(`ORT extract: ${libFile} — isSymlink=${
|
|
3627
|
-
if (
|
|
3812
|
+
const stat2 = lstatSync(src);
|
|
3813
|
+
log(`ORT extract: ${libFile} — isSymlink=${stat2.isSymbolicLink()}, isFile=${stat2.isFile()}, size=${stat2.size}`);
|
|
3814
|
+
if (stat2.isSymbolicLink()) {
|
|
3628
3815
|
symlinks.push({ name: libFile, target: readlinkSync(src) });
|
|
3629
3816
|
} else {
|
|
3630
3817
|
realFiles.push(libFile);
|
|
@@ -3635,7 +3822,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
3635
3822
|
}
|
|
3636
3823
|
}
|
|
3637
3824
|
copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks);
|
|
3638
|
-
const libPath =
|
|
3825
|
+
const libPath = join9(targetDir, info.libName);
|
|
3639
3826
|
let libHash = null;
|
|
3640
3827
|
try {
|
|
3641
3828
|
libHash = sha256File(libPath);
|
|
@@ -3660,8 +3847,8 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
3660
3847
|
function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, copyFile = copyFileSync3) {
|
|
3661
3848
|
const requiredLibs = new Set([info.libName]);
|
|
3662
3849
|
for (const libFile of realFiles) {
|
|
3663
|
-
const src =
|
|
3664
|
-
const dst =
|
|
3850
|
+
const src = join9(extractedDir, libFile);
|
|
3851
|
+
const dst = join9(targetDir, libFile);
|
|
3665
3852
|
try {
|
|
3666
3853
|
copyFile(src, dst);
|
|
3667
3854
|
if (process.platform !== "win32") {
|
|
@@ -3677,12 +3864,12 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
3677
3864
|
}
|
|
3678
3865
|
const targetRoot = realpathSync(targetDir);
|
|
3679
3866
|
for (const link of symlinks) {
|
|
3680
|
-
const dst =
|
|
3867
|
+
const dst = join9(targetDir, link.name);
|
|
3681
3868
|
try {
|
|
3682
3869
|
unlinkSync4(dst);
|
|
3683
3870
|
} catch {}
|
|
3684
|
-
const dstForContainment =
|
|
3685
|
-
const resolvedTarget = resolve5(
|
|
3871
|
+
const dstForContainment = join9(targetRoot, link.name);
|
|
3872
|
+
const resolvedTarget = resolve5(dirname5(dstForContainment), link.target);
|
|
3686
3873
|
if (!isPathInsideRoot(targetRoot, resolvedTarget)) {
|
|
3687
3874
|
const message = `ONNX Runtime symlink ${link.name} points outside install dir: ${link.target}`;
|
|
3688
3875
|
if (requiredLibs.has(link.name)) {
|
|
@@ -3702,7 +3889,7 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
3702
3889
|
log(`ORT extract: failed to symlink optional ${link.name}: ${symlinkErr}`);
|
|
3703
3890
|
}
|
|
3704
3891
|
}
|
|
3705
|
-
const requiredPath =
|
|
3892
|
+
const requiredPath = join9(targetDir, info.libName);
|
|
3706
3893
|
if (!existsSync6(requiredPath)) {
|
|
3707
3894
|
rmSync3(targetDir, { recursive: true, force: true });
|
|
3708
3895
|
throw new Error(`Required ONNX Runtime library missing after install: ${requiredPath}`);
|
|
@@ -3729,13 +3916,13 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
|
|
|
3729
3916
|
...sha256 ? { sha256 } : {},
|
|
3730
3917
|
archiveSha256
|
|
3731
3918
|
};
|
|
3732
|
-
writeFileSync3(
|
|
3919
|
+
writeFileSync3(join9(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
|
|
3733
3920
|
} catch (err) {
|
|
3734
3921
|
log(`[onnx] failed to write installed-meta in ${installDir}: ${err}`);
|
|
3735
3922
|
}
|
|
3736
3923
|
}
|
|
3737
3924
|
function readOnnxInstalledMeta(installDir) {
|
|
3738
|
-
const path2 =
|
|
3925
|
+
const path2 = join9(installDir, ONNX_INSTALLED_META_FILE);
|
|
3739
3926
|
try {
|
|
3740
3927
|
if (!statSync4(path2).isFile())
|
|
3741
3928
|
return null;
|
|
@@ -3873,7 +4060,7 @@ function isProcessAlive(pid) {
|
|
|
3873
4060
|
}
|
|
3874
4061
|
function cleanupOnnxRuntime(storageDir) {
|
|
3875
4062
|
try {
|
|
3876
|
-
const ortBase =
|
|
4063
|
+
const ortBase = join9(storageDir, "onnxruntime");
|
|
3877
4064
|
if (existsSync6(ortBase)) {
|
|
3878
4065
|
rmSync3(ortBase, { recursive: true, force: true });
|
|
3879
4066
|
}
|
|
@@ -3975,10 +4162,10 @@ function projectRootKeyHash(dir) {
|
|
|
3975
4162
|
var init_project_identity = () => {};
|
|
3976
4163
|
|
|
3977
4164
|
// ../aft-bridge/dist/pool.js
|
|
3978
|
-
import { homedir as
|
|
4165
|
+
import { homedir as homedir10 } from "node:os";
|
|
3979
4166
|
function canonicalHomeDir() {
|
|
3980
4167
|
try {
|
|
3981
|
-
const home =
|
|
4168
|
+
const home = homedir10();
|
|
3982
4169
|
if (!home)
|
|
3983
4170
|
return null;
|
|
3984
4171
|
return canonicalizeProjectRoot(home);
|
|
@@ -4004,6 +4191,7 @@ class BridgePool {
|
|
|
4004
4191
|
projectConfigLoader;
|
|
4005
4192
|
logger;
|
|
4006
4193
|
cleanupTimer = null;
|
|
4194
|
+
shutdownCalled = false;
|
|
4007
4195
|
constructor(binaryPath, options = {}, configOverrides = {}) {
|
|
4008
4196
|
this.binaryPath = binaryPath;
|
|
4009
4197
|
this.maxPoolSize = options.maxPoolSize ?? DEFAULT_MAX_POOL_SIZE;
|
|
@@ -4025,12 +4213,11 @@ class BridgePool {
|
|
|
4025
4213
|
childEnv: options.childEnv
|
|
4026
4214
|
};
|
|
4027
4215
|
this.configOverrides = configOverrides;
|
|
4028
|
-
|
|
4029
|
-
this.cleanupTimer = setInterval(() => this.cleanup(), CLEANUP_INTERVAL_MS);
|
|
4030
|
-
this.cleanupTimer.unref();
|
|
4031
|
-
}
|
|
4216
|
+
this.startCleanupTimer();
|
|
4032
4217
|
}
|
|
4033
4218
|
getActiveBridgeForRoot(projectRoot) {
|
|
4219
|
+
if (this.shutdownCalled)
|
|
4220
|
+
return null;
|
|
4034
4221
|
const key = normalizeKey(projectRoot);
|
|
4035
4222
|
const entry = this.bridges.get(key);
|
|
4036
4223
|
if (!entry?.bridge.isAlive())
|
|
@@ -4038,7 +4225,21 @@ class BridgePool {
|
|
|
4038
4225
|
entry.lastUsed = Date.now();
|
|
4039
4226
|
return entry.bridge;
|
|
4040
4227
|
}
|
|
4228
|
+
activeBridges() {
|
|
4229
|
+
if (this.shutdownCalled)
|
|
4230
|
+
return [];
|
|
4231
|
+
const alive = [];
|
|
4232
|
+
for (const entry of this.bridges.values()) {
|
|
4233
|
+
if (entry.bridge.isAlive())
|
|
4234
|
+
alive.push(entry.bridge);
|
|
4235
|
+
}
|
|
4236
|
+
return alive;
|
|
4237
|
+
}
|
|
4041
4238
|
getBridge(projectRoot) {
|
|
4239
|
+
if (this.shutdownCalled) {
|
|
4240
|
+
this.shutdownCalled = false;
|
|
4241
|
+
this.startCleanupTimer();
|
|
4242
|
+
}
|
|
4042
4243
|
const key = normalizeKey(projectRoot);
|
|
4043
4244
|
const existing = this.bridges.get(key);
|
|
4044
4245
|
if (existing) {
|
|
@@ -4048,15 +4249,7 @@ class BridgePool {
|
|
|
4048
4249
|
if (this.bridges.size >= this.maxPoolSize) {
|
|
4049
4250
|
this.evictLRU();
|
|
4050
4251
|
}
|
|
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
|
-
}
|
|
4252
|
+
const projectOverrides = this.loadProjectOverrides(key);
|
|
4060
4253
|
const mergedOverrides = { ...this.configOverrides, ...projectOverrides };
|
|
4061
4254
|
const bridge = new BinaryBridge(this.binaryPath, key, this.bridgeOptions, mergedOverrides);
|
|
4062
4255
|
this.bridges.set(key, { bridge, lastUsed: Date.now() });
|
|
@@ -4106,6 +4299,7 @@ class BridgePool {
|
|
|
4106
4299
|
}
|
|
4107
4300
|
async closeSession(_projectRoot, _session) {}
|
|
4108
4301
|
async shutdown() {
|
|
4302
|
+
this.shutdownCalled = true;
|
|
4109
4303
|
if (this.cleanupTimer) {
|
|
4110
4304
|
clearInterval(this.cleanupTimer);
|
|
4111
4305
|
this.cleanupTimer = null;
|
|
@@ -4118,6 +4312,9 @@ class BridgePool {
|
|
|
4118
4312
|
this.staleBridges.clear();
|
|
4119
4313
|
await Promise.allSettled(shutdowns);
|
|
4120
4314
|
}
|
|
4315
|
+
isShutdown() {
|
|
4316
|
+
return this.shutdownCalled;
|
|
4317
|
+
}
|
|
4121
4318
|
async replaceBinary(newPath) {
|
|
4122
4319
|
this.binaryPath = newPath;
|
|
4123
4320
|
for (const entry of this.bridges.values()) {
|
|
@@ -4127,6 +4324,12 @@ class BridgePool {
|
|
|
4127
4324
|
this.log(`Binary path updated to ${newPath}. Active bridges marked stale — next calls will use the new binary.`);
|
|
4128
4325
|
return newPath;
|
|
4129
4326
|
}
|
|
4327
|
+
startCleanupTimer() {
|
|
4328
|
+
if (!Number.isFinite(this.idleTimeoutMs) || this.cleanupTimer)
|
|
4329
|
+
return;
|
|
4330
|
+
this.cleanupTimer = setInterval(() => this.cleanup(), CLEANUP_INTERVAL_MS);
|
|
4331
|
+
this.cleanupTimer.unref();
|
|
4332
|
+
}
|
|
4130
4333
|
log(message, meta) {
|
|
4131
4334
|
const logger = this.logger ?? getActiveLogger();
|
|
4132
4335
|
if (logger) {
|
|
@@ -4158,6 +4361,36 @@ class BridgePool {
|
|
|
4158
4361
|
this.configOverrides[key] = value;
|
|
4159
4362
|
}
|
|
4160
4363
|
}
|
|
4364
|
+
async reconfigure(projectRoot, overrides) {
|
|
4365
|
+
const key = normalizeKey(projectRoot);
|
|
4366
|
+
for (const [name, value] of Object.entries(overrides)) {
|
|
4367
|
+
this.setConfigureOverride(name, value);
|
|
4368
|
+
}
|
|
4369
|
+
const bridge = this.getActiveBridgeForRoot(key);
|
|
4370
|
+
if (!bridge)
|
|
4371
|
+
return;
|
|
4372
|
+
const projectOverrides = this.loadProjectOverrides(key);
|
|
4373
|
+
const response = await bridge.send("configure", {
|
|
4374
|
+
project_root: key,
|
|
4375
|
+
...this.configOverrides,
|
|
4376
|
+
...projectOverrides,
|
|
4377
|
+
...overrides
|
|
4378
|
+
});
|
|
4379
|
+
if (response.success === false) {
|
|
4380
|
+
throw new Error(`configure refresh failed for ${key}: ${String(response.message ?? "unknown error")}`);
|
|
4381
|
+
}
|
|
4382
|
+
}
|
|
4383
|
+
loadProjectOverrides(key) {
|
|
4384
|
+
if (!this.projectConfigLoader)
|
|
4385
|
+
return {};
|
|
4386
|
+
try {
|
|
4387
|
+
return this.projectConfigLoader(key) ?? {};
|
|
4388
|
+
} catch (err) {
|
|
4389
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4390
|
+
this.error(`projectConfigLoader failed; using global overrides only: ${message}`);
|
|
4391
|
+
return {};
|
|
4392
|
+
}
|
|
4393
|
+
}
|
|
4161
4394
|
get size() {
|
|
4162
4395
|
return this.bridges.size;
|
|
4163
4396
|
}
|
|
@@ -4188,7 +4421,186 @@ var init_pool = __esm(() => {
|
|
|
4188
4421
|
};
|
|
4189
4422
|
});
|
|
4190
4423
|
|
|
4191
|
-
//
|
|
4424
|
+
// ../aft-bridge/dist/revivable-transport.js
|
|
4425
|
+
class RevivableTransportPool {
|
|
4426
|
+
createPool;
|
|
4427
|
+
onBinaryReplaced;
|
|
4428
|
+
activePool;
|
|
4429
|
+
revival = null;
|
|
4430
|
+
transports = new Map;
|
|
4431
|
+
configureOverrides = new Map;
|
|
4432
|
+
constructor(initialPool, createPool, onBinaryReplaced) {
|
|
4433
|
+
this.createPool = createPool;
|
|
4434
|
+
this.onBinaryReplaced = onBinaryReplaced;
|
|
4435
|
+
this.activePool = initialPool;
|
|
4436
|
+
}
|
|
4437
|
+
getBridge(projectRoot) {
|
|
4438
|
+
const key = canonicalizeProjectRoot(projectRoot);
|
|
4439
|
+
let transport = this.transports.get(key);
|
|
4440
|
+
if (!transport) {
|
|
4441
|
+
transport = new RevivableProjectTransport(this, key);
|
|
4442
|
+
this.transports.set(key, transport);
|
|
4443
|
+
}
|
|
4444
|
+
return transport;
|
|
4445
|
+
}
|
|
4446
|
+
activeBridges() {
|
|
4447
|
+
return this.activePool.activeBridges();
|
|
4448
|
+
}
|
|
4449
|
+
getActiveBridgeForRoot(projectRoot) {
|
|
4450
|
+
const key = canonicalizeProjectRoot(projectRoot);
|
|
4451
|
+
const bridge = this.currentBridge(key);
|
|
4452
|
+
if (!bridge)
|
|
4453
|
+
return null;
|
|
4454
|
+
const transport = this.getBridge(key);
|
|
4455
|
+
transport.refreshStatusSubscription(bridge);
|
|
4456
|
+
return transport;
|
|
4457
|
+
}
|
|
4458
|
+
async toolCall(projectRoot, runtime, name, rawArgs = {}, options) {
|
|
4459
|
+
return this.getBridge(projectRoot).toolCall(runtime.sessionID, name, rawArgs, options);
|
|
4460
|
+
}
|
|
4461
|
+
setConfigureOverride(key, value) {
|
|
4462
|
+
if (value === undefined)
|
|
4463
|
+
this.configureOverrides.delete(key);
|
|
4464
|
+
else
|
|
4465
|
+
this.configureOverrides.set(key, value);
|
|
4466
|
+
this.activePool.setConfigureOverride(key, value);
|
|
4467
|
+
}
|
|
4468
|
+
async reconfigure(projectRoot, overrides) {
|
|
4469
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
4470
|
+
if (value === undefined)
|
|
4471
|
+
this.configureOverrides.delete(key);
|
|
4472
|
+
else
|
|
4473
|
+
this.configureOverrides.set(key, value);
|
|
4474
|
+
}
|
|
4475
|
+
const pool = await this.ensureActivePool();
|
|
4476
|
+
await pool.reconfigure(projectRoot, overrides);
|
|
4477
|
+
}
|
|
4478
|
+
async replaceBinary(path2) {
|
|
4479
|
+
const replaced = await this.activePool.replaceBinary(path2);
|
|
4480
|
+
this.onBinaryReplaced?.(replaced);
|
|
4481
|
+
return replaced;
|
|
4482
|
+
}
|
|
4483
|
+
closeSession(projectRoot, session) {
|
|
4484
|
+
return this.activePool.closeSession(projectRoot, session);
|
|
4485
|
+
}
|
|
4486
|
+
async shutdown() {
|
|
4487
|
+
const revival = this.revival;
|
|
4488
|
+
if (revival) {
|
|
4489
|
+
await Promise.allSettled([revival]);
|
|
4490
|
+
}
|
|
4491
|
+
await this.activePool.shutdown();
|
|
4492
|
+
for (const transport of this.transports.values()) {
|
|
4493
|
+
transport.refreshStatusSubscription(null);
|
|
4494
|
+
}
|
|
4495
|
+
}
|
|
4496
|
+
isShutdown() {
|
|
4497
|
+
return this.activePool.isShutdown();
|
|
4498
|
+
}
|
|
4499
|
+
async ensureActivePool() {
|
|
4500
|
+
if (!this.activePool.isShutdown())
|
|
4501
|
+
return this.activePool;
|
|
4502
|
+
if (this.revival)
|
|
4503
|
+
return this.revival;
|
|
4504
|
+
warn("transport was shut down but new demand arrived — reviving (host quit hook fired without process exit?)");
|
|
4505
|
+
const revival = this.createPool().then((pool) => {
|
|
4506
|
+
for (const [key, value] of this.configureOverrides) {
|
|
4507
|
+
pool.setConfigureOverride(key, value);
|
|
4508
|
+
}
|
|
4509
|
+
this.activePool = pool;
|
|
4510
|
+
for (const [root, transport] of this.transports) {
|
|
4511
|
+
transport.refreshStatusSubscription(pool.getActiveBridgeForRoot(root));
|
|
4512
|
+
}
|
|
4513
|
+
return pool;
|
|
4514
|
+
});
|
|
4515
|
+
this.revival = revival;
|
|
4516
|
+
revival.then(() => {
|
|
4517
|
+
if (this.revival === revival)
|
|
4518
|
+
this.revival = null;
|
|
4519
|
+
}, () => {
|
|
4520
|
+
if (this.revival === revival)
|
|
4521
|
+
this.revival = null;
|
|
4522
|
+
});
|
|
4523
|
+
return revival;
|
|
4524
|
+
}
|
|
4525
|
+
currentBridge(projectRoot) {
|
|
4526
|
+
return this.activePool.getActiveBridgeForRoot(projectRoot);
|
|
4527
|
+
}
|
|
4528
|
+
async send(projectRoot, command, params, options) {
|
|
4529
|
+
const pool = await this.ensureActivePool();
|
|
4530
|
+
const bridge = pool.getBridge(projectRoot);
|
|
4531
|
+
this.getBridge(projectRoot).refreshStatusSubscription(bridge);
|
|
4532
|
+
return bridge.send(command, params, options);
|
|
4533
|
+
}
|
|
4534
|
+
async toolCallOnProject(projectRoot, sessionId, name, rawArgs, options) {
|
|
4535
|
+
const pool = await this.ensureActivePool();
|
|
4536
|
+
const bridge = pool.getBridge(projectRoot);
|
|
4537
|
+
this.getBridge(projectRoot).refreshStatusSubscription(bridge);
|
|
4538
|
+
return bridge.toolCall(sessionId, name, rawArgs, options);
|
|
4539
|
+
}
|
|
4540
|
+
}
|
|
4541
|
+
|
|
4542
|
+
class RevivableProjectTransport {
|
|
4543
|
+
owner;
|
|
4544
|
+
projectRoot;
|
|
4545
|
+
statusListeners = new Map;
|
|
4546
|
+
statusBridges = new Map;
|
|
4547
|
+
constructor(owner, projectRoot) {
|
|
4548
|
+
this.owner = owner;
|
|
4549
|
+
this.projectRoot = projectRoot;
|
|
4550
|
+
}
|
|
4551
|
+
getCwd() {
|
|
4552
|
+
return this.projectRoot;
|
|
4553
|
+
}
|
|
4554
|
+
getStatusBar() {
|
|
4555
|
+
return this.owner.currentBridge(this.projectRoot)?.getStatusBar();
|
|
4556
|
+
}
|
|
4557
|
+
getCachedStatus() {
|
|
4558
|
+
return this.owner.currentBridge(this.projectRoot)?.getCachedStatus() ?? null;
|
|
4559
|
+
}
|
|
4560
|
+
cacheStatusSnapshot(snapshot) {
|
|
4561
|
+
this.owner.currentBridge(this.projectRoot)?.cacheStatusSnapshot(snapshot);
|
|
4562
|
+
}
|
|
4563
|
+
send(command, params, options) {
|
|
4564
|
+
return this.owner.send(this.projectRoot, command, params, options);
|
|
4565
|
+
}
|
|
4566
|
+
toolCall(sessionId, name, rawArgs, options) {
|
|
4567
|
+
return this.owner.toolCallOnProject(this.projectRoot, sessionId, name, rawArgs, options);
|
|
4568
|
+
}
|
|
4569
|
+
subscribeStatus(listener) {
|
|
4570
|
+
if (this.statusListeners.has(listener))
|
|
4571
|
+
return () => this.removeStatusListener(listener);
|
|
4572
|
+
this.statusListeners.set(listener, () => {});
|
|
4573
|
+
this.bindStatusListener(listener, this.owner.currentBridge(this.projectRoot));
|
|
4574
|
+
return () => this.removeStatusListener(listener);
|
|
4575
|
+
}
|
|
4576
|
+
refreshStatusSubscription(bridge) {
|
|
4577
|
+
for (const listener of this.statusListeners.keys()) {
|
|
4578
|
+
this.bindStatusListener(listener, bridge);
|
|
4579
|
+
}
|
|
4580
|
+
}
|
|
4581
|
+
bindStatusListener(listener, bridge) {
|
|
4582
|
+
if (this.statusBridges.get(listener) === bridge)
|
|
4583
|
+
return;
|
|
4584
|
+
const previousUnsubscribe = this.statusListeners.get(listener);
|
|
4585
|
+
previousUnsubscribe?.();
|
|
4586
|
+
const maybe = bridge;
|
|
4587
|
+
const unsubscribe = maybe && typeof maybe.subscribeStatus === "function" ? maybe.subscribeStatus(listener) : () => {};
|
|
4588
|
+
this.statusListeners.set(listener, unsubscribe);
|
|
4589
|
+
this.statusBridges.set(listener, bridge);
|
|
4590
|
+
}
|
|
4591
|
+
removeStatusListener(listener) {
|
|
4592
|
+
const unsubscribe = this.statusListeners.get(listener);
|
|
4593
|
+
this.statusListeners.delete(listener);
|
|
4594
|
+
this.statusBridges.delete(listener);
|
|
4595
|
+
unsubscribe?.();
|
|
4596
|
+
}
|
|
4597
|
+
}
|
|
4598
|
+
var init_revivable_transport = __esm(() => {
|
|
4599
|
+
init_active_logger();
|
|
4600
|
+
init_project_identity();
|
|
4601
|
+
});
|
|
4602
|
+
|
|
4603
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.5.0/node_modules/@cortexkit/subc-client/dist/auth.js
|
|
4192
4604
|
import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
|
|
4193
4605
|
function computeProof(key, domain, clientNonce, serverNonce, daemonId) {
|
|
4194
4606
|
const mac = createHmac("sha256", Buffer.from(key));
|
|
@@ -4249,7 +4661,132 @@ var init_auth = __esm(() => {
|
|
|
4249
4661
|
};
|
|
4250
4662
|
});
|
|
4251
4663
|
|
|
4252
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
4664
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.5.0/node_modules/@cortexkit/subc-client/dist/envelope.js
|
|
4665
|
+
function isPureHeader(ty) {
|
|
4666
|
+
return ty === FrameType.Cancel || ty === FrameType.Ping || ty === FrameType.Pong || ty === FrameType.Goodbye;
|
|
4667
|
+
}
|
|
4668
|
+
function buildFlags(binary, priority, last, admissionClass = AdmissionClass.Normal) {
|
|
4669
|
+
let flags = 0;
|
|
4670
|
+
if (binary)
|
|
4671
|
+
flags |= FLAG_BINARY;
|
|
4672
|
+
flags |= priority << FLAG_PRIORITY_SHIFT;
|
|
4673
|
+
if (last)
|
|
4674
|
+
flags |= FLAG_LAST;
|
|
4675
|
+
flags |= admissionClass << FLAG_ADMISSION_SHIFT;
|
|
4676
|
+
return flags;
|
|
4677
|
+
}
|
|
4678
|
+
function encodeHeader(header) {
|
|
4679
|
+
const buffer = new Uint8Array(HEADER_LEN);
|
|
4680
|
+
const view = new DataView(buffer.buffer);
|
|
4681
|
+
view.setUint32(0, header.len, true);
|
|
4682
|
+
buffer[4] = header.ver;
|
|
4683
|
+
buffer[5] = header.ty;
|
|
4684
|
+
buffer[6] = header.flags;
|
|
4685
|
+
view.setUint16(7, header.channel, true);
|
|
4686
|
+
view.setUint32(9, header.epoch, true);
|
|
4687
|
+
view.setBigUint64(13, header.corr, true);
|
|
4688
|
+
return buffer;
|
|
4689
|
+
}
|
|
4690
|
+
function decodeHeader(bytes) {
|
|
4691
|
+
if (bytes.length < FROZEN_PREFIX_LEN) {
|
|
4692
|
+
throw new DecodeError(`header shorter than frozen prefix: have ${bytes.length} bytes`, "too_short_for_prefix");
|
|
4693
|
+
}
|
|
4694
|
+
const ver = bytes[4];
|
|
4695
|
+
if (ver !== PROTOCOL_VERSION)
|
|
4696
|
+
throw new DecodeError(`unsupported envelope version ${ver}`, "unsupported_version");
|
|
4697
|
+
if (bytes.length < HEADER_LEN) {
|
|
4698
|
+
throw new DecodeError(`header too short for version: have ${bytes.length} bytes, need ${HEADER_LEN}`, "too_short_for_header");
|
|
4699
|
+
}
|
|
4700
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
4701
|
+
const len = view.getUint32(0, true);
|
|
4702
|
+
const typeByte = bytes[5];
|
|
4703
|
+
if (typeByte > FRAME_TYPE_MAX)
|
|
4704
|
+
throw new DecodeError(`unknown frame type byte ${typeByte}`, "unknown_frame_type");
|
|
4705
|
+
const ty = typeByte;
|
|
4706
|
+
const flags = bytes[6];
|
|
4707
|
+
if ((flags & FLAG_RESERVED_MASK) !== 0) {
|
|
4708
|
+
throw new DecodeError(`reserved flag bits set in flags 0b${flags.toString(2).padStart(8, "0")}`, "reserved_flag_bits");
|
|
4709
|
+
}
|
|
4710
|
+
if ((flags & FLAG_PRIORITY_MASK) >> FLAG_PRIORITY_SHIFT === 3) {
|
|
4711
|
+
throw new DecodeError(`reserved priority bits set in flags 0b${flags.toString(2).padStart(8, "0")}`, "reserved_priority_bits");
|
|
4712
|
+
}
|
|
4713
|
+
const admission = (flags & FLAG_ADMISSION_MASK) >> FLAG_ADMISSION_SHIFT;
|
|
4714
|
+
if (admission === 3) {
|
|
4715
|
+
throw new DecodeError(`reserved admission class set in flags 0b${flags.toString(2).padStart(8, "0")}`, "reserved_admission_class");
|
|
4716
|
+
}
|
|
4717
|
+
if (admission === AdmissionClass.Sheddable && ty !== FrameType.Push && ty !== FrameType.StreamData) {
|
|
4718
|
+
throw new DecodeError(`SHEDDABLE admission class is illegal on ${FrameType[ty]} in flags 0b${flags.toString(2).padStart(8, "0")}`, "sheddable_illegal_frame_type");
|
|
4719
|
+
}
|
|
4720
|
+
const channel = view.getUint16(7, true);
|
|
4721
|
+
const epoch = view.getUint32(9, true);
|
|
4722
|
+
if (channel === 0 && epoch !== 0) {
|
|
4723
|
+
throw new DecodeError(`control channel carried nonzero epoch ${epoch}`, "nonzero_epoch_on_control_channel");
|
|
4724
|
+
}
|
|
4725
|
+
if (isPureHeader(ty) && len !== 0) {
|
|
4726
|
+
throw new DecodeError(`pure-header frame ${FrameType[ty]} declared non-zero body length ${len}`, "pure_header_frame_with_body");
|
|
4727
|
+
}
|
|
4728
|
+
return { len, ver, ty, flags, channel, epoch, corr: view.getBigUint64(13, true) };
|
|
4729
|
+
}
|
|
4730
|
+
function buildFrame(ty, flags, channel, epoch, corr, body) {
|
|
4731
|
+
return buildFrameWithVersion(PROTOCOL_VERSION, ty, flags, channel, epoch, corr, body);
|
|
4732
|
+
}
|
|
4733
|
+
function buildFrameWithVersion(ver, ty, flags, channel, epoch, corr, body) {
|
|
4734
|
+
if (body.length > MAX_FRAME_BODY_LEN) {
|
|
4735
|
+
throw new DecodeError(`frame body ${body.length} exceeds max ${MAX_FRAME_BODY_LEN}`, "frame_body_too_large");
|
|
4736
|
+
}
|
|
4737
|
+
const header = { len: body.length, ver, ty, flags, channel, epoch, corr };
|
|
4738
|
+
decodeHeader(encodeHeader(header));
|
|
4739
|
+
return { header, body };
|
|
4740
|
+
}
|
|
4741
|
+
function encodeFrame(frame) {
|
|
4742
|
+
if (frame.header.len !== frame.body.length) {
|
|
4743
|
+
throw new DecodeError(`frame header length ${frame.header.len} does not match body length ${frame.body.length}`, "frame_length_mismatch");
|
|
4744
|
+
}
|
|
4745
|
+
const header = encodeHeader(frame.header);
|
|
4746
|
+
const output = new Uint8Array(header.length + frame.body.length);
|
|
4747
|
+
output.set(header, 0);
|
|
4748
|
+
output.set(frame.body, header.length);
|
|
4749
|
+
return output;
|
|
4750
|
+
}
|
|
4751
|
+
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;
|
|
4752
|
+
var init_envelope = __esm(() => {
|
|
4753
|
+
MAX_FRAME_BODY_LEN = 64 * 1024 * 1024;
|
|
4754
|
+
(function(FrameType2) {
|
|
4755
|
+
FrameType2[FrameType2["Request"] = 0] = "Request";
|
|
4756
|
+
FrameType2[FrameType2["Response"] = 1] = "Response";
|
|
4757
|
+
FrameType2[FrameType2["Push"] = 2] = "Push";
|
|
4758
|
+
FrameType2[FrameType2["StreamData"] = 3] = "StreamData";
|
|
4759
|
+
FrameType2[FrameType2["StreamEnd"] = 4] = "StreamEnd";
|
|
4760
|
+
FrameType2[FrameType2["Error"] = 5] = "Error";
|
|
4761
|
+
FrameType2[FrameType2["Cancel"] = 6] = "Cancel";
|
|
4762
|
+
FrameType2[FrameType2["Ping"] = 7] = "Ping";
|
|
4763
|
+
FrameType2[FrameType2["Pong"] = 8] = "Pong";
|
|
4764
|
+
FrameType2[FrameType2["Hello"] = 9] = "Hello";
|
|
4765
|
+
FrameType2[FrameType2["HelloAck"] = 10] = "HelloAck";
|
|
4766
|
+
FrameType2[FrameType2["Goodbye"] = 11] = "Goodbye";
|
|
4767
|
+
})(FrameType || (FrameType = {}));
|
|
4768
|
+
FRAME_TYPE_MAX = FrameType.Goodbye;
|
|
4769
|
+
(function(Priority2) {
|
|
4770
|
+
Priority2[Priority2["Passive"] = 0] = "Passive";
|
|
4771
|
+
Priority2[Priority2["Interactive"] = 1] = "Interactive";
|
|
4772
|
+
Priority2[Priority2["Background"] = 2] = "Background";
|
|
4773
|
+
})(Priority || (Priority = {}));
|
|
4774
|
+
(function(AdmissionClass2) {
|
|
4775
|
+
AdmissionClass2[AdmissionClass2["Normal"] = 0] = "Normal";
|
|
4776
|
+
AdmissionClass2[AdmissionClass2["Expedite"] = 1] = "Expedite";
|
|
4777
|
+
AdmissionClass2[AdmissionClass2["Sheddable"] = 2] = "Sheddable";
|
|
4778
|
+
})(AdmissionClass || (AdmissionClass = {}));
|
|
4779
|
+
DecodeError = class DecodeError extends Error {
|
|
4780
|
+
code;
|
|
4781
|
+
constructor(message, code) {
|
|
4782
|
+
super(message);
|
|
4783
|
+
this.code = code;
|
|
4784
|
+
this.name = "DecodeError";
|
|
4785
|
+
}
|
|
4786
|
+
};
|
|
4787
|
+
});
|
|
4788
|
+
|
|
4789
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.5.0/node_modules/@cortexkit/subc-client/dist/connection-file.js
|
|
4253
4790
|
import { promises as fs } from "node:fs";
|
|
4254
4791
|
function toBytes(value, field) {
|
|
4255
4792
|
if (!Array.isArray(value) || value.some((n) => typeof n !== "number")) {
|
|
@@ -4274,8 +4811,8 @@ function validate(info) {
|
|
|
4274
4811
|
async function verifyOwnerOnly(path2) {
|
|
4275
4812
|
if (process.platform === "win32")
|
|
4276
4813
|
return;
|
|
4277
|
-
const
|
|
4278
|
-
const mode =
|
|
4814
|
+
const stat2 = await fs.stat(path2);
|
|
4815
|
+
const mode = stat2.mode & 511;
|
|
4279
4816
|
if ((mode & 63) !== 0) {
|
|
4280
4817
|
throw new ConnectionFileError(`connection file ${path2} has insecure permissions 0o${mode.toString(8)}; expected owner-only 0600`);
|
|
4281
4818
|
}
|
|
@@ -4289,6 +4826,10 @@ async function readConnectionFile(path2) {
|
|
|
4289
4826
|
} catch (err) {
|
|
4290
4827
|
throw new ConnectionFileError(`connection file JSON read failed for ${path2}: ${String(err)}`);
|
|
4291
4828
|
}
|
|
4829
|
+
const wireVersion = parsed.wire_version;
|
|
4830
|
+
if (wireVersion !== undefined && wireVersion !== PROTOCOL_VERSION) {
|
|
4831
|
+
throw new ConnectionFileError(`connection file wire_version ${String(wireVersion)} but this client speaks ${PROTOCOL_VERSION}; the client library must be upgraded`);
|
|
4832
|
+
}
|
|
4292
4833
|
const endpointsRaw = parsed.endpoints;
|
|
4293
4834
|
if (!Array.isArray(endpointsRaw)) {
|
|
4294
4835
|
throw new ConnectionFileError("connection file 'endpoints' must be an array");
|
|
@@ -4313,116 +4854,59 @@ async function readConnectionFile(path2) {
|
|
|
4313
4854
|
}
|
|
4314
4855
|
var SCHEMA_VERSION = 1, MIN_KEY_LEN = 32, DAEMON_ID_LEN = 16, ConnectionFileError;
|
|
4315
4856
|
var init_connection_file = __esm(() => {
|
|
4857
|
+
init_envelope();
|
|
4316
4858
|
ConnectionFileError = class ConnectionFileError extends Error {
|
|
4317
4859
|
};
|
|
4318
4860
|
});
|
|
4319
4861
|
|
|
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 {
|
|
4862
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.5.0/node_modules/@cortexkit/subc-client/dist/route-handle.js
|
|
4863
|
+
class RouteHandle {
|
|
4864
|
+
channel;
|
|
4865
|
+
epoch;
|
|
4866
|
+
constructor(channel, epoch, token) {
|
|
4867
|
+
if (!Number.isInteger(channel) || channel <= 0 || channel > 65535) {
|
|
4868
|
+
throw new RangeError(`route channel must be an integer in 1..65535, got ${channel}`);
|
|
4869
|
+
}
|
|
4870
|
+
if (!Number.isInteger(epoch) || epoch <= 0 || epoch > 4294967295) {
|
|
4871
|
+
throw new RangeError(`route epoch must be an integer in 1..4294967295, got ${epoch}`);
|
|
4872
|
+
}
|
|
4873
|
+
this.channel = channel;
|
|
4874
|
+
this.epoch = epoch;
|
|
4875
|
+
connectionToken.set(this, token);
|
|
4876
|
+
Object.freeze(this);
|
|
4877
|
+
}
|
|
4878
|
+
static create(channel, epoch, token) {
|
|
4879
|
+
return new RouteHandle(channel, epoch, token);
|
|
4880
|
+
}
|
|
4881
|
+
}
|
|
4882
|
+
function createRouteHandle(channel, epoch, token) {
|
|
4883
|
+
const factory = RouteHandle;
|
|
4884
|
+
return factory.create(channel, epoch, token);
|
|
4885
|
+
}
|
|
4886
|
+
function newConnectionToken() {
|
|
4887
|
+
return Object.freeze({});
|
|
4888
|
+
}
|
|
4889
|
+
function belongsToConnection(handle, token) {
|
|
4890
|
+
return connectionToken.get(handle) === token;
|
|
4891
|
+
}
|
|
4892
|
+
function sameRouteHandle(left, right) {
|
|
4893
|
+
return left === right;
|
|
4894
|
+
}
|
|
4895
|
+
var connectionToken, StaleRouteHandleError;
|
|
4896
|
+
var init_route_handle = __esm(() => {
|
|
4897
|
+
connectionToken = new WeakMap;
|
|
4898
|
+
StaleRouteHandleError = class StaleRouteHandleError extends Error {
|
|
4899
|
+
handle;
|
|
4900
|
+
code = "stale_route_handle";
|
|
4901
|
+
constructor(handle) {
|
|
4902
|
+
super(`route handle (${handle.channel}, ${handle.epoch}) is not live on the current connection`);
|
|
4903
|
+
this.handle = handle;
|
|
4904
|
+
this.name = "StaleRouteHandleError";
|
|
4905
|
+
}
|
|
4422
4906
|
};
|
|
4423
4907
|
});
|
|
4424
4908
|
|
|
4425
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
4909
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.5.0/node_modules/@cortexkit/subc-client/dist/socket.js
|
|
4426
4910
|
import net from "node:net";
|
|
4427
4911
|
|
|
4428
4912
|
class SubcSocket {
|
|
@@ -4471,6 +4955,24 @@ class SubcSocket {
|
|
|
4471
4955
|
});
|
|
4472
4956
|
});
|
|
4473
4957
|
}
|
|
4958
|
+
async readFrame(headerDeadlineMs, bodyDeadline, onHeader) {
|
|
4959
|
+
const prefix = await this.readExact(FROZEN_PREFIX_LEN, headerDeadlineMs);
|
|
4960
|
+
const version = prefix[4];
|
|
4961
|
+
if (version !== PROTOCOL_VERSION)
|
|
4962
|
+
throw new DecodeError(`unsupported envelope version ${version}`, "unsupported_version");
|
|
4963
|
+
const remainder = await this.readExact(HEADER_LEN - FROZEN_PREFIX_LEN, headerDeadlineMs);
|
|
4964
|
+
const headerBytes = new Uint8Array(HEADER_LEN);
|
|
4965
|
+
headerBytes.set(prefix);
|
|
4966
|
+
headerBytes.set(remainder, FROZEN_PREFIX_LEN);
|
|
4967
|
+
const header = decodeHeader(headerBytes);
|
|
4968
|
+
if (header.len > MAX_FRAME_BODY_LEN) {
|
|
4969
|
+
throw new DecodeError(`frame body ${header.len} exceeds max ${MAX_FRAME_BODY_LEN}`, "frame_body_too_large");
|
|
4970
|
+
}
|
|
4971
|
+
onHeader?.();
|
|
4972
|
+
const bodyDeadlineMs = typeof bodyDeadline === "number" ? bodyDeadline : Date.now() + bodyDeadline.afterHeaderMs;
|
|
4973
|
+
const body = header.len === 0 ? new Uint8Array(0) : await this.readExact(header.len, bodyDeadlineMs);
|
|
4974
|
+
return { header, body };
|
|
4975
|
+
}
|
|
4474
4976
|
readExact(n, deadlineMs) {
|
|
4475
4977
|
if (this.waiter) {
|
|
4476
4978
|
return Promise.reject(new Error("concurrent readExact is not supported"));
|
|
@@ -4593,6 +5095,7 @@ class SubcSocket {
|
|
|
4593
5095
|
}
|
|
4594
5096
|
var SocketClosedError, SocketTimeoutError, SocketWriteNotQueuedError, SocketWriteQueuedError;
|
|
4595
5097
|
var init_socket = __esm(() => {
|
|
5098
|
+
init_envelope();
|
|
4596
5099
|
SocketClosedError = class SocketClosedError extends Error {
|
|
4597
5100
|
};
|
|
4598
5101
|
SocketTimeoutError = class SocketTimeoutError extends Error {
|
|
@@ -4613,7 +5116,7 @@ var init_socket = __esm(() => {
|
|
|
4613
5116
|
};
|
|
4614
5117
|
});
|
|
4615
5118
|
|
|
4616
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
5119
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.5.0/node_modules/@cortexkit/subc-client/dist/client.js
|
|
4617
5120
|
import { promises as fs2 } from "node:fs";
|
|
4618
5121
|
import { debuglog } from "node:util";
|
|
4619
5122
|
|
|
@@ -4623,7 +5126,11 @@ class SubcClient {
|
|
|
4623
5126
|
opts;
|
|
4624
5127
|
nextCorr = 1n;
|
|
4625
5128
|
pending = new Map;
|
|
5129
|
+
lateResponses = new Map;
|
|
4626
5130
|
routes = new Map;
|
|
5131
|
+
liveRoutes = new Map;
|
|
5132
|
+
connectionToken = newConnectionToken();
|
|
5133
|
+
ingressEpochDropCount = 0;
|
|
4627
5134
|
closedErr = null;
|
|
4628
5135
|
closeStarted = false;
|
|
4629
5136
|
reconnecting = null;
|
|
@@ -4651,40 +5158,71 @@ class SubcClient {
|
|
|
4651
5158
|
}
|
|
4652
5159
|
async routeOpen(target, identity, opts = {}) {
|
|
4653
5160
|
const consumerIdentity = routeOpenConsumerIdentity(opts);
|
|
5161
|
+
const consumerCapabilities = opts.consumerCapabilities;
|
|
4654
5162
|
const body = this.encode({
|
|
4655
5163
|
op: "route.open",
|
|
4656
5164
|
target,
|
|
4657
5165
|
identity,
|
|
4658
|
-
...consumerIdentity ? { consumer_identity: consumerIdentity } : {}
|
|
5166
|
+
...consumerIdentity ? { consumer_identity: consumerIdentity } : {},
|
|
5167
|
+
...consumerCapabilities !== undefined ? { consumer_capabilities: consumerCapabilities } : {}
|
|
4659
5168
|
});
|
|
4660
|
-
|
|
4661
|
-
const
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
5169
|
+
let installed = null;
|
|
5170
|
+
const install = (frame) => {
|
|
5171
|
+
if (frame.header.ty !== FrameType.Response)
|
|
5172
|
+
return true;
|
|
5173
|
+
const parsed = this.parseJson(frame);
|
|
5174
|
+
if (typeof parsed.route_channel !== "number" || typeof parsed.route_epoch !== "number") {
|
|
5175
|
+
throw new SubcError(`route.open returned no route handle: ${JSON.stringify(parsed)}`);
|
|
5176
|
+
}
|
|
5177
|
+
installed = this.installRoute(parsed.route_channel, parsed.route_epoch);
|
|
5178
|
+
return true;
|
|
5179
|
+
};
|
|
5180
|
+
const closeLateRoute = (frame) => {
|
|
5181
|
+
if (frame.header.ty !== FrameType.Response)
|
|
5182
|
+
return;
|
|
5183
|
+
try {
|
|
5184
|
+
const parsed = this.parseJson(frame);
|
|
5185
|
+
if (typeof parsed.route_channel !== "number" || typeof parsed.route_epoch !== "number")
|
|
5186
|
+
return;
|
|
5187
|
+
const lateHandle = this.installRoute(parsed.route_channel, parsed.route_epoch);
|
|
5188
|
+
this.failHandle(lateHandle, new SubcError("late route.open was closed", "route_closed"));
|
|
5189
|
+
this.liveRoutes.delete(lateHandle.channel);
|
|
5190
|
+
this.sendRouteGoodbye(lateHandle, true);
|
|
5191
|
+
} catch {
|
|
5192
|
+
this.closeConnectionAfterCleanupFailure();
|
|
5193
|
+
}
|
|
5194
|
+
};
|
|
5195
|
+
await this.controlRpc(body, install, closeLateRoute);
|
|
5196
|
+
if (!installed)
|
|
5197
|
+
throw new SubcError("route.open response was not installed");
|
|
5198
|
+
return installed;
|
|
4666
5199
|
}
|
|
4667
|
-
async request(
|
|
5200
|
+
async request(handle, body, opts = {}) {
|
|
5201
|
+
this.assertLiveHandle(handle);
|
|
4668
5202
|
const bytes = body instanceof Uint8Array ? body : this.encode(body);
|
|
4669
5203
|
const priority = opts.priority ?? Priority.Interactive;
|
|
4670
|
-
const
|
|
5204
|
+
const admission = opts.admissionClass ?? AdmissionClass.Normal;
|
|
5205
|
+
const reply = await this.send(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress);
|
|
4671
5206
|
return this.parseJson(reply);
|
|
4672
5207
|
}
|
|
4673
5208
|
async call(moduleId, method, params, opts = {}) {
|
|
4674
5209
|
const body = params === undefined ? { method } : { method, params };
|
|
4675
5210
|
let retriedUnknownChannel = false;
|
|
4676
5211
|
for (;; ) {
|
|
4677
|
-
const
|
|
5212
|
+
const routeHandle = await this.cachedRouteHandle(moduleId, opts);
|
|
4678
5213
|
try {
|
|
4679
|
-
return await this.managedRequest(
|
|
5214
|
+
return await this.managedRequest(routeHandle, body, opts);
|
|
4680
5215
|
} catch (err) {
|
|
4681
5216
|
if (!(err instanceof SubcCallError))
|
|
4682
5217
|
throw this.terminalCallError("managed call failed", err);
|
|
4683
5218
|
if (err.code === "unknown_channel" && !retriedUnknownChannel && !this.closeStarted) {
|
|
4684
5219
|
retriedUnknownChannel = true;
|
|
4685
|
-
this.
|
|
5220
|
+
this.evictRouteHandle(routeHandle);
|
|
4686
5221
|
continue;
|
|
4687
5222
|
}
|
|
5223
|
+
if (err.code === "unknown_channel" && retriedUnknownChannel) {
|
|
5224
|
+
this.evictRouteHandle(routeHandle);
|
|
5225
|
+
}
|
|
4688
5226
|
if (err.kind === "not_sent") {
|
|
4689
5227
|
try {
|
|
4690
5228
|
await this.reconnectAfterDrop(err);
|
|
@@ -4700,29 +5238,31 @@ class SubcClient {
|
|
|
4700
5238
|
}
|
|
4701
5239
|
}
|
|
4702
5240
|
}
|
|
4703
|
-
subscribe(
|
|
5241
|
+
subscribe(handle, body, onEvent, opts = {}) {
|
|
5242
|
+
this.assertLiveHandle(handle);
|
|
4704
5243
|
const bytes = body instanceof Uint8Array ? body : this.encode(body);
|
|
4705
5244
|
const priority = opts.priority ?? Priority.Interactive;
|
|
4706
|
-
const
|
|
4707
|
-
const
|
|
5245
|
+
const admission = opts.admissionClass ?? AdmissionClass.Normal;
|
|
5246
|
+
const corr = this.allocateCorr();
|
|
5247
|
+
const key = pendingKey(handle, corr);
|
|
4708
5248
|
const closed = new Promise((resolve7, reject) => {
|
|
4709
5249
|
if (this.closedErr) {
|
|
4710
5250
|
reject(this.closedErr);
|
|
4711
5251
|
return;
|
|
4712
5252
|
}
|
|
4713
5253
|
this.pending.set(key, {
|
|
4714
|
-
|
|
5254
|
+
handle,
|
|
4715
5255
|
resolve: () => resolve7(),
|
|
4716
5256
|
reject,
|
|
4717
5257
|
onProgress: onEvent,
|
|
4718
5258
|
timer: null,
|
|
4719
5259
|
subscription: true
|
|
4720
5260
|
});
|
|
4721
|
-
const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false),
|
|
5261
|
+
const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), handle.channel, handle.epoch, corr, bytes);
|
|
4722
5262
|
this.sock.write(encodeFrame(frame), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS).catch((err) => {
|
|
4723
|
-
const
|
|
4724
|
-
if (
|
|
4725
|
-
this.rejectPending(key,
|
|
5263
|
+
const pending = this.pending.get(key);
|
|
5264
|
+
if (pending)
|
|
5265
|
+
this.rejectPending(key, pending, err instanceof Error ? err : new SubcError(String(err)));
|
|
4726
5266
|
});
|
|
4727
5267
|
});
|
|
4728
5268
|
let cancelled = false;
|
|
@@ -4730,45 +5270,77 @@ class SubcClient {
|
|
|
4730
5270
|
if (cancelled)
|
|
4731
5271
|
return;
|
|
4732
5272
|
cancelled = true;
|
|
4733
|
-
|
|
4734
|
-
this.sock.write(encodeFrame(cancel), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS).catch(() => {});
|
|
5273
|
+
this.cancel(handle, corr, priority);
|
|
4735
5274
|
};
|
|
4736
5275
|
return { unsubscribe, closed };
|
|
4737
5276
|
}
|
|
4738
|
-
|
|
5277
|
+
cancel(handle, corr, priority = Priority.Interactive) {
|
|
5278
|
+
this.assertLiveHandle(handle);
|
|
5279
|
+
const cancel = buildFrame(FrameType.Cancel, buildFlags(false, priority, false), handle.channel, handle.epoch, corr, EMPTY_BODY);
|
|
5280
|
+
this.sock.write(encodeFrame(cancel), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS).catch(() => {
|
|
5281
|
+
return;
|
|
5282
|
+
});
|
|
5283
|
+
}
|
|
5284
|
+
async routePoll(handle, kind) {
|
|
5285
|
+
this.assertLiveHandle(handle);
|
|
5286
|
+
const body = this.encode({
|
|
5287
|
+
op: "route.poll",
|
|
5288
|
+
route_channel: handle.channel,
|
|
5289
|
+
route_epoch: handle.epoch,
|
|
5290
|
+
kind
|
|
5291
|
+
});
|
|
5292
|
+
const reply = await this.controlRpc(body, (frame) => {
|
|
5293
|
+
if (frame.header.ty !== FrameType.Response)
|
|
5294
|
+
return true;
|
|
5295
|
+
const parsed = this.parseJson(frame);
|
|
5296
|
+
return parsed.route_channel === handle.channel && parsed.route_epoch === handle.epoch;
|
|
5297
|
+
});
|
|
5298
|
+
return this.parseJson(reply);
|
|
5299
|
+
}
|
|
5300
|
+
async closeRoute(handle, opts = {}) {
|
|
5301
|
+
this.assertLiveHandle(handle);
|
|
5302
|
+
for (const [key, cached] of this.routes) {
|
|
5303
|
+
if (cached.handle && sameRouteHandle(cached.handle, handle)) {
|
|
5304
|
+
cached.closed = true;
|
|
5305
|
+
cached.handle = null;
|
|
5306
|
+
this.routes.delete(key);
|
|
5307
|
+
}
|
|
5308
|
+
}
|
|
5309
|
+
if (opts.drain)
|
|
5310
|
+
await this.drainUnaryOnHandle(handle);
|
|
5311
|
+
this.failHandle(handle, new SubcError("route closed by closeRoute", "route_closed"));
|
|
5312
|
+
if (this.liveRoutes.get(handle.channel) === handle)
|
|
5313
|
+
this.liveRoutes.delete(handle.channel);
|
|
5314
|
+
this.sendRouteGoodbye(handle);
|
|
5315
|
+
}
|
|
5316
|
+
async closeManagedRoute(target, identity, opts = {}) {
|
|
4739
5317
|
const key = routeCacheKey(target, identity, routeOpenConsumerIdentity(opts));
|
|
4740
5318
|
const cached = this.routes.get(key);
|
|
4741
5319
|
if (!cached)
|
|
4742
5320
|
return;
|
|
4743
5321
|
cached.closed = true;
|
|
4744
5322
|
this.routes.delete(key);
|
|
4745
|
-
const
|
|
4746
|
-
cached.
|
|
4747
|
-
if (
|
|
4748
|
-
await this.
|
|
5323
|
+
const handle = cached.handle;
|
|
5324
|
+
cached.handle = null;
|
|
5325
|
+
if (handle)
|
|
5326
|
+
await this.closeRoute(handle, opts);
|
|
4749
5327
|
}
|
|
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);
|
|
5328
|
+
async closeRouteChannel(handle, opts = {}) {
|
|
5329
|
+
await this.closeRoute(handle, opts);
|
|
4758
5330
|
}
|
|
4759
5331
|
close() {
|
|
4760
5332
|
this.closeStarted = true;
|
|
4761
5333
|
this.fail(new SubcError("client closed"));
|
|
4762
5334
|
this.sock.close();
|
|
4763
5335
|
}
|
|
4764
|
-
|
|
5336
|
+
drainUnaryOnHandle(handle) {
|
|
4765
5337
|
const waiters = [];
|
|
4766
5338
|
for (const pending of this.pending.values()) {
|
|
4767
|
-
if (pending.
|
|
5339
|
+
if (pending.handle === handle && !pending.subscription) {
|
|
4768
5340
|
waiters.push(new Promise((resolve7) => {
|
|
4769
|
-
const
|
|
5341
|
+
const previous = pending.onSettle;
|
|
4770
5342
|
pending.onSettle = () => {
|
|
4771
|
-
|
|
5343
|
+
previous?.();
|
|
4772
5344
|
resolve7();
|
|
4773
5345
|
};
|
|
4774
5346
|
}));
|
|
@@ -4778,11 +5350,21 @@ class SubcClient {
|
|
|
4778
5350
|
return;
|
|
4779
5351
|
});
|
|
4780
5352
|
}
|
|
4781
|
-
sendRouteGoodbye(
|
|
4782
|
-
|
|
5353
|
+
sendRouteGoodbye(handle, closeOnQueueFailure = false) {
|
|
5354
|
+
this.assertLiveConnection(handle);
|
|
5355
|
+
if (this.closedErr) {
|
|
5356
|
+
if (closeOnQueueFailure)
|
|
5357
|
+
this.closeConnectionAfterCleanupFailure();
|
|
4783
5358
|
return;
|
|
4784
|
-
|
|
4785
|
-
|
|
5359
|
+
}
|
|
5360
|
+
const goodbye = buildFrame(FrameType.Goodbye, buildFlags(false, Priority.Interactive, false), handle.channel, handle.epoch, 0n, EMPTY_BODY);
|
|
5361
|
+
const write = this.sock.writeTracked(encodeFrame(goodbye), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS);
|
|
5362
|
+
if (!write.queued && closeOnQueueFailure)
|
|
5363
|
+
this.closeConnectionAfterCleanupFailure();
|
|
5364
|
+
write.completed.catch(() => {
|
|
5365
|
+
if (closeOnQueueFailure && !write.queued)
|
|
5366
|
+
this.closeConnectionAfterCleanupFailure();
|
|
5367
|
+
});
|
|
4786
5368
|
}
|
|
4787
5369
|
static async openConnection(opts) {
|
|
4788
5370
|
const conn = await readConnectionFile(opts.connectionFile);
|
|
@@ -4797,37 +5379,48 @@ class SubcClient {
|
|
|
4797
5379
|
}
|
|
4798
5380
|
return { sock, conn };
|
|
4799
5381
|
}
|
|
4800
|
-
async controlRpc(body) {
|
|
4801
|
-
return this.send(
|
|
5382
|
+
async controlRpc(body, acceptFrame, onLateResponse) {
|
|
5383
|
+
return this.send(null, body, Priority.Interactive, AdmissionClass.Normal, undefined, undefined, acceptFrame, onLateResponse);
|
|
4802
5384
|
}
|
|
4803
|
-
send(
|
|
5385
|
+
send(handle, body, priority, admission, timeoutMs, onProgress, acceptFrame, onLateResponse) {
|
|
5386
|
+
if (handle)
|
|
5387
|
+
this.assertLiveHandle(handle);
|
|
4804
5388
|
if (this.closedErr)
|
|
4805
5389
|
return Promise.reject(this.closedErr);
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
5390
|
+
let corr;
|
|
5391
|
+
try {
|
|
5392
|
+
corr = this.allocateCorr();
|
|
5393
|
+
} catch (error2) {
|
|
5394
|
+
return Promise.reject(error2);
|
|
5395
|
+
}
|
|
5396
|
+
const key = pendingKey(handle, corr);
|
|
5397
|
+
const channel = handle?.channel ?? 0;
|
|
5398
|
+
const epoch = handle?.epoch ?? 0;
|
|
5399
|
+
const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), channel, epoch, corr, body);
|
|
4809
5400
|
return new Promise((resolve7, reject) => {
|
|
4810
5401
|
const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
4811
5402
|
const pending = {
|
|
4812
|
-
|
|
5403
|
+
handle,
|
|
4813
5404
|
resolve: resolve7,
|
|
4814
5405
|
reject,
|
|
4815
5406
|
onProgress,
|
|
4816
|
-
timer: null
|
|
5407
|
+
timer: null,
|
|
5408
|
+
acceptFrame,
|
|
5409
|
+
onLateResponse
|
|
4817
5410
|
};
|
|
4818
|
-
pending.timer = setTimeout(() =>
|
|
4819
|
-
this.arbitrateTimeout(key, pending, channel, corr, ms);
|
|
4820
|
-
}, ms);
|
|
5411
|
+
pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, channel, corr, ms), ms);
|
|
4821
5412
|
this.pending.set(key, pending);
|
|
4822
|
-
this.sock.write(encodeFrame(frame), Date.now() + ms).catch((
|
|
4823
|
-
const
|
|
4824
|
-
if (
|
|
4825
|
-
this.rejectPending(key,
|
|
5413
|
+
this.sock.write(encodeFrame(frame), Date.now() + ms).catch((error2) => {
|
|
5414
|
+
const current = this.pending.get(key);
|
|
5415
|
+
if (current)
|
|
5416
|
+
this.rejectPending(key, current, error2 instanceof Error ? error2 : new SubcError(String(error2)));
|
|
4826
5417
|
});
|
|
4827
5418
|
});
|
|
4828
5419
|
}
|
|
4829
5420
|
arbitrateTimeout(key, pending, channel, corr, ms) {
|
|
4830
5421
|
const settleAsTimeout = () => {
|
|
5422
|
+
if (pending.onLateResponse)
|
|
5423
|
+
this.lateResponses.set(key, pending.onLateResponse);
|
|
4831
5424
|
this.rejectPending(key, pending, new SubcError(this.timeoutMessage(channel, corr, ms), REQUEST_DEADLINE_MARKER));
|
|
4832
5425
|
};
|
|
4833
5426
|
const graceDeadline = Date.now() + this.opts.timeoutArbitrationGraceMs;
|
|
@@ -4843,59 +5436,67 @@ class SubcClient {
|
|
|
4843
5436
|
};
|
|
4844
5437
|
setImmediate(arbitrate);
|
|
4845
5438
|
}
|
|
4846
|
-
async managedRequest(
|
|
5439
|
+
async managedRequest(handle, body, opts) {
|
|
4847
5440
|
const bytes = body instanceof Uint8Array ? body : this.encode(body);
|
|
4848
5441
|
const priority = opts.priority ?? Priority.Interactive;
|
|
5442
|
+
const admission = opts.admissionClass ?? AdmissionClass.Normal;
|
|
4849
5443
|
try {
|
|
4850
|
-
const reply = await this.sendManaged(
|
|
5444
|
+
const reply = await this.sendManaged(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress);
|
|
4851
5445
|
return this.parseJson(reply);
|
|
4852
|
-
} catch (
|
|
4853
|
-
if (
|
|
4854
|
-
throw
|
|
4855
|
-
throw this.terminalCallError("managed call failed",
|
|
5446
|
+
} catch (error2) {
|
|
5447
|
+
if (error2 instanceof SubcCallError)
|
|
5448
|
+
throw error2;
|
|
5449
|
+
throw this.terminalCallError("managed call failed", error2);
|
|
4856
5450
|
}
|
|
4857
5451
|
}
|
|
4858
|
-
sendManaged(
|
|
5452
|
+
sendManaged(handle, body, priority, admission, timeoutMs, onProgress) {
|
|
5453
|
+
try {
|
|
5454
|
+
this.assertLiveHandle(handle);
|
|
5455
|
+
} catch (error2) {
|
|
5456
|
+
return Promise.reject(this.notSentCallError("request used a stale route handle", error2));
|
|
5457
|
+
}
|
|
4859
5458
|
if (this.closedErr) {
|
|
4860
5459
|
return Promise.reject(this.notSentCallError("request was not sent because the subc connection was already closed", this.closedErr));
|
|
4861
5460
|
}
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
5461
|
+
let corr;
|
|
5462
|
+
try {
|
|
5463
|
+
corr = this.allocateCorr();
|
|
5464
|
+
} catch (error2) {
|
|
5465
|
+
return Promise.reject(this.notSentCallError("request correlation allocator was exhausted", error2));
|
|
5466
|
+
}
|
|
5467
|
+
const key = pendingKey(handle, corr);
|
|
5468
|
+
const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), handle.channel, handle.epoch, corr, body);
|
|
4865
5469
|
let handedToSocket = false;
|
|
4866
|
-
const classifyFailure = (
|
|
4867
|
-
if (!handedToSocket)
|
|
4868
|
-
return this.notSentCallError("request bytes were not queued to the subc socket",
|
|
5470
|
+
const classifyFailure = (error2) => {
|
|
5471
|
+
if (!handedToSocket)
|
|
5472
|
+
return this.notSentCallError("request bytes were not queued to the subc socket", error2);
|
|
5473
|
+
if (error2 instanceof SubcError && error2.code === REQUEST_DEADLINE_MARKER) {
|
|
5474
|
+
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);
|
|
4869
5475
|
}
|
|
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);
|
|
4872
|
-
}
|
|
4873
|
-
return this.outcomeUnknownCallError("connection dropped before the managed call returned a response", err);
|
|
5476
|
+
return this.outcomeUnknownCallError("connection dropped before the managed call returned a response", error2);
|
|
4874
5477
|
};
|
|
4875
5478
|
return new Promise((resolve7, reject) => {
|
|
4876
5479
|
const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
4877
5480
|
const pending = {
|
|
4878
|
-
|
|
5481
|
+
handle,
|
|
4879
5482
|
resolve: resolve7,
|
|
4880
5483
|
reject,
|
|
4881
5484
|
onProgress,
|
|
4882
5485
|
timer: null,
|
|
4883
5486
|
classifyFailure
|
|
4884
5487
|
};
|
|
4885
|
-
pending.timer = setTimeout(() =>
|
|
4886
|
-
this.arbitrateTimeout(key, pending, channel, corr, ms);
|
|
4887
|
-
}, ms);
|
|
5488
|
+
pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, handle.channel, corr, ms), ms);
|
|
4888
5489
|
this.pending.set(key, pending);
|
|
4889
5490
|
const write = this.sock.writeTracked(encodeFrame(frame), Date.now() + ms);
|
|
4890
5491
|
handedToSocket = write.queued;
|
|
4891
|
-
write.completed.catch((
|
|
4892
|
-
const
|
|
4893
|
-
if (
|
|
4894
|
-
this.rejectPending(key,
|
|
5492
|
+
write.completed.catch((error2) => {
|
|
5493
|
+
const current = this.pending.get(key);
|
|
5494
|
+
if (current)
|
|
5495
|
+
this.rejectPending(key, current, error2 instanceof Error ? error2 : new SubcError(String(error2)));
|
|
4895
5496
|
});
|
|
4896
5497
|
});
|
|
4897
5498
|
}
|
|
4898
|
-
async
|
|
5499
|
+
async cachedRouteHandle(moduleId, opts) {
|
|
4899
5500
|
const identity = opts.identity ?? this.opts.identity;
|
|
4900
5501
|
if (!identity) {
|
|
4901
5502
|
throw new SubcCallError("terminal", "managed call requires a BindIdentity in SubcClient.connect({ identity }) or call(..., { identity })", "missing_identity");
|
|
@@ -4911,15 +5512,13 @@ class SubcClient {
|
|
|
4911
5512
|
target,
|
|
4912
5513
|
identity,
|
|
4913
5514
|
consumerIdentity,
|
|
4914
|
-
|
|
4915
|
-
generation: 0,
|
|
5515
|
+
handle: null,
|
|
4916
5516
|
opening: null
|
|
4917
5517
|
};
|
|
4918
5518
|
this.routes.set(key, cached);
|
|
4919
5519
|
}
|
|
4920
|
-
if (cached.
|
|
4921
|
-
return cached.
|
|
4922
|
-
}
|
|
5520
|
+
if (cached.handle && this.isLiveHandle(cached.handle))
|
|
5521
|
+
return cached.handle;
|
|
4923
5522
|
if (!cached.opening) {
|
|
4924
5523
|
cached.opening = this.openCachedRoute(cached).finally(() => {
|
|
4925
5524
|
cached.opening = null;
|
|
@@ -4936,44 +5535,43 @@ class SubcClient {
|
|
|
4936
5535
|
throw this.routeClosedDuringOpen();
|
|
4937
5536
|
try {
|
|
4938
5537
|
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;
|
|
5538
|
+
} catch (error2) {
|
|
5539
|
+
throw this.notSentRecoveryError("route.open could not run because reconnect failed", error2);
|
|
4944
5540
|
}
|
|
5541
|
+
if (cached.handle && this.isLiveHandle(cached.handle))
|
|
5542
|
+
return cached.handle;
|
|
4945
5543
|
try {
|
|
4946
|
-
const
|
|
5544
|
+
const handle = await this.routeOpen(cached.target, cached.identity, {
|
|
4947
5545
|
consumerIdentity: cached.consumerIdentity ?? null
|
|
4948
5546
|
});
|
|
4949
5547
|
if (cached.closed) {
|
|
4950
|
-
this.
|
|
5548
|
+
this.liveRoutes.delete(handle.channel);
|
|
5549
|
+
this.sendRouteGoodbye(handle);
|
|
4951
5550
|
throw this.routeClosedDuringOpen();
|
|
4952
5551
|
}
|
|
4953
|
-
cached.
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
if (!this.closeStarted && isConsumerReconnectTransient(err)) {
|
|
5552
|
+
cached.handle = handle;
|
|
5553
|
+
return handle;
|
|
5554
|
+
} catch (error2) {
|
|
5555
|
+
if (error2 instanceof SubcCallError && error2.code === "route_closed")
|
|
5556
|
+
throw error2;
|
|
5557
|
+
if (!this.closeStarted && isConsumerReconnectTransient(error2)) {
|
|
4960
5558
|
try {
|
|
4961
|
-
await this.reconnectAfterDrop(
|
|
4962
|
-
} catch (
|
|
4963
|
-
throw this.notSentRecoveryError("route.open was not sent and reconnect failed",
|
|
5559
|
+
await this.reconnectAfterDrop(error2);
|
|
5560
|
+
} catch (reconnectError) {
|
|
5561
|
+
throw this.notSentRecoveryError("route.open was not sent and reconnect failed", reconnectError);
|
|
4964
5562
|
}
|
|
4965
5563
|
continue;
|
|
4966
5564
|
}
|
|
4967
|
-
if (!this.closeStarted &&
|
|
5565
|
+
if (!this.closeStarted && error2 instanceof SubcError && isRetryableRouteOpenCode(error2.code)) {
|
|
4968
5566
|
routeRetryAttempt += 1;
|
|
4969
5567
|
if (routeRetryAttempt < this.opts.reconnectBackoff.maxAttempts && Date.now() < routeRetryDeadline) {
|
|
4970
5568
|
await this.opts.sleep(routeRetryDelay);
|
|
4971
5569
|
routeRetryDelay = Math.min(routeRetryDelay * 2, this.opts.reconnectBackoff.capMs);
|
|
4972
5570
|
continue;
|
|
4973
5571
|
}
|
|
4974
|
-
throw this.notSentCallError(`route.open failed for module ${cached.moduleId}: ${
|
|
5572
|
+
throw this.notSentCallError(`route.open failed for module ${cached.moduleId}: ${error2.code} (retry budget exhausted)`, error2);
|
|
4975
5573
|
}
|
|
4976
|
-
throw this.terminalCallError(`route.open failed for module ${cached.moduleId}`,
|
|
5574
|
+
throw this.terminalCallError(`route.open failed for module ${cached.moduleId}`, error2);
|
|
4977
5575
|
}
|
|
4978
5576
|
}
|
|
4979
5577
|
}
|
|
@@ -5036,25 +5634,27 @@ class SubcClient {
|
|
|
5036
5634
|
this.currentConn = opened.conn;
|
|
5037
5635
|
this.closedErr = null;
|
|
5038
5636
|
this.generation += 1;
|
|
5637
|
+
this.connectionToken = newConnectionToken();
|
|
5638
|
+
this.liveRoutes.clear();
|
|
5639
|
+
this.lateResponses.clear();
|
|
5640
|
+
this.nextCorr = 1n;
|
|
5039
5641
|
this.readLoop(opened.sock, this.generation);
|
|
5040
5642
|
}
|
|
5041
5643
|
async reopenCachedRoutes() {
|
|
5042
|
-
for (const cached of this.routes.values())
|
|
5043
|
-
cached.
|
|
5044
|
-
cached.generation = 0;
|
|
5045
|
-
}
|
|
5644
|
+
for (const cached of this.routes.values())
|
|
5645
|
+
cached.handle = null;
|
|
5046
5646
|
for (const cached of this.routes.values()) {
|
|
5047
5647
|
if (cached.closed)
|
|
5048
5648
|
continue;
|
|
5049
|
-
const
|
|
5649
|
+
const handle = await this.routeOpen(cached.target, cached.identity, {
|
|
5050
5650
|
consumerIdentity: cached.consumerIdentity ?? null
|
|
5051
5651
|
});
|
|
5052
5652
|
if (cached.closed) {
|
|
5053
|
-
this.
|
|
5653
|
+
this.liveRoutes.delete(handle.channel);
|
|
5654
|
+
this.sendRouteGoodbye(handle);
|
|
5054
5655
|
continue;
|
|
5055
5656
|
}
|
|
5056
|
-
cached.
|
|
5057
|
-
cached.generation = this.generation;
|
|
5657
|
+
cached.handle = handle;
|
|
5058
5658
|
}
|
|
5059
5659
|
}
|
|
5060
5660
|
timeoutMessage(channel, corr, ms) {
|
|
@@ -5068,28 +5668,37 @@ class SubcClient {
|
|
|
5068
5668
|
async readLoop(sock, generation) {
|
|
5069
5669
|
try {
|
|
5070
5670
|
for (;; ) {
|
|
5071
|
-
|
|
5072
|
-
|
|
5671
|
+
this.readerActive = false;
|
|
5672
|
+
const frame = await sock.readFrame(Number.POSITIVE_INFINITY, { afterHeaderMs: BODY_READ_TIMEOUT_MS }, () => {
|
|
5673
|
+
this.readerActive = true;
|
|
5674
|
+
});
|
|
5073
5675
|
try {
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
if (this.sock === sock && this.generation === generation) {
|
|
5077
|
-
this.dispatch({ header, body });
|
|
5078
|
-
}
|
|
5676
|
+
if (this.sock === sock && this.generation === generation)
|
|
5677
|
+
this.dispatch(frame);
|
|
5079
5678
|
} finally {
|
|
5080
5679
|
this.readerActive = false;
|
|
5081
5680
|
}
|
|
5082
5681
|
}
|
|
5083
|
-
} catch (
|
|
5682
|
+
} catch (error2) {
|
|
5084
5683
|
if (this.sock === sock && this.generation === generation) {
|
|
5085
|
-
this.fail(
|
|
5684
|
+
this.fail(error2 instanceof Error ? error2 : new SubcError(String(error2)));
|
|
5685
|
+
}
|
|
5686
|
+
}
|
|
5687
|
+
}
|
|
5688
|
+
dispatch(frame) {
|
|
5689
|
+
let handle = null;
|
|
5690
|
+
if (frame.header.channel !== 0) {
|
|
5691
|
+
handle = this.liveRoutes.get(frame.header.channel) ?? null;
|
|
5692
|
+
if (!handle || handle.epoch !== frame.header.epoch) {
|
|
5693
|
+
this.ingressEpochDropCount += 1;
|
|
5694
|
+
return;
|
|
5086
5695
|
}
|
|
5087
5696
|
}
|
|
5088
|
-
|
|
5089
|
-
dispatch(frame) {
|
|
5090
|
-
const key = `${frame.header.channel}:${frame.header.corr}`;
|
|
5697
|
+
const key = pendingKey(handle, frame.header.corr);
|
|
5091
5698
|
const pending = this.pending.get(key);
|
|
5092
5699
|
if (pending) {
|
|
5700
|
+
if (pending.acceptFrame && !pending.acceptFrame(frame))
|
|
5701
|
+
return;
|
|
5093
5702
|
switch (frame.header.ty) {
|
|
5094
5703
|
case FrameType.Push:
|
|
5095
5704
|
case FrameType.StreamData:
|
|
@@ -5106,15 +5715,22 @@ class SubcClient {
|
|
|
5106
5715
|
return;
|
|
5107
5716
|
}
|
|
5108
5717
|
}
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
this.
|
|
5718
|
+
const late = this.lateResponses.get(key);
|
|
5719
|
+
if (late && (frame.header.ty === FrameType.Response || frame.header.ty === FrameType.Error)) {
|
|
5720
|
+
this.lateResponses.delete(key);
|
|
5721
|
+
late(frame);
|
|
5112
5722
|
return;
|
|
5113
5723
|
}
|
|
5114
|
-
if (frame.header.ty === FrameType.
|
|
5115
|
-
|
|
5724
|
+
if (frame.header.ty === FrameType.Goodbye && handle) {
|
|
5725
|
+
this.failHandle(handle, new SubcError("route closed by subc (GOODBYE)"));
|
|
5726
|
+
if (this.liveRoutes.get(handle.channel) === handle)
|
|
5727
|
+
this.liveRoutes.delete(handle.channel);
|
|
5728
|
+
this.evictRouteHandle(handle);
|
|
5116
5729
|
return;
|
|
5117
5730
|
}
|
|
5731
|
+
if (frame.header.ty === FrameType.Response || frame.header.ty === FrameType.Error || frame.header.ty === FrameType.StreamEnd) {
|
|
5732
|
+
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() ?? "?");
|
|
5733
|
+
}
|
|
5118
5734
|
}
|
|
5119
5735
|
settle(key, pending, run) {
|
|
5120
5736
|
if (this.pending.get(key) !== pending)
|
|
@@ -5137,18 +5753,16 @@ class SubcClient {
|
|
|
5137
5753
|
return new SubcError(Buffer.from(frame.body).toString("utf8") || "subc error");
|
|
5138
5754
|
}
|
|
5139
5755
|
}
|
|
5140
|
-
|
|
5756
|
+
evictRouteHandle(handle) {
|
|
5141
5757
|
for (const cached of this.routes.values()) {
|
|
5142
|
-
if (cached.
|
|
5143
|
-
cached.
|
|
5144
|
-
}
|
|
5758
|
+
if (cached.handle && sameRouteHandle(cached.handle, handle))
|
|
5759
|
+
cached.handle = null;
|
|
5145
5760
|
}
|
|
5146
5761
|
}
|
|
5147
|
-
|
|
5762
|
+
failHandle(handle, error2) {
|
|
5148
5763
|
for (const [key, pending] of this.pending) {
|
|
5149
|
-
if (pending.
|
|
5150
|
-
this.rejectPending(key, pending,
|
|
5151
|
-
}
|
|
5764
|
+
if (pending.handle && sameRouteHandle(pending.handle, handle))
|
|
5765
|
+
this.rejectPending(key, pending, error2);
|
|
5152
5766
|
}
|
|
5153
5767
|
}
|
|
5154
5768
|
fail(err) {
|
|
@@ -5176,6 +5790,44 @@ class SubcClient {
|
|
|
5176
5790
|
return this.notSentCallError(message, cause);
|
|
5177
5791
|
return this.terminalCallError(message, cause);
|
|
5178
5792
|
}
|
|
5793
|
+
get droppedIngressFrames() {
|
|
5794
|
+
return this.ingressEpochDropCount;
|
|
5795
|
+
}
|
|
5796
|
+
installRoute(channel, epoch) {
|
|
5797
|
+
const handle = createRouteHandle(channel, epoch, this.connectionToken);
|
|
5798
|
+
this.liveRoutes.set(channel, handle);
|
|
5799
|
+
return handle;
|
|
5800
|
+
}
|
|
5801
|
+
isLiveHandle(handle) {
|
|
5802
|
+
return belongsToConnection(handle, this.connectionToken) && this.liveRoutes.get(handle.channel) === handle;
|
|
5803
|
+
}
|
|
5804
|
+
assertLiveConnection(handle) {
|
|
5805
|
+
if (!belongsToConnection(handle, this.connectionToken))
|
|
5806
|
+
throw new StaleRouteHandleError(handle);
|
|
5807
|
+
}
|
|
5808
|
+
assertLiveHandle(handle) {
|
|
5809
|
+
if (!this.isLiveHandle(handle))
|
|
5810
|
+
throw new StaleRouteHandleError(handle);
|
|
5811
|
+
}
|
|
5812
|
+
allocateCorr() {
|
|
5813
|
+
const maximum = 0xffffffffffffffffn;
|
|
5814
|
+
if (this.nextCorr > maximum) {
|
|
5815
|
+
const error2 = new SubcError("channel-0 correlation id allocator exhausted", "corr_exhausted");
|
|
5816
|
+
this.fail(error2);
|
|
5817
|
+
this.sock.close();
|
|
5818
|
+
this.scheduleReconnectAfterDrop(error2);
|
|
5819
|
+
throw error2;
|
|
5820
|
+
}
|
|
5821
|
+
const corr = this.nextCorr;
|
|
5822
|
+
this.nextCorr += 1n;
|
|
5823
|
+
return corr;
|
|
5824
|
+
}
|
|
5825
|
+
closeConnectionAfterCleanupFailure() {
|
|
5826
|
+
const error2 = new SubcError("late route cleanup could not be queued", "late_route_cleanup_failed");
|
|
5827
|
+
this.fail(error2);
|
|
5828
|
+
this.sock.close();
|
|
5829
|
+
this.scheduleReconnectAfterDrop(error2);
|
|
5830
|
+
}
|
|
5179
5831
|
encode(value) {
|
|
5180
5832
|
return new Uint8Array(Buffer.from(JSON.stringify(value), "utf8"));
|
|
5181
5833
|
}
|
|
@@ -5245,11 +5897,15 @@ function causeMessage(cause) {
|
|
|
5245
5897
|
return "";
|
|
5246
5898
|
return `: ${cause instanceof Error ? cause.message : String(cause)}`;
|
|
5247
5899
|
}
|
|
5900
|
+
function pendingKey(handle, corr) {
|
|
5901
|
+
return handle ? `${handle.channel}:${handle.epoch}:${corr}` : `0:0:${corr}`;
|
|
5902
|
+
}
|
|
5248
5903
|
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
5904
|
var init_client = __esm(() => {
|
|
5250
5905
|
init_auth();
|
|
5251
5906
|
init_connection_file();
|
|
5252
5907
|
init_envelope();
|
|
5908
|
+
init_route_handle();
|
|
5253
5909
|
init_socket();
|
|
5254
5910
|
debug = debuglog("subc-client");
|
|
5255
5911
|
EMPTY_BODY = new Uint8Array(0);
|
|
@@ -5279,7 +5935,7 @@ var init_client = __esm(() => {
|
|
|
5279
5935
|
};
|
|
5280
5936
|
});
|
|
5281
5937
|
|
|
5282
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
5938
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.5.0/node_modules/@cortexkit/subc-client/dist/provider.js
|
|
5283
5939
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
5284
5940
|
|
|
5285
5941
|
class AsyncPermitPool {
|
|
@@ -5328,6 +5984,11 @@ class SubcProvider {
|
|
|
5328
5984
|
closeStarted = false;
|
|
5329
5985
|
closedErr = null;
|
|
5330
5986
|
inflight = new Map;
|
|
5987
|
+
pending = new Map;
|
|
5988
|
+
liveRoutes = new Map;
|
|
5989
|
+
connectionToken = newConnectionToken();
|
|
5990
|
+
nextCorr = 1n;
|
|
5991
|
+
ingressEpochDropCount = 0;
|
|
5331
5992
|
requestGate = new AsyncPermitPool(DEFAULT_PROVIDER_HANDLER_CAPACITY);
|
|
5332
5993
|
reconnecting = null;
|
|
5333
5994
|
generation = 1;
|
|
@@ -5347,12 +6008,55 @@ class SubcProvider {
|
|
|
5347
6008
|
this.readLoop(sock, this.generation);
|
|
5348
6009
|
this.enqueueConnectionState({ state: "connected", epoch: this.connectionEpoch });
|
|
5349
6010
|
}
|
|
6011
|
+
get droppedIngressFrames() {
|
|
6012
|
+
return this.ingressEpochDropCount;
|
|
6013
|
+
}
|
|
5350
6014
|
get conn() {
|
|
5351
6015
|
return this.currentConn;
|
|
5352
6016
|
}
|
|
5353
6017
|
currentEpoch() {
|
|
5354
6018
|
return this.connectionEpoch;
|
|
5355
6019
|
}
|
|
6020
|
+
async request(handle, body, opts = {}) {
|
|
6021
|
+
this.assertLiveHandle(handle);
|
|
6022
|
+
const corr = this.allocateCorr();
|
|
6023
|
+
const key = routeKey(handle, corr);
|
|
6024
|
+
const timeoutMs = opts.timeoutMs ?? WRITE_TIMEOUT_MS;
|
|
6025
|
+
const frame = buildFrame(FrameType.Request, buildFlags(false, opts.priority ?? Priority.Interactive, false, opts.admissionClass ?? AdmissionClass.Normal), handle.channel, handle.epoch, corr, body);
|
|
6026
|
+
return await new Promise((resolve7, reject) => {
|
|
6027
|
+
const timer = setTimeout(() => {
|
|
6028
|
+
if (this.pending.delete(key))
|
|
6029
|
+
reject(new SubcProviderError("reverse request timed out", "request_timeout"));
|
|
6030
|
+
}, timeoutMs);
|
|
6031
|
+
this.pending.set(key, {
|
|
6032
|
+
resolve: (response) => resolve7(response.body),
|
|
6033
|
+
reject,
|
|
6034
|
+
timer
|
|
6035
|
+
});
|
|
6036
|
+
this.sendOn(this.sock, this.generation, frame).catch((error2) => {
|
|
6037
|
+
const pending = this.pending.get(key);
|
|
6038
|
+
if (!pending)
|
|
6039
|
+
return;
|
|
6040
|
+
this.pending.delete(key);
|
|
6041
|
+
clearTimeout(pending.timer);
|
|
6042
|
+
reject(error2 instanceof Error ? error2 : new SubcProviderError(String(error2)));
|
|
6043
|
+
});
|
|
6044
|
+
});
|
|
6045
|
+
}
|
|
6046
|
+
async push(handle, body, opts = {}) {
|
|
6047
|
+
this.assertLiveHandle(handle);
|
|
6048
|
+
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));
|
|
6049
|
+
}
|
|
6050
|
+
cancel(handle, corr) {
|
|
6051
|
+
this.assertLiveHandle(handle);
|
|
6052
|
+
this.sendOn(this.sock, this.generation, buildFrame(FrameType.Cancel, controlFlags(), handle.channel, handle.epoch, corr, new Uint8Array(0)));
|
|
6053
|
+
}
|
|
6054
|
+
closeRoute(handle) {
|
|
6055
|
+
this.assertLiveHandle(handle);
|
|
6056
|
+
this.liveRoutes.delete(handle.channel);
|
|
6057
|
+
this.abortHandle(handle);
|
|
6058
|
+
this.sendOn(this.sock, this.generation, buildFrame(FrameType.Goodbye, controlFlags(), handle.channel, handle.epoch, 0n, new Uint8Array(0)));
|
|
6059
|
+
}
|
|
5356
6060
|
static async connect(opts) {
|
|
5357
6061
|
if (opts.manifest.protocol_ver !== PROTOCOL_VERSION) {
|
|
5358
6062
|
throw new SubcProviderError(`manifest protocol_ver ${opts.manifest.protocol_ver} does not match client protocol ${PROTOCOL_VERSION}`, "invalid_manifest");
|
|
@@ -5367,7 +6071,7 @@ class SubcProvider {
|
|
|
5367
6071
|
this.cancelRestoredDebounce();
|
|
5368
6072
|
const sock = this.sock;
|
|
5369
6073
|
try {
|
|
5370
|
-
await sendFrame(sock, buildFrame(FrameType.Goodbye, controlFlags(), 0, 0n, new Uint8Array(0)));
|
|
6074
|
+
await sendFrame(sock, buildFrame(FrameType.Goodbye, controlFlags(), 0, 0, 0n, new Uint8Array(0)));
|
|
5371
6075
|
} catch {} finally {
|
|
5372
6076
|
sock.close();
|
|
5373
6077
|
this.finishClosed();
|
|
@@ -5375,12 +6079,13 @@ class SubcProvider {
|
|
|
5375
6079
|
}
|
|
5376
6080
|
await this.closed;
|
|
5377
6081
|
}
|
|
5378
|
-
static async openConnection(opts) {
|
|
6082
|
+
static async openConnection(opts, onSocket) {
|
|
5379
6083
|
const conn = await readConnectionFile(opts.connectionFile);
|
|
5380
6084
|
const deadline = Date.now() + (opts.handshakeTimeoutMs ?? DEFAULT_HANDSHAKE_TIMEOUT_MS2);
|
|
5381
6085
|
const endpoint = conn.endpoints[0];
|
|
5382
6086
|
const sock = await SubcSocket.connect(endpoint.host, endpoint.port, deadline);
|
|
5383
6087
|
try {
|
|
6088
|
+
onSocket?.(sock);
|
|
5384
6089
|
await authenticateClient(sock, conn, deadline);
|
|
5385
6090
|
await sendFrame(sock, buildHelloFrame(opts));
|
|
5386
6091
|
const ack = await expectHelloAck(sock, deadline);
|
|
@@ -5393,19 +6098,17 @@ class SubcProvider {
|
|
|
5393
6098
|
async readLoop(sock, generation) {
|
|
5394
6099
|
try {
|
|
5395
6100
|
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);
|
|
6101
|
+
const frame = await sock.readFrame(Number.POSITIVE_INFINITY, { afterHeaderMs: BODY_READ_TIMEOUT_MS2 });
|
|
6102
|
+
const keepGoing = await this.dispatch(frame, sock, generation);
|
|
5400
6103
|
if (!keepGoing) {
|
|
5401
6104
|
if (this.sock === sock && this.generation === generation)
|
|
5402
6105
|
this.closeStarted = true;
|
|
5403
6106
|
break;
|
|
5404
6107
|
}
|
|
5405
6108
|
}
|
|
5406
|
-
} catch (
|
|
6109
|
+
} catch (error2) {
|
|
5407
6110
|
if (this.sock === sock && this.generation === generation && !this.closeStarted) {
|
|
5408
|
-
this.handleUnexpectedDrop(sock, generation,
|
|
6111
|
+
this.handleUnexpectedDrop(sock, generation, error2 instanceof Error ? error2 : new SubcProviderError(String(error2)));
|
|
5409
6112
|
return;
|
|
5410
6113
|
}
|
|
5411
6114
|
} finally {
|
|
@@ -5417,28 +6120,58 @@ class SubcProvider {
|
|
|
5417
6120
|
}
|
|
5418
6121
|
}
|
|
5419
6122
|
async dispatch(frame, sock, generation) {
|
|
6123
|
+
let handle = null;
|
|
6124
|
+
if (frame.header.channel !== 0) {
|
|
6125
|
+
handle = this.liveRoutes.get(frame.header.channel) ?? null;
|
|
6126
|
+
if (!handle || handle.epoch !== frame.header.epoch) {
|
|
6127
|
+
this.ingressEpochDropCount += 1;
|
|
6128
|
+
return true;
|
|
6129
|
+
}
|
|
6130
|
+
}
|
|
6131
|
+
if (handle) {
|
|
6132
|
+
const pendingKey2 = routeKey(handle, frame.header.corr);
|
|
6133
|
+
const pending = this.pending.get(pendingKey2);
|
|
6134
|
+
if (pending) {
|
|
6135
|
+
if (frame.header.ty === FrameType.Push || frame.header.ty === FrameType.StreamData)
|
|
6136
|
+
return true;
|
|
6137
|
+
if (frame.header.ty === FrameType.Response || frame.header.ty === FrameType.StreamEnd) {
|
|
6138
|
+
this.pending.delete(pendingKey2);
|
|
6139
|
+
clearTimeout(pending.timer);
|
|
6140
|
+
pending.resolve(frame);
|
|
6141
|
+
return true;
|
|
6142
|
+
}
|
|
6143
|
+
if (frame.header.ty === FrameType.Error) {
|
|
6144
|
+
this.pending.delete(pendingKey2);
|
|
6145
|
+
clearTimeout(pending.timer);
|
|
6146
|
+
pending.reject(providerErrorFromFrame(frame));
|
|
6147
|
+
return true;
|
|
6148
|
+
}
|
|
6149
|
+
}
|
|
6150
|
+
}
|
|
5420
6151
|
switch (frame.header.ty) {
|
|
5421
6152
|
case FrameType.Ping:
|
|
5422
6153
|
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)));
|
|
6154
|
+
await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver, FrameType.Pong, frame.header.flags, 0, 0, frame.header.corr, new Uint8Array(0)));
|
|
5424
6155
|
}
|
|
5425
6156
|
return true;
|
|
5426
6157
|
case FrameType.Goodbye:
|
|
5427
|
-
if (
|
|
6158
|
+
if (!handle)
|
|
5428
6159
|
return false;
|
|
5429
|
-
this.
|
|
5430
|
-
|
|
6160
|
+
this.liveRoutes.delete(handle.channel);
|
|
6161
|
+
this.abortHandle(handle);
|
|
6162
|
+
await this.opts.onRouteGone?.(handle);
|
|
5431
6163
|
return true;
|
|
5432
6164
|
case FrameType.Cancel:
|
|
5433
|
-
|
|
6165
|
+
if (handle)
|
|
6166
|
+
this.inflight.get(routeKey(handle, frame.header.corr))?.abort();
|
|
5434
6167
|
return true;
|
|
5435
6168
|
case FrameType.Request:
|
|
5436
6169
|
if (frame.header.channel === 0) {
|
|
5437
6170
|
await this.handleControlRequest(frame, sock, generation);
|
|
5438
|
-
} else {
|
|
5439
|
-
this.handleDataRequest(frame, sock, generation).catch((
|
|
6171
|
+
} else if (handle) {
|
|
6172
|
+
this.handleDataRequest(frame, handle, sock, generation).catch((error2) => {
|
|
5440
6173
|
if (!this.closeStarted && this.sock === sock && this.generation === generation) {
|
|
5441
|
-
console.warn("SubcProvider handler failed after its request was dispatched",
|
|
6174
|
+
console.warn("SubcProvider handler failed after its request was dispatched", error2);
|
|
5442
6175
|
}
|
|
5443
6176
|
});
|
|
5444
6177
|
}
|
|
@@ -5447,19 +6180,28 @@ class SubcProvider {
|
|
|
5447
6180
|
return true;
|
|
5448
6181
|
}
|
|
5449
6182
|
}
|
|
5450
|
-
|
|
5451
|
-
const prefix = `${
|
|
6183
|
+
abortHandle(handle) {
|
|
6184
|
+
const prefix = `${handle.channel}:${handle.epoch}:`;
|
|
5452
6185
|
for (const [key, controller] of this.inflight) {
|
|
5453
6186
|
if (key.startsWith(prefix))
|
|
5454
6187
|
controller.abort();
|
|
5455
6188
|
}
|
|
6189
|
+
for (const [key, pending] of this.pending) {
|
|
6190
|
+
if (!key.startsWith(prefix))
|
|
6191
|
+
continue;
|
|
6192
|
+
this.pending.delete(key);
|
|
6193
|
+
clearTimeout(pending.timer);
|
|
6194
|
+
pending.reject(new StaleRouteHandleError(handle));
|
|
6195
|
+
}
|
|
5456
6196
|
}
|
|
5457
|
-
abortGeneration(
|
|
5458
|
-
|
|
5459
|
-
for (const [key,
|
|
5460
|
-
|
|
5461
|
-
|
|
6197
|
+
abortGeneration(_generation) {
|
|
6198
|
+
this.abortAllInflight();
|
|
6199
|
+
for (const [key, pending] of this.pending) {
|
|
6200
|
+
this.pending.delete(key);
|
|
6201
|
+
clearTimeout(pending.timer);
|
|
6202
|
+
pending.reject(new SubcProviderError("provider connection dropped", "connection_dropped"));
|
|
5462
6203
|
}
|
|
6204
|
+
this.liveRoutes.clear();
|
|
5463
6205
|
}
|
|
5464
6206
|
abortAllInflight() {
|
|
5465
6207
|
for (const controller of this.inflight.values())
|
|
@@ -5468,9 +6210,9 @@ class SubcProvider {
|
|
|
5468
6210
|
async handleControlRequest(frame, sock, generation) {
|
|
5469
6211
|
const request = parseJson(frame.body);
|
|
5470
6212
|
if (request.op === HEALTH_CHECK_OP) {
|
|
5471
|
-
this.handleHealthRequest(frame, sock, generation).catch((
|
|
6213
|
+
this.handleHealthRequest(frame, sock, generation).catch((error2) => {
|
|
5472
6214
|
if (!this.closeStarted && this.sock === sock && this.generation === generation) {
|
|
5473
|
-
console.warn("SubcProvider health handler failed after its request was dispatched",
|
|
6215
|
+
console.warn("SubcProvider health handler failed after its request was dispatched", error2);
|
|
5474
6216
|
}
|
|
5475
6217
|
});
|
|
5476
6218
|
return;
|
|
@@ -5478,47 +6220,93 @@ class SubcProvider {
|
|
|
5478
6220
|
if (request.op !== "route.bind") {
|
|
5479
6221
|
throw new SubcProviderError(`unsupported module control request ${request.op ?? "<missing op>"}`);
|
|
5480
6222
|
}
|
|
6223
|
+
const boundChannel = numberField(request.route_channel, "route_channel");
|
|
6224
|
+
const boundEpoch = numberField(request.epoch, "epoch");
|
|
6225
|
+
const stale = this.liveRoutes.get(boundChannel);
|
|
6226
|
+
if (stale) {
|
|
6227
|
+
if (boundEpoch <= stale.epoch) {
|
|
6228
|
+
await this.sendError(frame, "route_rejected", `route.bind epoch ${boundEpoch} does not supersede installed epoch ${stale.epoch} on channel ${boundChannel}`, controlFlags(), sock, generation);
|
|
6229
|
+
return;
|
|
6230
|
+
}
|
|
6231
|
+
this.liveRoutes.delete(stale.channel);
|
|
6232
|
+
this.abortHandle(stale);
|
|
6233
|
+
await this.opts.onRouteGone?.(stale);
|
|
6234
|
+
}
|
|
6235
|
+
const tentative = createRouteHandle(boundChannel, boundEpoch, this.connectionToken);
|
|
5481
6236
|
const bindRequest = {
|
|
5482
|
-
|
|
6237
|
+
handle: tentative,
|
|
5483
6238
|
target: request.target,
|
|
5484
6239
|
identity: request.identity,
|
|
5485
|
-
principal: request.principal
|
|
6240
|
+
principal: request.principal,
|
|
6241
|
+
consumer_capabilities: request.consumer_capabilities
|
|
5486
6242
|
};
|
|
5487
|
-
|
|
6243
|
+
let decision;
|
|
6244
|
+
try {
|
|
6245
|
+
decision = await this.opts.onBind?.(bindRequest);
|
|
6246
|
+
} catch (error2) {
|
|
6247
|
+
try {
|
|
6248
|
+
await this.sendError(frame, "route_rejected", error2 instanceof Error ? error2.message : String(error2), controlFlags(), sock, generation);
|
|
6249
|
+
} finally {
|
|
6250
|
+
await this.opts.onRouteGone?.(tentative);
|
|
6251
|
+
}
|
|
6252
|
+
return;
|
|
6253
|
+
}
|
|
5488
6254
|
const rejection = bindRejection(decision);
|
|
5489
6255
|
if (rejection) {
|
|
5490
|
-
|
|
6256
|
+
try {
|
|
6257
|
+
await this.sendError(frame, rejection.code, rejection.message, controlFlags(), sock, generation);
|
|
6258
|
+
} finally {
|
|
6259
|
+
await this.opts.onRouteGone?.(tentative);
|
|
6260
|
+
}
|
|
6261
|
+
return;
|
|
6262
|
+
}
|
|
6263
|
+
try {
|
|
6264
|
+
await this.sendOn(sock, generation, buildFrameWithVersion(frame.header.ver, FrameType.Response, controlFlags(), 0, 0, frame.header.corr, encodeJson({ op: "route.bind" })));
|
|
6265
|
+
} catch (error2) {
|
|
6266
|
+
await this.opts.onRouteGone?.(tentative);
|
|
6267
|
+
throw error2;
|
|
6268
|
+
}
|
|
6269
|
+
if (this.sock !== sock || this.generation !== generation || this.closeStarted || this.closedErr) {
|
|
6270
|
+
await this.opts.onRouteGone?.(tentative);
|
|
5491
6271
|
return;
|
|
5492
6272
|
}
|
|
5493
|
-
|
|
6273
|
+
this.liveRoutes.set(tentative.channel, tentative);
|
|
6274
|
+
await this.opts.onBound?.(tentative);
|
|
5494
6275
|
}
|
|
5495
|
-
async handleDataRequest(frame, sock, generation) {
|
|
5496
|
-
const {
|
|
5497
|
-
const key = routeKey(
|
|
6276
|
+
async handleDataRequest(frame, handle, sock, generation) {
|
|
6277
|
+
const { corr, ver } = frame.header;
|
|
6278
|
+
const key = routeKey(handle, corr);
|
|
5498
6279
|
const controller = new AbortController;
|
|
5499
6280
|
this.inflight.set(key, controller);
|
|
5500
|
-
const
|
|
5501
|
-
|
|
6281
|
+
const context = {
|
|
6282
|
+
handle,
|
|
5502
6283
|
signal: controller.signal,
|
|
5503
6284
|
currentEpoch: () => this.connectionEpoch,
|
|
5504
|
-
emit: async (eventBody) => {
|
|
6285
|
+
emit: async (eventBody, options = {}) => {
|
|
6286
|
+
this.assertLiveHandle(handle);
|
|
5505
6287
|
if (controller.signal.aborted)
|
|
5506
6288
|
return;
|
|
5507
|
-
await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.StreamData,
|
|
6289
|
+
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
6290
|
}
|
|
5509
6291
|
};
|
|
5510
6292
|
const releasePermit = await (this.requestGate ?? new AsyncPermitPool(DEFAULT_PROVIDER_HANDLER_CAPACITY)).acquire();
|
|
6293
|
+
const dataFlags = buildFlags(false, Priority.Interactive, false);
|
|
5511
6294
|
try {
|
|
5512
|
-
const body = await this.opts.handler(
|
|
6295
|
+
const body = await this.opts.handler(handle, frame.body, context);
|
|
6296
|
+
if (controller.signal.aborted)
|
|
6297
|
+
return;
|
|
6298
|
+
this.assertLiveHandle(handle);
|
|
5513
6299
|
if (body === undefined) {
|
|
5514
|
-
await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.StreamEnd, dataFlags, channel, corr, new Uint8Array(0)));
|
|
6300
|
+
await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.StreamEnd, dataFlags, handle.channel, handle.epoch, corr, new Uint8Array(0)));
|
|
5515
6301
|
} else if (body instanceof Uint8Array) {
|
|
5516
|
-
await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.Response, dataFlags, channel, corr, body));
|
|
6302
|
+
await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.Response, dataFlags, handle.channel, handle.epoch, corr, body));
|
|
5517
6303
|
} else {
|
|
5518
6304
|
throw new SubcProviderError("provider handler must return a Uint8Array or void", "invalid_handler_response");
|
|
5519
6305
|
}
|
|
5520
|
-
} catch (
|
|
5521
|
-
|
|
6306
|
+
} catch (error2) {
|
|
6307
|
+
if (error2 instanceof StaleRouteHandleError || controller.signal.aborted)
|
|
6308
|
+
return;
|
|
6309
|
+
await this.sendError(frame, error2 instanceof SubcProviderError && error2.code ? error2.code : "handler_error", error2 instanceof Error ? error2.message : String(error2), dataFlags, sock, generation);
|
|
5522
6310
|
} finally {
|
|
5523
6311
|
releasePermit();
|
|
5524
6312
|
if (this.inflight.get(key) === controller)
|
|
@@ -5526,8 +6314,8 @@ class SubcProvider {
|
|
|
5526
6314
|
}
|
|
5527
6315
|
}
|
|
5528
6316
|
async handleHealthRequest(frame, sock, generation) {
|
|
5529
|
-
const {
|
|
5530
|
-
const key =
|
|
6317
|
+
const { corr, ver } = frame.header;
|
|
6318
|
+
const key = `control:${generation}:${corr}`;
|
|
5531
6319
|
const controller = new AbortController;
|
|
5532
6320
|
this.inflight.set(key, controller);
|
|
5533
6321
|
const releasePermit = await (this.requestGate ?? new AsyncPermitPool(DEFAULT_PROVIDER_HANDLER_CAPACITY)).acquire();
|
|
@@ -5535,14 +6323,14 @@ class SubcProvider {
|
|
|
5535
6323
|
if (controller.signal.aborted)
|
|
5536
6324
|
return;
|
|
5537
6325
|
const report = await this.opts.health();
|
|
5538
|
-
await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.Response, controlFlags(),
|
|
6326
|
+
await this.sendOn(sock, generation, buildFrameWithVersion(ver, FrameType.Response, controlFlags(), 0, 0, corr, encodeJson({
|
|
5539
6327
|
op: HEALTH_CHECK_OP,
|
|
5540
6328
|
status: report.status,
|
|
5541
6329
|
...report.detail === undefined ? {} : { detail: report.detail },
|
|
5542
6330
|
...report.metrics === undefined ? {} : { metrics: report.metrics }
|
|
5543
6331
|
})));
|
|
5544
|
-
} catch (
|
|
5545
|
-
await this.sendError(frame,
|
|
6332
|
+
} catch (error2) {
|
|
6333
|
+
await this.sendError(frame, error2 instanceof SubcProviderError && error2.code ? error2.code : "health_error", error2 instanceof Error ? error2.message : String(error2), controlFlags(), sock, generation);
|
|
5546
6334
|
} finally {
|
|
5547
6335
|
releasePermit();
|
|
5548
6336
|
if (this.inflight.get(key) === controller)
|
|
@@ -5550,7 +6338,7 @@ class SubcProvider {
|
|
|
5550
6338
|
}
|
|
5551
6339
|
}
|
|
5552
6340
|
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 })));
|
|
6341
|
+
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
6342
|
}
|
|
5555
6343
|
async sendOn(sock, generation, frame) {
|
|
5556
6344
|
if (this.sock !== sock || this.generation !== generation || this.closeStarted || this.closedErr)
|
|
@@ -5558,42 +6346,79 @@ class SubcProvider {
|
|
|
5558
6346
|
await sendFrame(sock, frame);
|
|
5559
6347
|
}
|
|
5560
6348
|
handleUnexpectedDrop(sock, generation, cause) {
|
|
6349
|
+
if (this.closeStarted || this.sock !== sock || this.generation !== generation)
|
|
6350
|
+
return;
|
|
5561
6351
|
this.cancelRestoredDebounce();
|
|
5562
6352
|
this.abortGeneration(generation);
|
|
5563
6353
|
this.generation += 1;
|
|
5564
6354
|
sock.close();
|
|
5565
|
-
this.
|
|
5566
|
-
this.scheduleReconnectAfterDrop(cause);
|
|
6355
|
+
this.scheduleReconnectAfterDrop(cause, this.generation, sock);
|
|
5567
6356
|
}
|
|
5568
|
-
scheduleReconnectAfterDrop(
|
|
5569
|
-
if (this.closeStarted
|
|
6357
|
+
scheduleReconnectAfterDrop(cause, generation, droppedSocket) {
|
|
6358
|
+
if (this.closeStarted)
|
|
5570
6359
|
return;
|
|
5571
|
-
const
|
|
5572
|
-
|
|
6360
|
+
const previous = this.reconnecting;
|
|
6361
|
+
if (previous) {
|
|
6362
|
+
if (!this.shouldSupersedeReconnect(previous, generation, droppedSocket))
|
|
6363
|
+
return;
|
|
6364
|
+
previous.superseded = true;
|
|
6365
|
+
previous.socket?.close();
|
|
6366
|
+
}
|
|
6367
|
+
const cycle = {
|
|
6368
|
+
generation,
|
|
6369
|
+
socket: null,
|
|
6370
|
+
socketDied: false,
|
|
6371
|
+
superseded: false
|
|
6372
|
+
};
|
|
6373
|
+
this.reconnecting = cycle;
|
|
6374
|
+
this.enqueueConnectionState({ state: "down", cause });
|
|
6375
|
+
this.reconnectWithRetry(cycle).catch((err) => {
|
|
6376
|
+
if (this.isCurrentReconnect(cycle) && !this.closeStarted) {
|
|
5573
6377
|
this.failFatal(err instanceof Error ? err : new SubcProviderError(String(err)));
|
|
6378
|
+
}
|
|
5574
6379
|
}).finally(() => {
|
|
5575
|
-
if (this.
|
|
6380
|
+
if (this.isCurrentReconnect(cycle))
|
|
5576
6381
|
this.reconnecting = null;
|
|
5577
6382
|
});
|
|
5578
|
-
this.reconnecting = promise;
|
|
5579
6383
|
}
|
|
5580
|
-
async reconnectWithRetry(
|
|
6384
|
+
async reconnectWithRetry(cycle) {
|
|
5581
6385
|
let attempt = 0;
|
|
5582
6386
|
let delay = this.opts.reconnectBackoff.baseMs;
|
|
5583
6387
|
for (;; ) {
|
|
6388
|
+
if (!this.isCurrentReconnect(cycle))
|
|
6389
|
+
return;
|
|
5584
6390
|
if (this.closeStarted)
|
|
5585
6391
|
throw new SubcProviderError("provider closed");
|
|
6392
|
+
cycle.socket = null;
|
|
6393
|
+
cycle.socketDied = false;
|
|
5586
6394
|
attempt += 1;
|
|
5587
|
-
this.
|
|
6395
|
+
this.enqueueReconnectState(cycle, attempt);
|
|
5588
6396
|
try {
|
|
5589
|
-
const opened = await SubcProvider.openConnection(this.opts)
|
|
5590
|
-
|
|
6397
|
+
const opened = await SubcProvider.openConnection(this.opts, (sock) => {
|
|
6398
|
+
if (!this.isCurrentReconnect(cycle)) {
|
|
6399
|
+
sock.close();
|
|
6400
|
+
return;
|
|
6401
|
+
}
|
|
6402
|
+
cycle.socket = sock;
|
|
6403
|
+
});
|
|
6404
|
+
if (!this.isCurrentReconnect(cycle) || this.closeStarted) {
|
|
5591
6405
|
opened.sock.close();
|
|
5592
|
-
|
|
6406
|
+
if (this.closeStarted)
|
|
6407
|
+
throw new SubcProviderError("provider closed");
|
|
6408
|
+
return;
|
|
5593
6409
|
}
|
|
5594
|
-
this.replaceConnection(opened);
|
|
6410
|
+
const epoch = this.replaceConnection(opened, cycle.generation);
|
|
6411
|
+
this.reconnecting = null;
|
|
6412
|
+
if (this.reconnecting !== null) {
|
|
6413
|
+
throw new SubcProviderError("reconnect state must clear before restored", "reconnect_state");
|
|
6414
|
+
}
|
|
6415
|
+
this.scheduleRestored(cycle.generation, epoch);
|
|
5595
6416
|
return;
|
|
5596
6417
|
} catch (err) {
|
|
6418
|
+
if (!this.isCurrentReconnect(cycle))
|
|
6419
|
+
return;
|
|
6420
|
+
if (cycle.socket)
|
|
6421
|
+
cycle.socketDied = true;
|
|
5597
6422
|
if (this.closeStarted)
|
|
5598
6423
|
throw err;
|
|
5599
6424
|
if (!isProviderReconnectTransient(err))
|
|
@@ -5603,16 +6428,29 @@ class SubcProvider {
|
|
|
5603
6428
|
}
|
|
5604
6429
|
}
|
|
5605
6430
|
}
|
|
5606
|
-
|
|
6431
|
+
isCurrentReconnect(cycle) {
|
|
6432
|
+
return !cycle.superseded && this.reconnecting === cycle && this.generation === cycle.generation;
|
|
6433
|
+
}
|
|
6434
|
+
shouldSupersedeReconnect(cycle, generation, droppedSocket) {
|
|
6435
|
+
return cycle.generation < generation || cycle.socketDied || cycle.socket === droppedSocket;
|
|
6436
|
+
}
|
|
6437
|
+
enqueueReconnectState(cycle, attempt) {
|
|
6438
|
+
if (!this.isCurrentReconnect(cycle))
|
|
6439
|
+
return;
|
|
6440
|
+
this.enqueueConnectionState({ state: "reconnecting", attempt }, cycle.generation, cycle);
|
|
6441
|
+
}
|
|
6442
|
+
replaceConnection(opened, generation) {
|
|
5607
6443
|
this.sock.close();
|
|
5608
6444
|
this.sock = opened.sock;
|
|
5609
6445
|
this.currentConn = opened.conn;
|
|
5610
6446
|
this.storage = opened.ack.storage;
|
|
5611
6447
|
this.closedErr = null;
|
|
5612
6448
|
this.connectionEpoch += 1;
|
|
5613
|
-
|
|
6449
|
+
this.connectionToken = newConnectionToken();
|
|
6450
|
+
this.liveRoutes.clear();
|
|
6451
|
+
this.nextCorr = 1n;
|
|
5614
6452
|
this.readLoop(opened.sock, generation);
|
|
5615
|
-
|
|
6453
|
+
return this.connectionEpoch;
|
|
5616
6454
|
}
|
|
5617
6455
|
scheduleRestored(generation, epoch) {
|
|
5618
6456
|
if (!this.opts.onConnectionState)
|
|
@@ -5620,7 +6458,7 @@ class SubcProvider {
|
|
|
5620
6458
|
const token = ++this.restoredDebounceToken;
|
|
5621
6459
|
this.opts.sleep(this.opts.restoredDebounceMs).then(() => {
|
|
5622
6460
|
if (token === this.restoredDebounceToken && !this.closeStarted && this.sock && this.generation === generation && this.connectionEpoch === epoch) {
|
|
5623
|
-
this.enqueueConnectionState({ state: "restored", epoch });
|
|
6461
|
+
this.enqueueConnectionState({ state: "restored", epoch }, generation);
|
|
5624
6462
|
}
|
|
5625
6463
|
}).catch((err) => {
|
|
5626
6464
|
if (token === this.restoredDebounceToken && !this.closeStarted) {
|
|
@@ -5631,10 +6469,10 @@ class SubcProvider {
|
|
|
5631
6469
|
cancelRestoredDebounce() {
|
|
5632
6470
|
this.restoredDebounceToken += 1;
|
|
5633
6471
|
}
|
|
5634
|
-
enqueueConnectionState(event) {
|
|
6472
|
+
enqueueConnectionState(event, generation, reconnect) {
|
|
5635
6473
|
if (!this.opts.onConnectionState)
|
|
5636
6474
|
return;
|
|
5637
|
-
this.stateQueue.push(event);
|
|
6475
|
+
this.stateQueue.push({ event, generation, reconnect });
|
|
5638
6476
|
if (!this.drainingStateQueue)
|
|
5639
6477
|
this.drainConnectionStateQueue();
|
|
5640
6478
|
}
|
|
@@ -5644,7 +6482,12 @@ class SubcProvider {
|
|
|
5644
6482
|
this.drainingStateQueue = true;
|
|
5645
6483
|
try {
|
|
5646
6484
|
while (this.stateQueue.length > 0) {
|
|
5647
|
-
const
|
|
6485
|
+
const queued = this.stateQueue[0];
|
|
6486
|
+
if (this.closeStarted || queued.generation !== undefined && queued.generation !== this.generation || queued.reconnect?.superseded) {
|
|
6487
|
+
this.stateQueue.shift();
|
|
6488
|
+
continue;
|
|
6489
|
+
}
|
|
6490
|
+
const { event } = queued;
|
|
5648
6491
|
try {
|
|
5649
6492
|
await this.opts.onConnectionState?.(event);
|
|
5650
6493
|
this.stateQueue.shift();
|
|
@@ -5664,6 +6507,24 @@ class SubcProvider {
|
|
|
5664
6507
|
this.drainConnectionStateQueue();
|
|
5665
6508
|
}
|
|
5666
6509
|
}
|
|
6510
|
+
isLiveHandle(handle) {
|
|
6511
|
+
return belongsToConnection(handle, this.connectionToken) && this.liveRoutes.get(handle.channel) === handle;
|
|
6512
|
+
}
|
|
6513
|
+
assertLiveHandle(handle) {
|
|
6514
|
+
if (!this.isLiveHandle(handle))
|
|
6515
|
+
throw new StaleRouteHandleError(handle);
|
|
6516
|
+
}
|
|
6517
|
+
allocateCorr() {
|
|
6518
|
+
const maximum = 0xffffffffffffffffn;
|
|
6519
|
+
if (this.nextCorr > maximum) {
|
|
6520
|
+
const error2 = new SubcProviderError("channel-0 correlation id allocator exhausted", "corr_exhausted");
|
|
6521
|
+
this.handleUnexpectedDrop(this.sock, this.generation, error2);
|
|
6522
|
+
throw error2;
|
|
6523
|
+
}
|
|
6524
|
+
const corr = this.nextCorr;
|
|
6525
|
+
this.nextCorr += 1n;
|
|
6526
|
+
return corr;
|
|
6527
|
+
}
|
|
5667
6528
|
failFatal(err) {
|
|
5668
6529
|
if (!this.closedErr)
|
|
5669
6530
|
this.closedErr = err;
|
|
@@ -5677,8 +6538,16 @@ class SubcProvider {
|
|
|
5677
6538
|
this.resolveClosed();
|
|
5678
6539
|
}
|
|
5679
6540
|
}
|
|
5680
|
-
function routeKey(
|
|
5681
|
-
return `${
|
|
6541
|
+
function routeKey(handle, corr) {
|
|
6542
|
+
return `${handle.channel}:${handle.epoch}:${corr}`;
|
|
6543
|
+
}
|
|
6544
|
+
function providerErrorFromFrame(frame) {
|
|
6545
|
+
try {
|
|
6546
|
+
const body = parseJson(frame.body);
|
|
6547
|
+
return new SubcProviderError(body.message ?? "subc error", body.code);
|
|
6548
|
+
} catch {
|
|
6549
|
+
return new SubcProviderError(Buffer2.from(frame.body).toString("utf8") || "subc error");
|
|
6550
|
+
}
|
|
5682
6551
|
}
|
|
5683
6552
|
function launchNonce(opts) {
|
|
5684
6553
|
const nonce = opts.launchNonce ?? process.env[SUBC_LAUNCH_NONCE_ENV2];
|
|
@@ -5693,6 +6562,7 @@ function normalizeProviderConnectOptions(opts) {
|
|
|
5693
6562
|
handshakeTimeoutMs: opts.handshakeTimeoutMs,
|
|
5694
6563
|
controlOps: opts.controlOps,
|
|
5695
6564
|
onBind: opts.onBind,
|
|
6565
|
+
onBound: opts.onBound,
|
|
5696
6566
|
onRouteGone: opts.onRouteGone,
|
|
5697
6567
|
reconnectBackoff: opts.reconnectBackoff ?? DEFAULT_RECONNECT_BACKOFF,
|
|
5698
6568
|
sleep: opts.sleep ?? ((ms) => new Promise((resolve7) => setTimeout(resolve7, ms))),
|
|
@@ -5710,7 +6580,7 @@ function normalizedControlOps(controlOps) {
|
|
|
5710
6580
|
}
|
|
5711
6581
|
function buildHelloFrame(opts) {
|
|
5712
6582
|
const nonce = launchNonce(opts);
|
|
5713
|
-
return buildFrame(FrameType.Hello, controlFlags(), 0, HELLO_CORR, encodeJson({
|
|
6583
|
+
return buildFrame(FrameType.Hello, controlFlags(), 0, 0, HELLO_CORR, encodeJson({
|
|
5714
6584
|
manifest: normalizeManifest(opts.manifest),
|
|
5715
6585
|
protocol_ver: PROTOCOL_VERSION,
|
|
5716
6586
|
control_ops: normalizedControlOps(opts.controlOps),
|
|
@@ -5749,14 +6619,17 @@ async function sendFrame(sock, frame) {
|
|
|
5749
6619
|
await sock.write(encodeFrame(frame), Date.now() + WRITE_TIMEOUT_MS);
|
|
5750
6620
|
}
|
|
5751
6621
|
async function expectHelloAck(sock, deadline) {
|
|
5752
|
-
const
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
6622
|
+
const frame = await sock.readFrame(deadline, deadline);
|
|
6623
|
+
switch (frame.header.ty) {
|
|
6624
|
+
case FrameType.HelloAck: {
|
|
6625
|
+
const ack = parseJson(frame.body);
|
|
6626
|
+
if (ack.negotiated_ver !== PROTOCOL_VERSION) {
|
|
6627
|
+
throw new SubcProviderError(`subc negotiated protocol ${ack.negotiated_ver}; expected exactly ${PROTOCOL_VERSION}`, "unsupported_version");
|
|
6628
|
+
}
|
|
6629
|
+
return ack;
|
|
6630
|
+
}
|
|
5758
6631
|
case FrameType.Error: {
|
|
5759
|
-
const error2 = parseJson(body);
|
|
6632
|
+
const error2 = parseJson(frame.body);
|
|
5760
6633
|
throw new SubcProviderError(`subc rejected HELLO: ${error2.code ?? "unknown"} — ${error2.message ?? "subc error"}`, error2.code);
|
|
5761
6634
|
}
|
|
5762
6635
|
default:
|
|
@@ -5903,6 +6776,7 @@ var init_provider = __esm(() => {
|
|
|
5903
6776
|
init_client();
|
|
5904
6777
|
init_connection_file();
|
|
5905
6778
|
init_envelope();
|
|
6779
|
+
init_route_handle();
|
|
5906
6780
|
init_socket();
|
|
5907
6781
|
SubcProviderError = class SubcProviderError extends Error {
|
|
5908
6782
|
code;
|
|
@@ -5913,9 +6787,10 @@ var init_provider = __esm(() => {
|
|
|
5913
6787
|
};
|
|
5914
6788
|
});
|
|
5915
6789
|
|
|
5916
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
6790
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.5.0/node_modules/@cortexkit/subc-client/dist/index.js
|
|
5917
6791
|
var init_dist = __esm(() => {
|
|
5918
6792
|
init_client();
|
|
6793
|
+
init_route_handle();
|
|
5919
6794
|
init_connection_file();
|
|
5920
6795
|
init_envelope();
|
|
5921
6796
|
init_auth();
|
|
@@ -5932,15 +6807,17 @@ class BgSubscription {
|
|
|
5932
6807
|
identity;
|
|
5933
6808
|
acquireClient;
|
|
5934
6809
|
dropClient;
|
|
6810
|
+
consumerIdentity;
|
|
5935
6811
|
onNudge;
|
|
5936
6812
|
sleep;
|
|
5937
6813
|
stopped = false;
|
|
5938
6814
|
current = null;
|
|
5939
6815
|
loop;
|
|
5940
|
-
constructor(identity, acquireClient, dropClient, onNudge, sleep2) {
|
|
6816
|
+
constructor(identity, acquireClient, dropClient, consumerIdentity, onNudge, sleep2) {
|
|
5941
6817
|
this.identity = identity;
|
|
5942
6818
|
this.acquireClient = acquireClient;
|
|
5943
6819
|
this.dropClient = dropClient;
|
|
6820
|
+
this.consumerIdentity = consumerIdentity;
|
|
5944
6821
|
this.onNudge = onNudge;
|
|
5945
6822
|
this.sleep = sleep2;
|
|
5946
6823
|
this.loop = this.run();
|
|
@@ -5969,9 +6846,9 @@ class BgSubscription {
|
|
|
5969
6846
|
}
|
|
5970
6847
|
if (this.stopped)
|
|
5971
6848
|
return;
|
|
5972
|
-
let
|
|
6849
|
+
let route;
|
|
5973
6850
|
try {
|
|
5974
|
-
|
|
6851
|
+
route = await client.routeOpen({ kind: "tool_provider", module_id: AFT_MODULE_ID }, this.identity, { consumerIdentity: this.consumerIdentity });
|
|
5975
6852
|
} catch (err) {
|
|
5976
6853
|
if (isConsumerReconnectTransient(err))
|
|
5977
6854
|
this.dropClient(client);
|
|
@@ -5979,12 +6856,12 @@ class BgSubscription {
|
|
|
5979
6856
|
continue;
|
|
5980
6857
|
}
|
|
5981
6858
|
if (this.stopped) {
|
|
5982
|
-
safeCloseRoute(client,
|
|
6859
|
+
safeCloseRoute(client, route);
|
|
5983
6860
|
return;
|
|
5984
6861
|
}
|
|
5985
6862
|
const subscribedAt = Date.now();
|
|
5986
6863
|
try {
|
|
5987
|
-
const sub = client.subscribe(
|
|
6864
|
+
const sub = client.subscribe(route, { op: "bg_events" }, () => {
|
|
5988
6865
|
if (!this.stopped)
|
|
5989
6866
|
this.onNudge();
|
|
5990
6867
|
});
|
|
@@ -6004,7 +6881,7 @@ class BgSubscription {
|
|
|
6004
6881
|
attempt = 0;
|
|
6005
6882
|
} finally {
|
|
6006
6883
|
this.current = null;
|
|
6007
|
-
safeCloseRoute(client,
|
|
6884
|
+
safeCloseRoute(client, route);
|
|
6008
6885
|
}
|
|
6009
6886
|
await this.backoff(attempt++);
|
|
6010
6887
|
}
|
|
@@ -6017,12 +6894,12 @@ class BgSubscription {
|
|
|
6017
6894
|
function isRecord(value) {
|
|
6018
6895
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6019
6896
|
}
|
|
6020
|
-
function
|
|
6021
|
-
return err instanceof SubcError && err.code === "unknown_channel";
|
|
6897
|
+
function isRouteProvenAbsentError(err) {
|
|
6898
|
+
return err instanceof SubcError && err.code === "unknown_channel" || err instanceof StaleRouteHandleError;
|
|
6022
6899
|
}
|
|
6023
|
-
function safeCloseRoute(client,
|
|
6900
|
+
function safeCloseRoute(client, route) {
|
|
6024
6901
|
try {
|
|
6025
|
-
client.closeRouteChannel(
|
|
6902
|
+
client.closeRouteChannel(route).catch(() => {
|
|
6026
6903
|
return;
|
|
6027
6904
|
});
|
|
6028
6905
|
} catch {}
|
|
@@ -6106,6 +6983,7 @@ class SubcTransportPool {
|
|
|
6106
6983
|
harness;
|
|
6107
6984
|
connectionFile;
|
|
6108
6985
|
handshakeTimeoutMs;
|
|
6986
|
+
consumerIdentity;
|
|
6109
6987
|
connectFn;
|
|
6110
6988
|
onBgEventsNudge;
|
|
6111
6989
|
bgBackoffSleep;
|
|
@@ -6119,6 +6997,7 @@ class SubcTransportPool {
|
|
|
6119
6997
|
this.connectionFile = options.connectionFile;
|
|
6120
6998
|
this.harness = options.harness;
|
|
6121
6999
|
this.handshakeTimeoutMs = options.handshakeTimeoutMs;
|
|
7000
|
+
this.consumerIdentity = options.consumerIdentity;
|
|
6122
7001
|
this.connectFn = options.connect ?? ((opts) => SubcClient.connect(opts));
|
|
6123
7002
|
this.onBgEventsNudge = options.onBgEventsNudge;
|
|
6124
7003
|
this.bgBackoffSleep = options.bgBackoffSleep ?? ((ms) => new Promise((resolve7) => setTimeout(resolve7, ms)));
|
|
@@ -6141,6 +7020,11 @@ class SubcTransportPool {
|
|
|
6141
7020
|
return null;
|
|
6142
7021
|
return this.transports.get(key) ?? null;
|
|
6143
7022
|
}
|
|
7023
|
+
activeBridges() {
|
|
7024
|
+
if (!this.client || this.shuttingDown)
|
|
7025
|
+
return [];
|
|
7026
|
+
return [...this.transports.values()];
|
|
7027
|
+
}
|
|
6144
7028
|
async toolCall(projectRoot, runtime, name, rawArgs = {}, options) {
|
|
6145
7029
|
return this.getBridge(projectRoot).toolCall(runtime.sessionID, name, rawArgs, options);
|
|
6146
7030
|
}
|
|
@@ -6171,7 +7055,7 @@ class SubcTransportPool {
|
|
|
6171
7055
|
throw new RouteTornDownError("subc session closed");
|
|
6172
7056
|
}
|
|
6173
7057
|
try {
|
|
6174
|
-
const opened = await this.
|
|
7058
|
+
const opened = await this.routeHandle(client, identity, record);
|
|
6175
7059
|
if (!this.isCurrentSession(key, record)) {
|
|
6176
7060
|
throw new RouteTornDownError("subc session closed");
|
|
6177
7061
|
}
|
|
@@ -6197,29 +7081,29 @@ class SubcTransportPool {
|
|
|
6197
7081
|
if (isConsumerReconnectTransient(err)) {
|
|
6198
7082
|
this.transportFailures = 0;
|
|
6199
7083
|
this.dropClient(client);
|
|
6200
|
-
} else if (!
|
|
7084
|
+
} else if (!isRouteProvenAbsentError(err) && ++this.transportFailures >= MAX_CONSECUTIVE_TRANSPORT_FAILURES) {
|
|
6201
7085
|
this.transportFailures = 0;
|
|
6202
7086
|
this.dropClient(client);
|
|
6203
7087
|
}
|
|
6204
7088
|
}
|
|
6205
7089
|
};
|
|
6206
|
-
const requestOnRoute = async (
|
|
6207
|
-
const reply = await client.request(
|
|
7090
|
+
const requestOnRoute = async (route2) => {
|
|
7091
|
+
const reply = await client.request(route2, body, { timeoutMs, onProgress });
|
|
6208
7092
|
if (this.isCurrentSession(key, record) && this.client === client) {
|
|
6209
7093
|
this.transportFailures = 0;
|
|
6210
7094
|
}
|
|
6211
7095
|
this.ensureBgSubscription(identity, record);
|
|
6212
7096
|
return reply;
|
|
6213
7097
|
};
|
|
6214
|
-
let {
|
|
7098
|
+
let { route, entry } = await openRoute();
|
|
6215
7099
|
try {
|
|
6216
|
-
return await requestOnRoute(
|
|
7100
|
+
return await requestOnRoute(route);
|
|
6217
7101
|
} catch (err) {
|
|
6218
|
-
if (
|
|
7102
|
+
if (isRouteProvenAbsentError(err) && this.isCurrentSession(key, record) && this.client === client) {
|
|
6219
7103
|
clearRouteEntry(entry);
|
|
6220
|
-
({
|
|
7104
|
+
({ route, entry } = await openRoute());
|
|
6221
7105
|
try {
|
|
6222
|
-
return await requestOnRoute(
|
|
7106
|
+
return await requestOnRoute(route);
|
|
6223
7107
|
} catch (retryErr) {
|
|
6224
7108
|
handleRequestFailure(retryErr, entry);
|
|
6225
7109
|
throw retryErr;
|
|
@@ -6261,24 +7145,26 @@ class SubcTransportPool {
|
|
|
6261
7145
|
});
|
|
6262
7146
|
return this.connecting;
|
|
6263
7147
|
}
|
|
6264
|
-
async
|
|
7148
|
+
async routeHandle(client, identity, record) {
|
|
6265
7149
|
const key = identityKey(identity);
|
|
6266
7150
|
const existing = record.routeEntry;
|
|
6267
|
-
if (existing?.
|
|
6268
|
-
return {
|
|
7151
|
+
if (existing?.handle != null)
|
|
7152
|
+
return { route: existing.handle, entry: existing };
|
|
6269
7153
|
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
|
|
7154
|
+
return { route: await existing.opening, entry: existing };
|
|
7155
|
+
const entry = { client, opening: null, handle: null, closed: false };
|
|
7156
|
+
const opening = client.routeOpen({ kind: "tool_provider", module_id: AFT_MODULE_ID }, identity, {
|
|
7157
|
+
consumerIdentity: this.consumerIdentity
|
|
7158
|
+
}).then((route) => {
|
|
6273
7159
|
if (!this.isCurrentSession(key, record) || record.routeEntry !== entry || entry.closed || this.client !== client) {
|
|
6274
|
-
safeCloseRoute(client,
|
|
7160
|
+
safeCloseRoute(client, route);
|
|
6275
7161
|
if (record.routeEntry === entry)
|
|
6276
7162
|
record.routeEntry = null;
|
|
6277
7163
|
throw new RouteTornDownError("subc route opened after teardown");
|
|
6278
7164
|
}
|
|
6279
|
-
entry.
|
|
7165
|
+
entry.handle = route;
|
|
6280
7166
|
entry.opening = null;
|
|
6281
|
-
return
|
|
7167
|
+
return route;
|
|
6282
7168
|
}).catch((err) => {
|
|
6283
7169
|
const current = this.isCurrentSession(key, record);
|
|
6284
7170
|
if (record.routeEntry === entry) {
|
|
@@ -6292,7 +7178,7 @@ class SubcTransportPool {
|
|
|
6292
7178
|
});
|
|
6293
7179
|
entry.opening = opening;
|
|
6294
7180
|
record.routeEntry = entry;
|
|
6295
|
-
return {
|
|
7181
|
+
return { route: await opening, entry };
|
|
6296
7182
|
}
|
|
6297
7183
|
ensureBgSubscription(identity, record) {
|
|
6298
7184
|
if (this.shuttingDown || !this.onBgEventsNudge)
|
|
@@ -6303,7 +7189,7 @@ class SubcTransportPool {
|
|
|
6303
7189
|
if (record.bgSub)
|
|
6304
7190
|
return;
|
|
6305
7191
|
const onNudge = () => this.onBgEventsNudge?.(identity.project_root, identity.session);
|
|
6306
|
-
const sub = new BgSubscription(identity, () => this.ensureClient(), (client) => this.dropClient(client), onNudge, this.bgBackoffSleep);
|
|
7192
|
+
const sub = new BgSubscription(identity, () => this.ensureClient(), (client) => this.dropClient(client), this.consumerIdentity, onNudge, this.bgBackoffSleep);
|
|
6307
7193
|
record.bgSub = sub;
|
|
6308
7194
|
}
|
|
6309
7195
|
dropClient(client) {
|
|
@@ -6324,9 +7210,13 @@ class SubcTransportPool {
|
|
|
6324
7210
|
}
|
|
6325
7211
|
}
|
|
6326
7212
|
setConfigureOverride(_key, _value) {}
|
|
7213
|
+
async reconfigure(_projectRoot, _overrides) {}
|
|
6327
7214
|
async replaceBinary(path2) {
|
|
6328
7215
|
return path2;
|
|
6329
7216
|
}
|
|
7217
|
+
isShutdown() {
|
|
7218
|
+
return this.shuttingDown;
|
|
7219
|
+
}
|
|
6330
7220
|
async shutdown() {
|
|
6331
7221
|
this.shuttingDown = true;
|
|
6332
7222
|
const subs = [];
|
|
@@ -6350,10 +7240,10 @@ class SubcTransportPool {
|
|
|
6350
7240
|
this.transports.clear();
|
|
6351
7241
|
await Promise.allSettled(subs.map((sub) => sub.stop()));
|
|
6352
7242
|
await Promise.allSettled(entries.map(async (entry) => {
|
|
6353
|
-
if (entry.
|
|
7243
|
+
if (entry.handle == null)
|
|
6354
7244
|
return;
|
|
6355
7245
|
try {
|
|
6356
|
-
await entry.client.closeRouteChannel(entry.
|
|
7246
|
+
await entry.client.closeRouteChannel(entry.handle);
|
|
6357
7247
|
} catch {}
|
|
6358
7248
|
}));
|
|
6359
7249
|
if (client) {
|
|
@@ -6382,9 +7272,9 @@ class SubcTransportPool {
|
|
|
6382
7272
|
entry.closed = true;
|
|
6383
7273
|
if (sub)
|
|
6384
7274
|
await sub.stop();
|
|
6385
|
-
if (entry?.
|
|
7275
|
+
if (entry?.handle != null) {
|
|
6386
7276
|
try {
|
|
6387
|
-
await entry.client.closeRouteChannel(entry.
|
|
7277
|
+
await entry.client.closeRouteChannel(entry.handle);
|
|
6388
7278
|
} catch {}
|
|
6389
7279
|
}
|
|
6390
7280
|
}
|
|
@@ -6485,18 +7375,25 @@ function formatReadFooter(agentSpecifiedRange, data, options) {
|
|
|
6485
7375
|
}
|
|
6486
7376
|
|
|
6487
7377
|
// ../aft-bridge/dist/transport-factory.js
|
|
6488
|
-
import { homedir as
|
|
6489
|
-
import { isAbsolute as isAbsolute5, join as
|
|
7378
|
+
import { homedir as homedir11 } from "node:os";
|
|
7379
|
+
import { isAbsolute as isAbsolute5, join as join10 } from "node:path";
|
|
6490
7380
|
function resolveConnectionFilePath(raw) {
|
|
6491
7381
|
const trimmed = raw.trim();
|
|
6492
7382
|
if (trimmed.startsWith("~")) {
|
|
6493
|
-
return
|
|
7383
|
+
return join10(homedir11(), trimmed.slice(1).replace(/^[/\\]/, ""));
|
|
6494
7384
|
}
|
|
6495
7385
|
if (isAbsolute5(trimmed))
|
|
6496
7386
|
return trimmed;
|
|
6497
|
-
return
|
|
7387
|
+
return join10(homedir11(), trimmed);
|
|
6498
7388
|
}
|
|
6499
7389
|
async function createAftTransportPool(opts) {
|
|
7390
|
+
let binaryPath = opts.binaryPath;
|
|
7391
|
+
const createPool = () => createConcreteAftTransportPool({ ...opts, binaryPath });
|
|
7392
|
+
return new RevivableTransportPool(await createPool(), createPool, (path2) => {
|
|
7393
|
+
binaryPath = path2;
|
|
7394
|
+
});
|
|
7395
|
+
}
|
|
7396
|
+
async function createConcreteAftTransportPool(opts) {
|
|
6500
7397
|
const raw = opts.subcConnectionFile?.trim();
|
|
6501
7398
|
if (raw && raw.length > 0) {
|
|
6502
7399
|
const connectionFile = resolveConnectionFilePath(raw);
|
|
@@ -6507,6 +7404,7 @@ async function createAftTransportPool(opts) {
|
|
|
6507
7404
|
return new SubcTransportPool({
|
|
6508
7405
|
connectionFile,
|
|
6509
7406
|
harness: opts.harness,
|
|
7407
|
+
consumerIdentity: opts.subcConsumerIdentity,
|
|
6510
7408
|
onBgEventsNudge: opts.onBgEventsNudge
|
|
6511
7409
|
});
|
|
6512
7410
|
}
|
|
@@ -6514,6 +7412,7 @@ async function createAftTransportPool(opts) {
|
|
|
6514
7412
|
}
|
|
6515
7413
|
var init_transport_factory = __esm(() => {
|
|
6516
7414
|
init_pool();
|
|
7415
|
+
init_revivable_transport();
|
|
6517
7416
|
init_subc_transport();
|
|
6518
7417
|
});
|
|
6519
7418
|
|
|
@@ -6631,6 +7530,7 @@ __export(exports_dist, {
|
|
|
6631
7530
|
timeoutForCommand: () => timeoutForCommand,
|
|
6632
7531
|
tagStderrLine: () => tagStderrLine,
|
|
6633
7532
|
stripJsoncSymbols: () => stripJsoncSymbols,
|
|
7533
|
+
stripHarnessSpecificConfigKeys: () => stripHarnessSpecificConfigKeys,
|
|
6634
7534
|
statusBarLine: () => statusBarLine,
|
|
6635
7535
|
sleep: () => sleep,
|
|
6636
7536
|
shouldShowAnnouncement: () => shouldShowAnnouncement,
|
|
@@ -6645,6 +7545,8 @@ __export(exports_dist, {
|
|
|
6645
7545
|
resolveCortexKitProjectConfigPath: () => resolveCortexKitProjectConfigPath,
|
|
6646
7546
|
resolveCortexKitConfigPaths: () => resolveCortexKitConfigPaths,
|
|
6647
7547
|
resolveBashKillTimeout: () => resolveBashKillTimeout,
|
|
7548
|
+
resolveAftStorageRoot: () => resolveAftStorageRoot,
|
|
7549
|
+
resolveAftLogPath: () => resolveAftLogPath,
|
|
6648
7550
|
repairRootScopedStorageFile: () => repairRootScopedStorageFile,
|
|
6649
7551
|
readConfigTiers: () => readConfigTiers,
|
|
6650
7552
|
projectRootKeyHash: () => projectRootKeyHash,
|
|
@@ -6687,6 +7589,7 @@ __export(exports_dist, {
|
|
|
6687
7589
|
ensureOnnxRuntime: () => ensureOnnxRuntime,
|
|
6688
7590
|
ensureBinary: () => ensureBinary,
|
|
6689
7591
|
downloadBinary: () => downloadBinary,
|
|
7592
|
+
decodeFileUrl: () => decodeFileUrl,
|
|
6690
7593
|
createStatusBarEmitState: () => createStatusBarEmitState,
|
|
6691
7594
|
createAftTransportPool: () => createAftTransportPool,
|
|
6692
7595
|
compressionSavingsPercent: () => compressionSavingsPercent,
|
|
@@ -6702,11 +7605,17 @@ __export(exports_dist, {
|
|
|
6702
7605
|
__onnxTest__: () => __test__,
|
|
6703
7606
|
SubcTransportPool: () => SubcTransportPool,
|
|
6704
7607
|
STATUS_BAR_HEARTBEAT_CALLS: () => STATUS_BAR_HEARTBEAT_CALLS,
|
|
7608
|
+
RotatingLogSink: () => RotatingLogSink,
|
|
7609
|
+
RevivableTransportPool: () => RevivableTransportPool,
|
|
6705
7610
|
PLATFORM_ASSET_MAP: () => PLATFORM_ASSET_MAP,
|
|
6706
7611
|
PLATFORM_ARCH_MAP: () => PLATFORM_ARCH_MAP,
|
|
6707
7612
|
PLAIN_CALLGRAPH_THEME: () => PLAIN_CALLGRAPH_THEME,
|
|
7613
|
+
PI_ONLY_KEYS: () => PI_ONLY_KEYS,
|
|
7614
|
+
OPENCODE_ONLY_KEYS: () => OPENCODE_ONLY_KEYS,
|
|
6708
7615
|
LONG_RUNNING_COMMAND_TIMEOUT_MS: () => LONG_RUNNING_COMMAND_TIMEOUT_MS,
|
|
6709
7616
|
HomeProjectRootError: () => HomeProjectRootError,
|
|
7617
|
+
DEFAULT_LOG_GENERATIONS: () => DEFAULT_LOG_GENERATIONS,
|
|
7618
|
+
DEFAULT_LOG_BYTES: () => DEFAULT_LOG_BYTES,
|
|
6710
7619
|
BridgeTransportTimeoutError: () => BridgeTransportTimeoutError,
|
|
6711
7620
|
BridgePool: () => BridgePool,
|
|
6712
7621
|
BinaryBridge: () => BinaryBridge
|
|
@@ -6717,8 +7626,10 @@ var init_dist2 = __esm(() => {
|
|
|
6717
7626
|
init_bridge();
|
|
6718
7627
|
init_callgraph_format();
|
|
6719
7628
|
init_command_timeouts();
|
|
7629
|
+
init_config_keys();
|
|
6720
7630
|
init_config_tiers();
|
|
6721
7631
|
init_downloader();
|
|
7632
|
+
init_durable_log();
|
|
6722
7633
|
init_migration();
|
|
6723
7634
|
init_npm_resolver();
|
|
6724
7635
|
init_onnx_runtime();
|
|
@@ -6727,70 +7638,70 @@ var init_dist2 = __esm(() => {
|
|
|
6727
7638
|
init_pool();
|
|
6728
7639
|
init_project_identity();
|
|
6729
7640
|
init_resolver();
|
|
7641
|
+
init_revivable_transport();
|
|
6730
7642
|
init_subc_transport();
|
|
6731
7643
|
init_transport_factory();
|
|
6732
7644
|
});
|
|
6733
7645
|
|
|
6734
7646
|
// src/lib/paths.ts
|
|
6735
|
-
import { homedir as
|
|
6736
|
-
import { join as
|
|
7647
|
+
import { homedir as homedir12 } from "node:os";
|
|
7648
|
+
import { join as join11 } from "node:path";
|
|
6737
7649
|
function getAftBinaryCacheDir() {
|
|
6738
7650
|
if (process.env.AFT_CACHE_DIR) {
|
|
6739
|
-
return
|
|
7651
|
+
return join11(process.env.AFT_CACHE_DIR, "bin");
|
|
6740
7652
|
}
|
|
6741
7653
|
if (process.platform === "win32") {
|
|
6742
7654
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
6743
|
-
const base2 = localAppData ||
|
|
6744
|
-
return
|
|
7655
|
+
const base2 = localAppData || join11(homedir12(), "AppData", "Local");
|
|
7656
|
+
return join11(base2, "aft", "bin");
|
|
6745
7657
|
}
|
|
6746
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
6747
|
-
return
|
|
7658
|
+
const base = process.env.XDG_CACHE_HOME || join11(homedir12(), ".cache");
|
|
7659
|
+
return join11(base, "aft", "bin");
|
|
6748
7660
|
}
|
|
6749
7661
|
function getAftBinaryName() {
|
|
6750
7662
|
return process.platform === "win32" ? "aft.exe" : "aft";
|
|
6751
7663
|
}
|
|
6752
7664
|
function getAftLspPackagesDir() {
|
|
6753
7665
|
if (process.env.AFT_CACHE_DIR) {
|
|
6754
|
-
return
|
|
7666
|
+
return join11(process.env.AFT_CACHE_DIR, "lsp-packages");
|
|
6755
7667
|
}
|
|
6756
7668
|
if (process.platform === "win32") {
|
|
6757
7669
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
6758
|
-
const base2 = localAppData ||
|
|
6759
|
-
return
|
|
7670
|
+
const base2 = localAppData || join11(homedir12(), "AppData", "Local");
|
|
7671
|
+
return join11(base2, "aft", "lsp-packages");
|
|
6760
7672
|
}
|
|
6761
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
6762
|
-
return
|
|
7673
|
+
const base = process.env.XDG_CACHE_HOME || join11(homedir12(), ".cache");
|
|
7674
|
+
return join11(base, "aft", "lsp-packages");
|
|
6763
7675
|
}
|
|
6764
7676
|
function getAftLspBinariesDir() {
|
|
6765
7677
|
if (process.env.AFT_CACHE_DIR) {
|
|
6766
|
-
return
|
|
7678
|
+
return join11(process.env.AFT_CACHE_DIR, "lsp-binaries");
|
|
6767
7679
|
}
|
|
6768
7680
|
if (process.platform === "win32") {
|
|
6769
7681
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
6770
|
-
const base2 = localAppData ||
|
|
6771
|
-
return
|
|
7682
|
+
const base2 = localAppData || join11(homedir12(), "AppData", "Local");
|
|
7683
|
+
return join11(base2, "aft", "lsp-binaries");
|
|
6772
7684
|
}
|
|
6773
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
6774
|
-
return
|
|
7685
|
+
const base = process.env.XDG_CACHE_HOME || join11(homedir12(), ".cache");
|
|
7686
|
+
return join11(base, "aft", "lsp-binaries");
|
|
6775
7687
|
}
|
|
6776
|
-
function
|
|
7688
|
+
function homeDir4() {
|
|
6777
7689
|
if (process.platform === "win32")
|
|
6778
|
-
return process.env.USERPROFILE || process.env.HOME ||
|
|
6779
|
-
return process.env.HOME ||
|
|
7690
|
+
return process.env.USERPROFILE || process.env.HOME || homedir12();
|
|
7691
|
+
return process.env.HOME || homedir12();
|
|
6780
7692
|
}
|
|
6781
|
-
function
|
|
7693
|
+
function dataHome3() {
|
|
6782
7694
|
if (process.env.XDG_DATA_HOME)
|
|
6783
7695
|
return process.env.XDG_DATA_HOME;
|
|
6784
7696
|
if (process.platform === "win32") {
|
|
6785
|
-
return process.env.LOCALAPPDATA || process.env.APPDATA ||
|
|
7697
|
+
return process.env.LOCALAPPDATA || process.env.APPDATA || join11(homeDir4(), "AppData", "Local");
|
|
6786
7698
|
}
|
|
6787
|
-
return
|
|
7699
|
+
return join11(homeDir4(), ".local", "share");
|
|
6788
7700
|
}
|
|
6789
7701
|
function getCortexKitStorageRoot() {
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
return join10(tmpdir2(), filename);
|
|
7702
|
+
if (process.env.AFT_CACHE_DIR)
|
|
7703
|
+
return join11(process.env.AFT_CACHE_DIR, "aft");
|
|
7704
|
+
return join11(dataHome3(), "cortexkit", "aft");
|
|
6794
7705
|
}
|
|
6795
7706
|
var init_paths2 = () => {};
|
|
6796
7707
|
|
|
@@ -6798,8 +7709,8 @@ var init_paths2 = () => {};
|
|
|
6798
7709
|
import { execSync as execSync2, spawnSync as spawnSync3 } from "node:child_process";
|
|
6799
7710
|
import { existsSync as existsSync7 } from "node:fs";
|
|
6800
7711
|
import { createRequire as createRequire2 } from "node:module";
|
|
6801
|
-
import { homedir as
|
|
6802
|
-
import { join as
|
|
7712
|
+
import { homedir as homedir13 } from "node:os";
|
|
7713
|
+
import { join as join12 } from "node:path";
|
|
6803
7714
|
async function loadPluginVersion() {
|
|
6804
7715
|
try {
|
|
6805
7716
|
const bridge = await Promise.resolve().then(() => (init_dist2(), exports_dist));
|
|
@@ -6921,7 +7832,7 @@ function aftBinaryCandidates(preferredVersion) {
|
|
|
6921
7832
|
const candidates = [];
|
|
6922
7833
|
if (preferredVersion) {
|
|
6923
7834
|
const tag = preferredVersion.startsWith("v") ? preferredVersion : `v${preferredVersion}`;
|
|
6924
|
-
pushCandidate(candidates,
|
|
7835
|
+
pushCandidate(candidates, join12(getAftBinaryCacheDir(), tag, getAftBinaryName()));
|
|
6925
7836
|
}
|
|
6926
7837
|
const key = platformKey2();
|
|
6927
7838
|
if (key) {
|
|
@@ -6944,7 +7855,7 @@ function aftBinaryCandidates(preferredVersion) {
|
|
|
6944
7855
|
}
|
|
6945
7856
|
}
|
|
6946
7857
|
} catch {}
|
|
6947
|
-
pushCandidate(candidates,
|
|
7858
|
+
pushCandidate(candidates, join12(homedir13(), ".cargo", "bin", getAftBinaryName()));
|
|
6948
7859
|
return candidates;
|
|
6949
7860
|
}
|
|
6950
7861
|
function findAftBinary(preferredVersion) {
|
|
@@ -6960,21 +7871,21 @@ var init_binary_probe = __esm(async () => {
|
|
|
6960
7871
|
|
|
6961
7872
|
// src/lib/fs-util.ts
|
|
6962
7873
|
import { existsSync as existsSync8, readdirSync as readdirSync3, statSync as statSync5 } from "node:fs";
|
|
6963
|
-
import { join as
|
|
7874
|
+
import { join as join13 } from "node:path";
|
|
6964
7875
|
function dirSize(path2) {
|
|
6965
7876
|
if (!existsSync8(path2)) {
|
|
6966
7877
|
return 0;
|
|
6967
7878
|
}
|
|
6968
|
-
const
|
|
6969
|
-
if (
|
|
6970
|
-
return
|
|
7879
|
+
const stat2 = statSync5(path2);
|
|
7880
|
+
if (stat2.isFile()) {
|
|
7881
|
+
return stat2.size;
|
|
6971
7882
|
}
|
|
6972
|
-
if (!
|
|
7883
|
+
if (!stat2.isDirectory()) {
|
|
6973
7884
|
return 0;
|
|
6974
7885
|
}
|
|
6975
7886
|
let total = 0;
|
|
6976
7887
|
for (const entry of readdirSync3(path2)) {
|
|
6977
|
-
total += dirSize(
|
|
7888
|
+
total += dirSize(join13(path2, entry));
|
|
6978
7889
|
}
|
|
6979
7890
|
return total;
|
|
6980
7891
|
}
|
|
@@ -14597,10 +15508,10 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
14597
15508
|
replacer = null;
|
|
14598
15509
|
indent = EMPTY;
|
|
14599
15510
|
};
|
|
14600
|
-
var
|
|
15511
|
+
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
15512
|
var join_content = (inside, value, gap) => {
|
|
14602
15513
|
const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
|
|
14603
|
-
return
|
|
15514
|
+
return join14(comment, inside, gap);
|
|
14604
15515
|
};
|
|
14605
15516
|
var stringify_string = (holder, key, value) => {
|
|
14606
15517
|
const raw = get_raw_string_literal(holder, key);
|
|
@@ -14622,13 +15533,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
14622
15533
|
if (i !== 0) {
|
|
14623
15534
|
inside += COMMA;
|
|
14624
15535
|
}
|
|
14625
|
-
const before =
|
|
15536
|
+
const before = join14(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
|
|
14626
15537
|
inside += before || LF + deeper_gap;
|
|
14627
15538
|
inside += stringify(i, value, deeper_gap) || STR_NULL;
|
|
14628
15539
|
inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
|
|
14629
15540
|
after_comma = process_comments(value, AFTER(i), deeper_gap);
|
|
14630
15541
|
}
|
|
14631
|
-
inside +=
|
|
15542
|
+
inside += join14(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
14632
15543
|
return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
|
|
14633
15544
|
};
|
|
14634
15545
|
var object_stringify = (value, gap) => {
|
|
@@ -14649,13 +15560,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
14649
15560
|
inside += COMMA;
|
|
14650
15561
|
}
|
|
14651
15562
|
first = false;
|
|
14652
|
-
const before =
|
|
15563
|
+
const before = join14(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
|
|
14653
15564
|
inside += before || LF + deeper_gap;
|
|
14654
15565
|
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
15566
|
after_comma = process_comments(value, AFTER(key), deeper_gap);
|
|
14656
15567
|
};
|
|
14657
15568
|
keys.forEach(iteratee);
|
|
14658
|
-
inside +=
|
|
15569
|
+
inside += join14(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
14659
15570
|
return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
|
|
14660
15571
|
};
|
|
14661
15572
|
function stringify(key, holder, gap) {
|
|
@@ -14749,7 +15660,7 @@ var require_src2 = __commonJS((exports, module) => {
|
|
|
14749
15660
|
|
|
14750
15661
|
// src/lib/jsonc.ts
|
|
14751
15662
|
import { existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
|
|
14752
|
-
import { dirname as
|
|
15663
|
+
import { dirname as dirname6 } from "node:path";
|
|
14753
15664
|
function detectJsoncFile(configDir, baseName) {
|
|
14754
15665
|
const jsoncPath = `${configDir}/${baseName}.jsonc`;
|
|
14755
15666
|
const jsonPath = `${configDir}/${baseName}.json`;
|
|
@@ -14777,7 +15688,7 @@ function readJsoncFile(path2) {
|
|
|
14777
15688
|
}
|
|
14778
15689
|
}
|
|
14779
15690
|
function writeJsoncFile(path2, value, format = "json") {
|
|
14780
|
-
mkdirSync6(
|
|
15691
|
+
mkdirSync6(dirname6(path2), { recursive: true });
|
|
14781
15692
|
const serialized = format === "jsonc" ? import_comment_json.stringify(value, null, 2) : JSON.stringify(value, null, 2);
|
|
14782
15693
|
writeFileSync4(path2, `${serialized}
|
|
14783
15694
|
`);
|
|
@@ -14837,25 +15748,25 @@ var init_self_version = () => {};
|
|
|
14837
15748
|
// src/adapters/opencode.ts
|
|
14838
15749
|
import { execSync as execSync3 } from "node:child_process";
|
|
14839
15750
|
import { existsSync as existsSync10, readFileSync as readFileSync8, rmSync as rmSync4, statSync as statSync6 } from "node:fs";
|
|
14840
|
-
import { homedir as
|
|
14841
|
-
import { dirname as
|
|
15751
|
+
import { homedir as homedir14 } from "node:os";
|
|
15752
|
+
import { dirname as dirname7, join as join14, parse, resolve as resolve7 } from "node:path";
|
|
14842
15753
|
import { fileURLToPath } from "node:url";
|
|
14843
15754
|
function getOpenCodeConfigDir() {
|
|
14844
15755
|
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
14845
15756
|
if (envDir)
|
|
14846
15757
|
return resolve7(envDir);
|
|
14847
|
-
const xdg = process.env.XDG_CONFIG_HOME ||
|
|
14848
|
-
return
|
|
15758
|
+
const xdg = process.env.XDG_CONFIG_HOME || join14(homedir14(), ".config");
|
|
15759
|
+
return join14(xdg, "opencode");
|
|
14849
15760
|
}
|
|
14850
15761
|
function getOpenCodeCacheDir() {
|
|
14851
15762
|
const xdg = process.env.XDG_CACHE_HOME;
|
|
14852
15763
|
if (xdg)
|
|
14853
|
-
return
|
|
15764
|
+
return join14(xdg, "opencode");
|
|
14854
15765
|
if (process.platform === "win32") {
|
|
14855
|
-
const localAppData = process.env.LOCALAPPDATA ??
|
|
14856
|
-
return
|
|
15766
|
+
const localAppData = process.env.LOCALAPPDATA ?? join14(homedir14(), "AppData", "Local");
|
|
15767
|
+
return join14(localAppData, "opencode");
|
|
14857
15768
|
}
|
|
14858
|
-
return
|
|
15769
|
+
return join14(homedir14(), ".cache", "opencode");
|
|
14859
15770
|
}
|
|
14860
15771
|
function hasOpenCodeCli() {
|
|
14861
15772
|
try {
|
|
@@ -14868,12 +15779,12 @@ function hasOpenCodeCli() {
|
|
|
14868
15779
|
function openCodeDesktopAppExists() {
|
|
14869
15780
|
const candidates = [];
|
|
14870
15781
|
if (process.platform === "darwin") {
|
|
14871
|
-
candidates.push("/Applications/OpenCode.app", "/Applications/OpenCode Beta.app",
|
|
15782
|
+
candidates.push("/Applications/OpenCode.app", "/Applications/OpenCode Beta.app", join14(homedir14(), "Applications", "OpenCode.app"), join14(homedir14(), "Applications", "OpenCode Beta.app"));
|
|
14872
15783
|
} else if (process.platform === "win32") {
|
|
14873
|
-
const localAppData = process.env.LOCALAPPDATA ??
|
|
14874
|
-
candidates.push(
|
|
15784
|
+
const localAppData = process.env.LOCALAPPDATA ?? join14(homedir14(), "AppData", "Local");
|
|
15785
|
+
candidates.push(join14(localAppData, "Programs", "opencode"), join14(localAppData, "opencode"));
|
|
14875
15786
|
} else {
|
|
14876
|
-
candidates.push("/opt/OpenCode", "/usr/lib/opencode",
|
|
15787
|
+
candidates.push("/opt/OpenCode", "/usr/lib/opencode", join14(homedir14(), ".local", "share", "applications", "opencode.desktop"));
|
|
14877
15788
|
}
|
|
14878
15789
|
return candidates.some((p) => {
|
|
14879
15790
|
try {
|
|
@@ -14902,15 +15813,15 @@ function pathPointsToOurPlugin(entry) {
|
|
|
14902
15813
|
try {
|
|
14903
15814
|
if (!existsSync10(fsPath))
|
|
14904
15815
|
return false;
|
|
14905
|
-
let searchDir = statSync6(fsPath).isDirectory() ? fsPath :
|
|
15816
|
+
let searchDir = statSync6(fsPath).isDirectory() ? fsPath : dirname7(fsPath);
|
|
14906
15817
|
let pkgJsonPath = null;
|
|
14907
15818
|
while (true) {
|
|
14908
|
-
const candidate =
|
|
15819
|
+
const candidate = join14(searchDir, "package.json");
|
|
14909
15820
|
if (existsSync10(candidate)) {
|
|
14910
15821
|
pkgJsonPath = candidate;
|
|
14911
15822
|
break;
|
|
14912
15823
|
}
|
|
14913
|
-
const parent =
|
|
15824
|
+
const parent = dirname7(searchDir);
|
|
14914
15825
|
if (parent === searchDir || searchDir === parse(searchDir).root)
|
|
14915
15826
|
break;
|
|
14916
15827
|
searchDir = parent;
|
|
@@ -15076,10 +15987,10 @@ class OpenCodeAdapter {
|
|
|
15076
15987
|
};
|
|
15077
15988
|
}
|
|
15078
15989
|
getPluginCacheInfo() {
|
|
15079
|
-
const path2 =
|
|
15990
|
+
const path2 = join14(getOpenCodeCacheDir(), "packages", PLUGIN_ENTRY);
|
|
15080
15991
|
let cached;
|
|
15081
15992
|
try {
|
|
15082
|
-
const installedPkgPath =
|
|
15993
|
+
const installedPkgPath = join14(path2, "node_modules", "@cortexkit", "aft-opencode", "package.json");
|
|
15083
15994
|
if (existsSync10(installedPkgPath)) {
|
|
15084
15995
|
const pkg = JSON.parse(readFileSync8(installedPkgPath, "utf-8"));
|
|
15085
15996
|
cached = typeof pkg.version === "string" ? pkg.version : undefined;
|
|
@@ -15098,7 +16009,7 @@ class OpenCodeAdapter {
|
|
|
15098
16009
|
return getCortexKitStorageRoot();
|
|
15099
16010
|
}
|
|
15100
16011
|
getLogFile() {
|
|
15101
|
-
return
|
|
16012
|
+
return resolveAftLogPath("aft-plugin.log");
|
|
15102
16013
|
}
|
|
15103
16014
|
getInstallHint() {
|
|
15104
16015
|
return "Install OpenCode: https://opencode.ai/docs/install";
|
|
@@ -15140,11 +16051,11 @@ class OpenCodeAdapter {
|
|
|
15140
16051
|
describeStorageSubtrees() {
|
|
15141
16052
|
const storage = this.getStorageDir();
|
|
15142
16053
|
return {
|
|
15143
|
-
index: dirSize(
|
|
15144
|
-
semantic: dirSize(
|
|
15145
|
-
backups: dirSize(
|
|
15146
|
-
url_cache: dirSize(
|
|
15147
|
-
onnxruntime: dirSize(
|
|
16054
|
+
index: dirSize(join14(storage, "index")),
|
|
16055
|
+
semantic: dirSize(join14(storage, "semantic")),
|
|
16056
|
+
backups: dirSize(join14(storage, "backups")),
|
|
16057
|
+
url_cache: dirSize(join14(storage, "url_cache")),
|
|
16058
|
+
onnxruntime: dirSize(join14(storage, "onnxruntime"))
|
|
15148
16059
|
};
|
|
15149
16060
|
}
|
|
15150
16061
|
}
|
|
@@ -15161,15 +16072,15 @@ var init_opencode = __esm(() => {
|
|
|
15161
16072
|
// src/adapters/pi.ts
|
|
15162
16073
|
import { execSync as execSync4, spawnSync as spawnSync4 } from "node:child_process";
|
|
15163
16074
|
import { existsSync as existsSync11, readFileSync as readFileSync9 } from "node:fs";
|
|
15164
|
-
import { homedir as
|
|
15165
|
-
import { join as
|
|
16075
|
+
import { homedir as homedir15 } from "node:os";
|
|
16076
|
+
import { join as join15 } from "node:path";
|
|
15166
16077
|
function getPiAgentDir() {
|
|
15167
16078
|
const envHome = process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME;
|
|
15168
|
-
const home = envHome && envHome.length > 0 ? envHome :
|
|
15169
|
-
return
|
|
16079
|
+
const home = envHome && envHome.length > 0 ? envHome : homedir15();
|
|
16080
|
+
return join15(home, ".pi", "agent");
|
|
15170
16081
|
}
|
|
15171
16082
|
function readPiExtensionIndex() {
|
|
15172
|
-
const settingsPath =
|
|
16083
|
+
const settingsPath = join15(getPiAgentDir(), "settings.json");
|
|
15173
16084
|
if (existsSync11(settingsPath)) {
|
|
15174
16085
|
try {
|
|
15175
16086
|
const raw = readFileSync9(settingsPath, "utf-8");
|
|
@@ -15183,10 +16094,10 @@ function readPiExtensionIndex() {
|
|
|
15183
16094
|
} catch {}
|
|
15184
16095
|
}
|
|
15185
16096
|
const candidates = [
|
|
15186
|
-
|
|
15187
|
-
|
|
15188
|
-
|
|
15189
|
-
|
|
16097
|
+
join15(getPiAgentDir(), "extensions.json"),
|
|
16098
|
+
join15(getPiAgentDir(), "extensions.jsonc"),
|
|
16099
|
+
join15(getPiAgentDir(), "config.json"),
|
|
16100
|
+
join15(getPiAgentDir(), "config.jsonc")
|
|
15190
16101
|
];
|
|
15191
16102
|
for (const path2 of candidates) {
|
|
15192
16103
|
if (!existsSync11(path2))
|
|
@@ -15222,14 +16133,14 @@ function piEntryMatchesAft(entry) {
|
|
|
15222
16133
|
} else if (entry.startsWith("/")) {
|
|
15223
16134
|
resolved = entry;
|
|
15224
16135
|
} else if (entry.length > 0) {
|
|
15225
|
-
resolved =
|
|
16136
|
+
resolved = join15(getPiAgentDir(), entry);
|
|
15226
16137
|
}
|
|
15227
16138
|
if (!resolved)
|
|
15228
16139
|
return false;
|
|
15229
16140
|
try {
|
|
15230
16141
|
if (!existsSync11(resolved))
|
|
15231
16142
|
return false;
|
|
15232
|
-
const pkgPath =
|
|
16143
|
+
const pkgPath = join15(resolved, "package.json");
|
|
15233
16144
|
if (!existsSync11(pkgPath))
|
|
15234
16145
|
return false;
|
|
15235
16146
|
const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
|
|
@@ -15281,7 +16192,7 @@ class PiAdapter {
|
|
|
15281
16192
|
const aftConfigExists = existsSync11(aftConfigPath);
|
|
15282
16193
|
return {
|
|
15283
16194
|
configDir,
|
|
15284
|
-
harnessConfig: index.path ??
|
|
16195
|
+
harnessConfig: index.path ?? join15(configDir, "extensions.json"),
|
|
15285
16196
|
harnessConfigFormat: index.path ? "json" : "none",
|
|
15286
16197
|
aftConfig: aftConfigPath,
|
|
15287
16198
|
aftConfigFormat: aftConfigExists ? "jsonc" : "none"
|
|
@@ -15326,8 +16237,8 @@ class PiAdapter {
|
|
|
15326
16237
|
}
|
|
15327
16238
|
getPluginCacheInfo() {
|
|
15328
16239
|
const candidates = [
|
|
15329
|
-
|
|
15330
|
-
|
|
16240
|
+
join15(getPiAgentDir(), "node_modules", "@cortexkit", "aft-pi", "package.json"),
|
|
16241
|
+
join15(getPiAgentDir(), "extensions", "node_modules", "@cortexkit", "aft-pi", "package.json")
|
|
15331
16242
|
];
|
|
15332
16243
|
for (const candidate of candidates) {
|
|
15333
16244
|
if (!existsSync11(candidate))
|
|
@@ -15344,7 +16255,7 @@ class PiAdapter {
|
|
|
15344
16255
|
} catch {}
|
|
15345
16256
|
}
|
|
15346
16257
|
return {
|
|
15347
|
-
path:
|
|
16258
|
+
path: join15(getPiAgentDir(), "extensions"),
|
|
15348
16259
|
exists: false
|
|
15349
16260
|
};
|
|
15350
16261
|
}
|
|
@@ -15352,7 +16263,7 @@ class PiAdapter {
|
|
|
15352
16263
|
return getCortexKitStorageRoot();
|
|
15353
16264
|
}
|
|
15354
16265
|
getLogFile() {
|
|
15355
|
-
return
|
|
16266
|
+
return resolveAftLogPath("aft-plugin.log");
|
|
15356
16267
|
}
|
|
15357
16268
|
getInstallHint() {
|
|
15358
16269
|
return "Install Pi: https://github.com/badlogic/pi-mono";
|
|
@@ -15366,11 +16277,11 @@ class PiAdapter {
|
|
|
15366
16277
|
describeStorageSubtrees() {
|
|
15367
16278
|
const storage = this.getStorageDir();
|
|
15368
16279
|
return {
|
|
15369
|
-
index: dirSize(
|
|
15370
|
-
semantic: dirSize(
|
|
15371
|
-
backups: dirSize(
|
|
15372
|
-
url_cache: dirSize(
|
|
15373
|
-
onnxruntime: dirSize(
|
|
16280
|
+
index: dirSize(join15(storage, "index")),
|
|
16281
|
+
semantic: dirSize(join15(storage, "semantic")),
|
|
16282
|
+
backups: dirSize(join15(storage, "backups")),
|
|
16283
|
+
url_cache: dirSize(join15(storage, "url_cache")),
|
|
16284
|
+
onnxruntime: dirSize(join15(storage, "onnxruntime"))
|
|
15374
16285
|
};
|
|
15375
16286
|
}
|
|
15376
16287
|
}
|
|
@@ -17394,28 +18305,30 @@ var init_aft_bridge = () => {};
|
|
|
17394
18305
|
// src/commands/lsp.ts
|
|
17395
18306
|
var exports_lsp = {};
|
|
17396
18307
|
__export(exports_lsp, {
|
|
18308
|
+
typescriptPackageWarning: () => typescriptPackageWarning,
|
|
17397
18309
|
runLspDoctor: () => runLspDoctor,
|
|
17398
18310
|
renderLspInspection: () => renderLspInspection,
|
|
17399
18311
|
printLspDoctorHelp: () => printLspDoctorHelp,
|
|
17400
18312
|
findProjectRootForFile: () => findProjectRootForFile
|
|
17401
18313
|
});
|
|
17402
18314
|
import { existsSync as existsSync12, readdirSync as readdirSync4, statSync as statSync7 } from "node:fs";
|
|
17403
|
-
import {
|
|
18315
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
18316
|
+
import { dirname as dirname8, join as join16, resolve as resolve8 } from "node:path";
|
|
17404
18317
|
function findProjectRootForFile(filePath, fallbackCwd = process.cwd()) {
|
|
17405
18318
|
const resolvedFile = resolve8(fallbackCwd, filePath);
|
|
17406
|
-
let dir =
|
|
18319
|
+
let dir = dirname8(resolvedFile);
|
|
17407
18320
|
try {
|
|
17408
18321
|
if (existsSync12(resolvedFile) && statSync7(resolvedFile).isDirectory()) {
|
|
17409
18322
|
dir = resolvedFile;
|
|
17410
18323
|
}
|
|
17411
18324
|
} catch {
|
|
17412
|
-
dir =
|
|
18325
|
+
dir = dirname8(resolvedFile);
|
|
17413
18326
|
}
|
|
17414
18327
|
while (true) {
|
|
17415
|
-
if (PROJECT_ROOT_MARKERS.some((marker) => existsSync12(
|
|
18328
|
+
if (PROJECT_ROOT_MARKERS.some((marker) => existsSync12(join16(dir, marker)))) {
|
|
17416
18329
|
return dir;
|
|
17417
18330
|
}
|
|
17418
|
-
const parent =
|
|
18331
|
+
const parent = dirname8(dir);
|
|
17419
18332
|
if (parent === dir)
|
|
17420
18333
|
return resolve8(fallbackCwd);
|
|
17421
18334
|
dir = parent;
|
|
@@ -17471,7 +18384,12 @@ async function runLspDoctor(options) {
|
|
|
17471
18384
|
log2.error(inspect.message ?? inspect.code ?? "lsp_inspect failed");
|
|
17472
18385
|
return 1;
|
|
17473
18386
|
}
|
|
17474
|
-
|
|
18387
|
+
const inspection = inspect;
|
|
18388
|
+
const typescriptWarning = typescriptPackageWarning(inspection);
|
|
18389
|
+
console.log(renderLspInspection(file, {
|
|
18390
|
+
...inspection,
|
|
18391
|
+
...typescriptWarning ? { typescript_package_warning: typescriptWarning } : {}
|
|
18392
|
+
}));
|
|
17475
18393
|
return 0;
|
|
17476
18394
|
}
|
|
17477
18395
|
function renderLspInspection(inputFile, response) {
|
|
@@ -17507,6 +18425,10 @@ function renderLspInspection(inputFile, response) {
|
|
|
17507
18425
|
lines.push(` Action: ${installHint(server.binary_name)}`);
|
|
17508
18426
|
}
|
|
17509
18427
|
}
|
|
18428
|
+
if (response.typescript_package_warning) {
|
|
18429
|
+
lines.push("");
|
|
18430
|
+
lines.push(`Warning: ${response.typescript_package_warning}`);
|
|
18431
|
+
}
|
|
17510
18432
|
const diagnostics = response.diagnostics ?? [];
|
|
17511
18433
|
lines.push("");
|
|
17512
18434
|
lines.push(`Diagnostics (${response.diagnostics_count ?? diagnostics.length} found):`);
|
|
@@ -17535,8 +18457,8 @@ function parseFileArg(argv) {
|
|
|
17535
18457
|
function buildConfigureParams(adapter, projectRoot) {
|
|
17536
18458
|
const userConfigPath = adapter.detectConfigPaths().aftConfig;
|
|
17537
18459
|
const dir = adapter.kind === "pi" ? ".pi" : ".opencode";
|
|
17538
|
-
const projectJsonc =
|
|
17539
|
-
const projectJson =
|
|
18460
|
+
const projectJsonc = join16(projectRoot, dir, "aft.jsonc");
|
|
18461
|
+
const projectJson = join16(projectRoot, dir, "aft.json");
|
|
17540
18462
|
const projectConfigPath = existsSync12(projectJsonc) ? projectJsonc : projectJson;
|
|
17541
18463
|
return {
|
|
17542
18464
|
id: "doctor-lsp-configure",
|
|
@@ -17550,10 +18472,10 @@ function buildConfigureParams(adapter, projectRoot) {
|
|
|
17550
18472
|
function inferLspPathsExtra(_lsp) {
|
|
17551
18473
|
const paths = new Set;
|
|
17552
18474
|
for (const entry of childDirs(getAftLspPackagesDir())) {
|
|
17553
|
-
paths.add(
|
|
18475
|
+
paths.add(join16(entry, "node_modules", ".bin"));
|
|
17554
18476
|
}
|
|
17555
18477
|
for (const entry of childDirs(getAftLspBinariesDir())) {
|
|
17556
|
-
paths.add(
|
|
18478
|
+
paths.add(join16(entry, "bin"));
|
|
17557
18479
|
}
|
|
17558
18480
|
return [...paths];
|
|
17559
18481
|
}
|
|
@@ -17561,7 +18483,7 @@ function childDirs(path2) {
|
|
|
17561
18483
|
if (!existsSync12(path2))
|
|
17562
18484
|
return [];
|
|
17563
18485
|
try {
|
|
17564
|
-
return readdirSync4(path2).map((entry) =>
|
|
18486
|
+
return readdirSync4(path2).map((entry) => join16(path2, entry)).filter((entry) => {
|
|
17565
18487
|
try {
|
|
17566
18488
|
return statSync7(entry).isDirectory();
|
|
17567
18489
|
} catch {
|
|
@@ -17596,6 +18518,18 @@ function formatSpawnStatus(server) {
|
|
|
17596
18518
|
function formatList(values) {
|
|
17597
18519
|
return values.length === 0 ? "(none)" : values.join(", ");
|
|
17598
18520
|
}
|
|
18521
|
+
function typescriptPackageWarning(response) {
|
|
18522
|
+
const typescriptServerSpawned = response.matching_servers?.some((server) => server.id === "typescript" && server.spawn_status === "ok");
|
|
18523
|
+
const diagnosticsCount = response.diagnostics_count ?? response.diagnostics?.length ?? 0;
|
|
18524
|
+
if (!typescriptServerSpawned || !response.project_root || diagnosticsCount > 0)
|
|
18525
|
+
return null;
|
|
18526
|
+
try {
|
|
18527
|
+
createRequire4(join16(response.project_root, "package.json")).resolve("typescript");
|
|
18528
|
+
return null;
|
|
18529
|
+
} catch {
|
|
18530
|
+
return "typescript package not resolvable from project — server will produce no diagnostics";
|
|
18531
|
+
}
|
|
18532
|
+
}
|
|
17599
18533
|
function installHint(binaryName) {
|
|
17600
18534
|
if (binaryName === "ty")
|
|
17601
18535
|
return "Install with `uv tool install ty` or `pip install ty`.";
|
|
@@ -17639,7 +18573,7 @@ __export(exports_doctor_filters, {
|
|
|
17639
18573
|
printDoctorFiltersHelp: () => printDoctorFiltersHelp
|
|
17640
18574
|
});
|
|
17641
18575
|
import { existsSync as existsSync13 } from "node:fs";
|
|
17642
|
-
import { homedir as
|
|
18576
|
+
import { homedir as homedir16 } from "node:os";
|
|
17643
18577
|
import { relative as relative3, resolve as resolve9 } from "node:path";
|
|
17644
18578
|
function printDoctorFiltersHelp() {
|
|
17645
18579
|
console.log("Usage: aft doctor filters [--show <name>] [trust|untrust]");
|
|
@@ -17857,7 +18791,7 @@ function truncate(value) {
|
|
|
17857
18791
|
return value.length <= 80 ? value : `${value.slice(0, 77)}…`;
|
|
17858
18792
|
}
|
|
17859
18793
|
function formatHome(path2) {
|
|
17860
|
-
const home =
|
|
18794
|
+
const home = homedir16();
|
|
17861
18795
|
return path2.startsWith(home) ? `~${path2.slice(home.length)}` : path2;
|
|
17862
18796
|
}
|
|
17863
18797
|
function formatProjectPath(path2, projectRoot) {
|
|
@@ -17881,7 +18815,7 @@ var init_doctor_filters = __esm(async () => {
|
|
|
17881
18815
|
|
|
17882
18816
|
// src/lib/binary-cache.ts
|
|
17883
18817
|
import { existsSync as existsSync14, readdirSync as readdirSync5, statSync as statSync8 } from "node:fs";
|
|
17884
|
-
import { join as
|
|
18818
|
+
import { join as join17 } from "node:path";
|
|
17885
18819
|
function getBinaryCacheInfo(activeVersion) {
|
|
17886
18820
|
const path2 = getAftBinaryCacheDir();
|
|
17887
18821
|
if (!existsSync14(path2)) {
|
|
@@ -17894,7 +18828,7 @@ function getBinaryCacheInfo(activeVersion) {
|
|
|
17894
18828
|
}
|
|
17895
18829
|
const versions = readdirSync5(path2).filter((entry) => {
|
|
17896
18830
|
try {
|
|
17897
|
-
return statSync8(
|
|
18831
|
+
return statSync8(join17(path2, entry)).isDirectory();
|
|
17898
18832
|
} catch {
|
|
17899
18833
|
return false;
|
|
17900
18834
|
}
|
|
@@ -17915,7 +18849,7 @@ var init_binary_cache = __esm(() => {
|
|
|
17915
18849
|
|
|
17916
18850
|
// src/lib/sanitize.ts
|
|
17917
18851
|
import { realpathSync as realpathSync3 } from "node:fs";
|
|
17918
|
-
import { homedir as
|
|
18852
|
+
import { homedir as homedir17, userInfo } from "node:os";
|
|
17919
18853
|
function escapeRegex(value) {
|
|
17920
18854
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
17921
18855
|
}
|
|
@@ -17946,7 +18880,7 @@ function redactSecrets(content) {
|
|
|
17946
18880
|
}
|
|
17947
18881
|
function sanitizeContent(content) {
|
|
17948
18882
|
const username = userInfo().username;
|
|
17949
|
-
const home =
|
|
18883
|
+
const home = homedir17();
|
|
17950
18884
|
let sanitized = redactSecrets(content);
|
|
17951
18885
|
const cwd = process.cwd();
|
|
17952
18886
|
for (const candidate of new Set([cwd, safeRealpath(cwd)])) {
|
|
@@ -17993,11 +18927,9 @@ var init_sanitize = __esm(() => {
|
|
|
17993
18927
|
|
|
17994
18928
|
// src/lib/bridge-tool-failures.ts
|
|
17995
18929
|
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
18930
|
function resolveBridgePluginLogPath() {
|
|
17999
18931
|
const isTestEnv = process.env.BUN_TEST === "1" || false;
|
|
18000
|
-
return
|
|
18932
|
+
return resolveAftLogPath(isTestEnv ? "aft-plugin-test.log" : "aft-plugin.log");
|
|
18001
18933
|
}
|
|
18002
18934
|
function tailLogFileBytes(path2, maxBytes) {
|
|
18003
18935
|
if (!existsSync15(path2) || maxBytes <= 0)
|
|
@@ -18128,31 +19060,156 @@ function buildRecentAftToolFailuresSectionFromLog(logPath = resolveBridgePluginL
|
|
|
18128
19060
|
}
|
|
18129
19061
|
var BRIDGE_LOG_TAIL_BYTES, MAX_TOOL_FAILURE_CLASSES = 30, SESSION_TAG_PATTERN, STRUCTURED_CODE_PATTERN;
|
|
18130
19062
|
var init_bridge_tool_failures = __esm(() => {
|
|
19063
|
+
init_dist2();
|
|
18131
19064
|
init_sanitize();
|
|
18132
19065
|
BRIDGE_LOG_TAIL_BYTES = 2 * 1024 * 1024;
|
|
18133
19066
|
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
19067
|
STRUCTURED_CODE_PATTERN = /"code"\s*:\s*"([^"]+)"/;
|
|
18135
19068
|
});
|
|
18136
19069
|
|
|
18137
|
-
// src/lib/
|
|
18138
|
-
import { existsSync as existsSync16, readdirSync as readdirSync6,
|
|
19070
|
+
// src/lib/legacy-storage.ts
|
|
19071
|
+
import { existsSync as existsSync16, readdirSync as readdirSync6, statSync as statSync10 } from "node:fs";
|
|
18139
19072
|
import { join as join18 } from "node:path";
|
|
19073
|
+
function summarizeLegacyPartitionDuplication(storageRoot) {
|
|
19074
|
+
if (!existsSync16(storageRoot)) {
|
|
19075
|
+
return { totalPartitions: 0, totalBytes: 0, byHarness: [] };
|
|
19076
|
+
}
|
|
19077
|
+
const byHarness = [];
|
|
19078
|
+
for (const harness of safeReadDir(storageRoot)) {
|
|
19079
|
+
const harnessPath = join18(storageRoot, harness);
|
|
19080
|
+
if (!isDirectory(harnessPath))
|
|
19081
|
+
continue;
|
|
19082
|
+
const partitions = new Map;
|
|
19083
|
+
collectCallgraphPartitions(join18(harnessPath, "callgraph"), partitions);
|
|
19084
|
+
collectInspectPartitions(join18(harnessPath, "inspect"), partitions);
|
|
19085
|
+
if (partitions.size === 0)
|
|
19086
|
+
continue;
|
|
19087
|
+
let bytes = 0;
|
|
19088
|
+
for (const size of partitions.values())
|
|
19089
|
+
bytes += size;
|
|
19090
|
+
byHarness.push({ harness, partitions: partitions.size, bytes });
|
|
19091
|
+
}
|
|
19092
|
+
byHarness.sort((left, right) => left.harness.localeCompare(right.harness));
|
|
19093
|
+
return {
|
|
19094
|
+
totalPartitions: byHarness.reduce((sum, item) => sum + item.partitions, 0),
|
|
19095
|
+
totalBytes: byHarness.reduce((sum, item) => sum + item.bytes, 0),
|
|
19096
|
+
byHarness
|
|
19097
|
+
};
|
|
19098
|
+
}
|
|
19099
|
+
function collectCallgraphPartitions(domainPath, partitions) {
|
|
19100
|
+
if (!isDirectory(domainPath))
|
|
19101
|
+
return;
|
|
19102
|
+
for (const name of safeReadDir(domainPath)) {
|
|
19103
|
+
const path2 = join18(domainPath, name);
|
|
19104
|
+
if (isDirectory(path2)) {
|
|
19105
|
+
if (!looksLikePartitionKey(name))
|
|
19106
|
+
continue;
|
|
19107
|
+
addPartitionBytes(partitions, `callgraph:${name}`, dirSize(path2));
|
|
19108
|
+
continue;
|
|
19109
|
+
}
|
|
19110
|
+
const key = callgraphPartitionKeyFromName(name);
|
|
19111
|
+
if (!key)
|
|
19112
|
+
continue;
|
|
19113
|
+
addPartitionBytes(partitions, `callgraph:${key}`, safeFileSize(path2));
|
|
19114
|
+
}
|
|
19115
|
+
}
|
|
19116
|
+
function collectInspectPartitions(domainPath, partitions) {
|
|
19117
|
+
if (!isDirectory(domainPath))
|
|
19118
|
+
return;
|
|
19119
|
+
for (const name of safeReadDir(domainPath)) {
|
|
19120
|
+
const path2 = join18(domainPath, name);
|
|
19121
|
+
if (isDirectory(path2)) {
|
|
19122
|
+
if (!looksLikePartitionKey(name))
|
|
19123
|
+
continue;
|
|
19124
|
+
addPartitionBytes(partitions, `inspect:${name}`, dirSize(path2));
|
|
19125
|
+
continue;
|
|
19126
|
+
}
|
|
19127
|
+
const key = inspectPartitionKeyFromName(name);
|
|
19128
|
+
if (!key)
|
|
19129
|
+
continue;
|
|
19130
|
+
addPartitionBytes(partitions, `inspect:${key}`, safeFileSize(path2));
|
|
19131
|
+
}
|
|
19132
|
+
}
|
|
19133
|
+
function addPartitionBytes(partitions, key, bytes) {
|
|
19134
|
+
partitions.set(key, (partitions.get(key) ?? 0) + bytes);
|
|
19135
|
+
}
|
|
19136
|
+
function callgraphPartitionKeyFromName(name) {
|
|
19137
|
+
if (name.includes(".tmp."))
|
|
19138
|
+
return null;
|
|
19139
|
+
if (name.endsWith(".current")) {
|
|
19140
|
+
const key2 = name.slice(0, -".current".length);
|
|
19141
|
+
return looksLikePartitionKey(key2) ? key2 : null;
|
|
19142
|
+
}
|
|
19143
|
+
const base = sqliteishBaseName(name);
|
|
19144
|
+
if (!base)
|
|
19145
|
+
return null;
|
|
19146
|
+
const split = base.indexOf(".g");
|
|
19147
|
+
const key = split === -1 ? base : base.slice(0, split);
|
|
19148
|
+
return looksLikePartitionKey(key) ? key : null;
|
|
19149
|
+
}
|
|
19150
|
+
function inspectPartitionKeyFromName(name) {
|
|
19151
|
+
if (name.includes(".tmp."))
|
|
19152
|
+
return null;
|
|
19153
|
+
const base = sqliteishBaseName(name);
|
|
19154
|
+
return base && looksLikePartitionKey(base) ? base : null;
|
|
19155
|
+
}
|
|
19156
|
+
function sqliteishBaseName(name) {
|
|
19157
|
+
for (const suffix of SQLITE_SUFFIXES) {
|
|
19158
|
+
if (name.endsWith(suffix)) {
|
|
19159
|
+
return name.slice(0, -suffix.length);
|
|
19160
|
+
}
|
|
19161
|
+
}
|
|
19162
|
+
return null;
|
|
19163
|
+
}
|
|
19164
|
+
function looksLikePartitionKey(value) {
|
|
19165
|
+
return /^[0-9a-fA-F]{16}$/.test(value);
|
|
19166
|
+
}
|
|
19167
|
+
function safeReadDir(path2) {
|
|
19168
|
+
try {
|
|
19169
|
+
return readdirSync6(path2).sort((left, right) => left.localeCompare(right));
|
|
19170
|
+
} catch {
|
|
19171
|
+
return [];
|
|
19172
|
+
}
|
|
19173
|
+
}
|
|
19174
|
+
function isDirectory(path2) {
|
|
19175
|
+
try {
|
|
19176
|
+
return statSync10(path2).isDirectory();
|
|
19177
|
+
} catch {
|
|
19178
|
+
return false;
|
|
19179
|
+
}
|
|
19180
|
+
}
|
|
19181
|
+
function safeFileSize(path2) {
|
|
19182
|
+
try {
|
|
19183
|
+
return statSync10(path2).isFile() ? statSync10(path2).size : 0;
|
|
19184
|
+
} catch {
|
|
19185
|
+
return 0;
|
|
19186
|
+
}
|
|
19187
|
+
}
|
|
19188
|
+
var SQLITE_SUFFIXES;
|
|
19189
|
+
var init_legacy_storage = __esm(() => {
|
|
19190
|
+
init_fs_util();
|
|
19191
|
+
SQLITE_SUFFIXES = [".sqlite-wal", ".sqlite-shm", ".sqlite-journal", ".sqlite"];
|
|
19192
|
+
});
|
|
19193
|
+
|
|
19194
|
+
// src/lib/lsp-cache.ts
|
|
19195
|
+
import { existsSync as existsSync17, readdirSync as readdirSync7, rmSync as rmSync5, statSync as statSync11 } from "node:fs";
|
|
19196
|
+
import { join as join19 } from "node:path";
|
|
18140
19197
|
function inspectDir(path2) {
|
|
18141
|
-
if (!
|
|
19198
|
+
if (!existsSync17(path2)) {
|
|
18142
19199
|
return { entries: [], totalSize: 0 };
|
|
18143
19200
|
}
|
|
18144
19201
|
const entries = [];
|
|
18145
19202
|
let totalSize = 0;
|
|
18146
19203
|
let names;
|
|
18147
19204
|
try {
|
|
18148
|
-
names =
|
|
19205
|
+
names = readdirSync7(path2);
|
|
18149
19206
|
} catch {
|
|
18150
19207
|
return { entries: [], totalSize: 0 };
|
|
18151
19208
|
}
|
|
18152
19209
|
for (const name of names) {
|
|
18153
|
-
const full =
|
|
19210
|
+
const full = join19(path2, name);
|
|
18154
19211
|
try {
|
|
18155
|
-
if (!
|
|
19212
|
+
if (!statSync11(full).isDirectory())
|
|
18156
19213
|
continue;
|
|
18157
19214
|
const size = dirSize(full);
|
|
18158
19215
|
entries.push({
|
|
@@ -18208,8 +19265,8 @@ var init_lsp_cache = __esm(() => {
|
|
|
18208
19265
|
});
|
|
18209
19266
|
|
|
18210
19267
|
// src/lib/onnx.ts
|
|
18211
|
-
import { existsSync as
|
|
18212
|
-
import { basename as basename3, isAbsolute as isAbsolute6, join as
|
|
19268
|
+
import { existsSync as existsSync18, readdirSync as readdirSync8, readlinkSync as readlinkSync2, realpathSync as realpathSync4 } from "node:fs";
|
|
19269
|
+
import { basename as basename3, isAbsolute as isAbsolute6, join as join20, resolve as resolve10, win32 as win322 } from "node:path";
|
|
18213
19270
|
function getOnnxLibraryName() {
|
|
18214
19271
|
if (process.platform === "darwin")
|
|
18215
19272
|
return "libonnxruntime.dylib";
|
|
@@ -18249,9 +19306,20 @@ function pathEntriesForPlatform2() {
|
|
|
18249
19306
|
return isAbsolute6(entry) || win322.isAbsolute(entry);
|
|
18250
19307
|
});
|
|
18251
19308
|
}
|
|
19309
|
+
function isWindowsSystem32Directory2(dir) {
|
|
19310
|
+
if (process.platform !== "win32")
|
|
19311
|
+
return false;
|
|
19312
|
+
const normalizedDir = win322.resolve(dir).replace(/[\\/]+$/, "").toLowerCase();
|
|
19313
|
+
const windowsRoots = [process.env.SystemRoot, process.env.windir, "C:\\Windows"];
|
|
19314
|
+
return windowsRoots.some((root) => {
|
|
19315
|
+
if (!root)
|
|
19316
|
+
return false;
|
|
19317
|
+
return normalizedDir === win322.resolve(root, "System32").replace(/[\\/]+$/, "").toLowerCase();
|
|
19318
|
+
});
|
|
19319
|
+
}
|
|
18252
19320
|
function directoryContainsLibrary2(dir, libName) {
|
|
18253
19321
|
try {
|
|
18254
|
-
const entries =
|
|
19322
|
+
const entries = readdirSync8(dir);
|
|
18255
19323
|
if (process.platform === "win32") {
|
|
18256
19324
|
const expected = libName.toLowerCase();
|
|
18257
19325
|
return entries.some((entry) => entry.toLowerCase() === expected);
|
|
@@ -18261,6 +19329,24 @@ function directoryContainsLibrary2(dir, libName) {
|
|
|
18261
19329
|
return false;
|
|
18262
19330
|
}
|
|
18263
19331
|
}
|
|
19332
|
+
function findIgnoredWindowsSystemOnnxRuntime() {
|
|
19333
|
+
if (process.platform !== "win32")
|
|
19334
|
+
return null;
|
|
19335
|
+
const windowsRoots = [process.env.SystemRoot, process.env.windir, "C:\\Windows"];
|
|
19336
|
+
const seen = new Set;
|
|
19337
|
+
for (const root of windowsRoots) {
|
|
19338
|
+
if (!root)
|
|
19339
|
+
continue;
|
|
19340
|
+
const systemDir = join20(root, "System32");
|
|
19341
|
+
const key = win322.resolve(systemDir).toLowerCase();
|
|
19342
|
+
if (seen.has(key))
|
|
19343
|
+
continue;
|
|
19344
|
+
seen.add(key);
|
|
19345
|
+
if (directoryContainsLibrary2(systemDir, getOnnxLibraryName()))
|
|
19346
|
+
return systemDir;
|
|
19347
|
+
}
|
|
19348
|
+
return null;
|
|
19349
|
+
}
|
|
18264
19350
|
function findSystemOnnxRuntime2() {
|
|
18265
19351
|
const libName = getOnnxLibraryName();
|
|
18266
19352
|
const searchPaths = [];
|
|
@@ -18272,21 +19358,21 @@ function findSystemOnnxRuntime2() {
|
|
|
18272
19358
|
searchPaths.push(...pathEntriesForPlatform2());
|
|
18273
19359
|
const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
|
|
18274
19360
|
const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
18275
|
-
searchPaths.push(
|
|
19361
|
+
searchPaths.push(join20(programFiles, "onnxruntime", "lib"), join20(programFiles, "Microsoft ONNX Runtime", "lib"), join20(programFiles, "Microsoft Machine Learning", "lib"), join20(programFilesX86, "onnxruntime", "lib"), ...(() => {
|
|
18276
19362
|
const nugetPaths = [];
|
|
18277
19363
|
const userProfile = process.env.USERPROFILE ?? "";
|
|
18278
19364
|
if (!userProfile)
|
|
18279
19365
|
return nugetPaths;
|
|
18280
|
-
const nugetPackageDir =
|
|
18281
|
-
if (!
|
|
19366
|
+
const nugetPackageDir = join20(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
|
|
19367
|
+
if (!existsSync18(nugetPackageDir))
|
|
18282
19368
|
return nugetPaths;
|
|
18283
19369
|
try {
|
|
18284
|
-
for (const entry of
|
|
19370
|
+
for (const entry of readdirSync8(nugetPackageDir, { withFileTypes: true })) {
|
|
18285
19371
|
if (!entry.isDirectory())
|
|
18286
19372
|
continue;
|
|
18287
19373
|
if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
|
|
18288
19374
|
continue;
|
|
18289
|
-
nugetPaths.push(
|
|
19375
|
+
nugetPaths.push(join20(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join20(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
|
|
18290
19376
|
}
|
|
18291
19377
|
} catch {}
|
|
18292
19378
|
return nugetPaths;
|
|
@@ -18306,6 +19392,8 @@ function findSystemOnnxRuntime2() {
|
|
|
18306
19392
|
continue;
|
|
18307
19393
|
const version = detectOrtVersion(dir);
|
|
18308
19394
|
if (!version) {
|
|
19395
|
+
if (isWindowsSystem32Directory2(dir))
|
|
19396
|
+
continue;
|
|
18309
19397
|
unknownVersionPaths.push(dir);
|
|
18310
19398
|
continue;
|
|
18311
19399
|
}
|
|
@@ -18316,12 +19404,12 @@ function findSystemOnnxRuntime2() {
|
|
|
18316
19404
|
return unknownVersionPaths[0] ?? null;
|
|
18317
19405
|
}
|
|
18318
19406
|
function findCachedOnnxRuntime(storageDir) {
|
|
18319
|
-
const ortDir =
|
|
19407
|
+
const ortDir = join20(storageDir, "onnxruntime", ONNX_RUNTIME_VERSION);
|
|
18320
19408
|
const libName = getOnnxLibraryName();
|
|
18321
|
-
if (
|
|
19409
|
+
if (existsSync18(join20(ortDir, libName)))
|
|
18322
19410
|
return ortDir;
|
|
18323
|
-
const libSubdir =
|
|
18324
|
-
if (
|
|
19411
|
+
const libSubdir = join20(ortDir, "lib");
|
|
19412
|
+
if (existsSync18(join20(libSubdir, libName)))
|
|
18325
19413
|
return libSubdir;
|
|
18326
19414
|
return null;
|
|
18327
19415
|
}
|
|
@@ -18342,11 +19430,11 @@ function parseOrtVersionFromDirectoryPath(value) {
|
|
|
18342
19430
|
return null;
|
|
18343
19431
|
}
|
|
18344
19432
|
function detectOrtVersion(libDir) {
|
|
18345
|
-
if (!
|
|
19433
|
+
if (!existsSync18(libDir))
|
|
18346
19434
|
return null;
|
|
18347
19435
|
const libName = getOnnxLibraryName();
|
|
18348
19436
|
try {
|
|
18349
|
-
const entries =
|
|
19437
|
+
const entries = readdirSync8(libDir);
|
|
18350
19438
|
const barePrefix = libName.replace(/\.(so|dylib|dll)$/, "");
|
|
18351
19439
|
const expectedPrefix = process.platform === "win32" ? barePrefix.toLowerCase() : barePrefix;
|
|
18352
19440
|
for (const entry of entries) {
|
|
@@ -18357,8 +19445,8 @@ function detectOrtVersion(libDir) {
|
|
|
18357
19445
|
if (version)
|
|
18358
19446
|
return version;
|
|
18359
19447
|
}
|
|
18360
|
-
const base =
|
|
18361
|
-
if (
|
|
19448
|
+
const base = join20(libDir, libName);
|
|
19449
|
+
if (existsSync18(base)) {
|
|
18362
19450
|
try {
|
|
18363
19451
|
const real = realpathSync4(base);
|
|
18364
19452
|
const version = parseOrtVersionFromPath(real) ?? parseOrtVersionFromDirectoryPath(real);
|
|
@@ -18393,10 +19481,10 @@ import {
|
|
|
18393
19481
|
accessSync,
|
|
18394
19482
|
closeSync as closeSync6,
|
|
18395
19483
|
constants,
|
|
18396
|
-
existsSync as
|
|
19484
|
+
existsSync as existsSync19,
|
|
18397
19485
|
openSync as openSync6,
|
|
18398
19486
|
readSync as readSync3,
|
|
18399
|
-
statSync as
|
|
19487
|
+
statSync as statSync12
|
|
18400
19488
|
} from "node:fs";
|
|
18401
19489
|
async function collectDiagnostics(adapters) {
|
|
18402
19490
|
const cliVersion = getSelfVersion();
|
|
@@ -18431,7 +19519,7 @@ async function diagnoseHarness(adapter) {
|
|
|
18431
19519
|
const logPath = adapter.getLogFile();
|
|
18432
19520
|
const pluginCache = adapter.getPluginCacheInfo();
|
|
18433
19521
|
const storageAccessible = (() => {
|
|
18434
|
-
if (!
|
|
19522
|
+
if (!existsSync19(storage))
|
|
18435
19523
|
return false;
|
|
18436
19524
|
try {
|
|
18437
19525
|
accessSync(storage, constants.R_OK | constants.W_OK);
|
|
@@ -18441,8 +19529,10 @@ async function diagnoseHarness(adapter) {
|
|
|
18441
19529
|
}
|
|
18442
19530
|
})();
|
|
18443
19531
|
const describeStorage = "describeStorageSubtrees" in adapter && typeof adapter.describeStorageSubtrees === "function" ? adapter.describeStorageSubtrees() : {};
|
|
19532
|
+
const legacyDuplication = summarizeLegacyPartitionDuplication(storage);
|
|
18444
19533
|
const semanticEnabled = aftEnabled && (aftConfigRead.value?.semantic_search === true || aftConfigRead.value?.experimental_semantic_search === true);
|
|
18445
19534
|
const systemOrtDir = findSystemOnnxRuntime2();
|
|
19535
|
+
const ignoredSystemOrtDir = systemOrtDir ? null : findIgnoredWindowsSystemOnnxRuntime();
|
|
18446
19536
|
const cachedOrtDir = findCachedOnnxRuntime(storage);
|
|
18447
19537
|
const systemVersion = systemOrtDir ? detectOrtVersion(systemOrtDir) : null;
|
|
18448
19538
|
const cachedVersion = cachedOrtDir ? detectOrtVersion(cachedOrtDir) : null;
|
|
@@ -18454,7 +19544,7 @@ async function diagnoseHarness(adapter) {
|
|
|
18454
19544
|
pluginRegistered: adapter.hasPluginEntry(),
|
|
18455
19545
|
configPaths,
|
|
18456
19546
|
aftConfig: {
|
|
18457
|
-
exists:
|
|
19547
|
+
exists: existsSync19(configPaths.aftConfig),
|
|
18458
19548
|
...aftConfigRead.error ? { parseError: aftConfigRead.error } : {},
|
|
18459
19549
|
enabled: aftEnabled,
|
|
18460
19550
|
...aftEnabledSource ? { enabledSource: aftEnabledSource } : {},
|
|
@@ -18463,15 +19553,18 @@ async function diagnoseHarness(adapter) {
|
|
|
18463
19553
|
pluginCache,
|
|
18464
19554
|
storageDir: {
|
|
18465
19555
|
path: storage,
|
|
18466
|
-
exists:
|
|
19556
|
+
exists: existsSync19(storage),
|
|
18467
19557
|
accessible: storageAccessible,
|
|
18468
|
-
sizesByKey: describeStorage
|
|
19558
|
+
sizesByKey: describeStorage,
|
|
19559
|
+
...legacyDuplication.totalPartitions > 0 ? { legacyDuplication } : {}
|
|
18469
19560
|
},
|
|
18470
19561
|
onnxRuntime: {
|
|
18471
19562
|
required: semanticEnabled,
|
|
18472
19563
|
systemPath: systemOrtDir,
|
|
18473
19564
|
systemVersion,
|
|
18474
19565
|
systemCompatible: systemVersion ? isOrtVersionCompatible(systemVersion) : null,
|
|
19566
|
+
ignoredSystemPath: ignoredSystemOrtDir,
|
|
19567
|
+
ignoredSystemReason: ignoredSystemOrtDir ? "version unreadable (Windows system copy) — ignored" : null,
|
|
18475
19568
|
cachedPath: cachedOrtDir,
|
|
18476
19569
|
cachedVersion,
|
|
18477
19570
|
cachedCompatible: cachedVersion ? isOrtVersionCompatible(cachedVersion) : null,
|
|
@@ -18481,8 +19574,8 @@ async function diagnoseHarness(adapter) {
|
|
|
18481
19574
|
},
|
|
18482
19575
|
logFile: {
|
|
18483
19576
|
path: logPath,
|
|
18484
|
-
exists:
|
|
18485
|
-
sizeKb:
|
|
19577
|
+
exists: existsSync19(logPath),
|
|
19578
|
+
sizeKb: existsSync19(logPath) ? Math.round(statSync12(logPath).size / 1024) : 0
|
|
18486
19579
|
}
|
|
18487
19580
|
};
|
|
18488
19581
|
}
|
|
@@ -18637,7 +19730,7 @@ function collectDiagnosticIssues(report) {
|
|
|
18637
19730
|
code: "onnx_missing",
|
|
18638
19731
|
severity: "medium",
|
|
18639
19732
|
scope: h2.displayName,
|
|
18640
|
-
message: "ONNX Runtime is required for semantic search but was not detected.",
|
|
19733
|
+
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
19734
|
remediation: `Run \`aft doctor --fix\` or install ONNX Runtime manually (${h2.onnxRuntime.installHint}).`
|
|
18642
19735
|
});
|
|
18643
19736
|
}
|
|
@@ -18678,14 +19771,14 @@ function formatDiagnosticIssuesSection(report) {
|
|
|
18678
19771
|
return lines;
|
|
18679
19772
|
}
|
|
18680
19773
|
function tailLogFile(path2, lines) {
|
|
18681
|
-
if (!
|
|
19774
|
+
if (!existsSync19(path2))
|
|
18682
19775
|
return "";
|
|
18683
19776
|
if (lines <= 0)
|
|
18684
19777
|
return "";
|
|
18685
19778
|
const chunkSize = 64 * 1024;
|
|
18686
19779
|
let fd = null;
|
|
18687
19780
|
try {
|
|
18688
|
-
const size =
|
|
19781
|
+
const size = statSync12(path2).size;
|
|
18689
19782
|
fd = openSync6(path2, "r");
|
|
18690
19783
|
const chunks = [];
|
|
18691
19784
|
let position = size;
|
|
@@ -18718,6 +19811,7 @@ var init_diagnostics = __esm(async () => {
|
|
|
18718
19811
|
init_dist2();
|
|
18719
19812
|
init_binary_cache();
|
|
18720
19813
|
init_jsonc();
|
|
19814
|
+
init_legacy_storage();
|
|
18721
19815
|
init_lsp_cache();
|
|
18722
19816
|
init_onnx();
|
|
18723
19817
|
init_sanitize();
|
|
@@ -18865,34 +19959,42 @@ var init_issue_body = __esm(() => {
|
|
|
18865
19959
|
});
|
|
18866
19960
|
|
|
18867
19961
|
// src/lib/onnx-fix.ts
|
|
18868
|
-
import { existsSync as
|
|
18869
|
-
import { join as
|
|
19962
|
+
import { existsSync as existsSync20, rmSync as rmSync6 } from "node:fs";
|
|
19963
|
+
import { join as join21 } from "node:path";
|
|
18870
19964
|
function findOnnxFixCandidates(report) {
|
|
18871
19965
|
const candidates = [];
|
|
18872
19966
|
for (const harness of report.harnesses) {
|
|
18873
19967
|
if (!harness.onnxRuntime.required)
|
|
18874
19968
|
continue;
|
|
18875
|
-
|
|
18876
|
-
continue;
|
|
18877
|
-
const storageOnnxDir = join20(harness.storageDir.path, "onnxruntime");
|
|
19969
|
+
const storageOnnxDir = join21(harness.storageDir.path, "onnxruntime");
|
|
18878
19970
|
const systemTooOld = harness.onnxRuntime.systemPath !== null && harness.onnxRuntime.systemCompatible === false;
|
|
18879
19971
|
const cachedTooOld = harness.onnxRuntime.cachedPath !== null && harness.onnxRuntime.cachedCompatible === false;
|
|
18880
19972
|
const hasCompatibleCached = harness.onnxRuntime.cachedCompatible === true;
|
|
18881
19973
|
if (cachedTooOld) {
|
|
18882
19974
|
candidates.push({
|
|
18883
19975
|
harness,
|
|
18884
|
-
reason: `cached ONNX Runtime at ${harness.onnxRuntime.cachedPath} is v${harness.onnxRuntime.cachedVersion}, but AFT requires ${harness.onnxRuntime.requirement}. Clearing
|
|
19976
|
+
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
19977
|
storageOnnxDir,
|
|
18886
|
-
storageOnnxBytes:
|
|
19978
|
+
storageOnnxBytes: existsSync20(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
|
|
18887
19979
|
});
|
|
18888
19980
|
continue;
|
|
18889
19981
|
}
|
|
18890
19982
|
if (systemTooOld && !hasCompatibleCached) {
|
|
18891
19983
|
candidates.push({
|
|
18892
19984
|
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
|
|
19985
|
+
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.`,
|
|
19986
|
+
storageOnnxDir,
|
|
19987
|
+
storageOnnxBytes: existsSync20(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
|
|
19988
|
+
});
|
|
19989
|
+
continue;
|
|
19990
|
+
}
|
|
19991
|
+
if (!harness.onnxRuntime.systemPath && !harness.onnxRuntime.cachedPath) {
|
|
19992
|
+
const ignoredCopy = harness.onnxRuntime.ignoredSystemPath ? ` The Windows system copy at ${harness.onnxRuntime.ignoredSystemPath} was ignored because its version is unreadable.` : "";
|
|
19993
|
+
candidates.push({
|
|
19994
|
+
harness,
|
|
19995
|
+
reason: `no compatible ONNX Runtime is installed.${ignoredCopy} AFT will download v1.24 into managed storage.`,
|
|
18894
19996
|
storageOnnxDir,
|
|
18895
|
-
storageOnnxBytes:
|
|
19997
|
+
storageOnnxBytes: existsSync20(storageOnnxDir) ? dirSize(storageOnnxDir) : 0
|
|
18896
19998
|
});
|
|
18897
19999
|
}
|
|
18898
20000
|
}
|
|
@@ -18900,58 +20002,74 @@ function findOnnxFixCandidates(report) {
|
|
|
18900
20002
|
}
|
|
18901
20003
|
async function runOnnxFix(adapters, report, options = {}) {
|
|
18902
20004
|
const candidates = findOnnxFixCandidates(report);
|
|
18903
|
-
if (candidates.length === 0)
|
|
20005
|
+
if (candidates.length === 0)
|
|
18904
20006
|
return null;
|
|
18905
|
-
}
|
|
18906
|
-
|
|
18907
|
-
|
|
18908
|
-
|
|
18909
|
-
|
|
18910
|
-
log2.info(` will delete: ${c3.storageOnnxDir} (${formatBytes(c3.storageOnnxBytes)})`);
|
|
20007
|
+
log2.warn(`Found ${candidates.length} ONNX Runtime issue(s) that --fix can repair with an AFT-managed runtime:`);
|
|
20008
|
+
for (const candidate of candidates) {
|
|
20009
|
+
log2.info(` • ${candidate.harness.displayName}: ${candidate.reason}`);
|
|
20010
|
+
if (candidate.storageOnnxBytes > 0) {
|
|
20011
|
+
log2.info(` will delete: ${candidate.storageOnnxDir} (${formatBytes(candidate.storageOnnxBytes)})`);
|
|
18911
20012
|
} else {
|
|
18912
|
-
log2.info(
|
|
20013
|
+
log2.info(" no AFT-managed ONNX cache to delete");
|
|
18913
20014
|
}
|
|
18914
20015
|
}
|
|
18915
|
-
note("This NEVER touches system paths like /usr/lib. It only
|
|
20016
|
+
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
20017
|
const confirmFn = options.confirmFn ?? confirm2;
|
|
18917
20018
|
const proceed = options.yes ? true : await confirmFn("Proceed with the fixes above?", true);
|
|
18918
20019
|
if (!proceed) {
|
|
18919
20020
|
log2.info("Skipped — no changes made.");
|
|
18920
20021
|
return null;
|
|
18921
20022
|
}
|
|
18922
|
-
const result = { cleared: 0, bytesReclaimed: 0, errors: [] };
|
|
20023
|
+
const result = { cleared: 0, installed: 0, bytesReclaimed: 0, errors: [] };
|
|
18923
20024
|
const rmFn = options.rmFn ?? rmSync6;
|
|
18924
|
-
|
|
18925
|
-
|
|
18926
|
-
|
|
18927
|
-
|
|
20025
|
+
const ensureFn = options.ensureFn ?? ensureOnnxRuntime;
|
|
20026
|
+
for (const candidate of candidates) {
|
|
20027
|
+
if (existsSync20(candidate.storageOnnxDir)) {
|
|
20028
|
+
try {
|
|
20029
|
+
rmFn(candidate.storageOnnxDir, { recursive: true, force: true });
|
|
20030
|
+
result.cleared += 1;
|
|
20031
|
+
result.bytesReclaimed += candidate.storageOnnxBytes;
|
|
20032
|
+
log2.success(`${candidate.harness.displayName}: cleared ${candidate.storageOnnxDir} (reclaimed ${formatBytes(candidate.storageOnnxBytes)})`);
|
|
20033
|
+
} catch (err) {
|
|
20034
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
20035
|
+
log2.error(`${candidate.harness.displayName}: failed to clear ${candidate.storageOnnxDir}: ${message}`);
|
|
20036
|
+
result.errors.push({ path: candidate.storageOnnxDir, error: message });
|
|
20037
|
+
continue;
|
|
20038
|
+
}
|
|
18928
20039
|
}
|
|
18929
20040
|
try {
|
|
18930
|
-
|
|
18931
|
-
|
|
18932
|
-
|
|
18933
|
-
|
|
20041
|
+
log2.info(`${candidate.harness.displayName}: downloading managed ONNX Runtime…`);
|
|
20042
|
+
const installedPath = await ensureFn(candidate.harness.storageDir.path);
|
|
20043
|
+
if (!installedPath) {
|
|
20044
|
+
const message = "managed ONNX Runtime download was unavailable";
|
|
20045
|
+
log2.error(`${candidate.harness.displayName}: ${message}`);
|
|
20046
|
+
result.errors.push({ path: candidate.storageOnnxDir, error: message });
|
|
20047
|
+
continue;
|
|
20048
|
+
}
|
|
20049
|
+
result.installed += 1;
|
|
20050
|
+
log2.success(`${candidate.harness.displayName}: ONNX Runtime installed at ${installedPath}`);
|
|
18934
20051
|
} catch (err) {
|
|
18935
|
-
const message = err.message
|
|
18936
|
-
log2.error(`${
|
|
18937
|
-
result.errors.push({ path:
|
|
20052
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
20053
|
+
log2.error(`${candidate.harness.displayName}: ONNX Runtime download failed: ${message}`);
|
|
20054
|
+
result.errors.push({ path: candidate.storageOnnxDir, error: message });
|
|
18938
20055
|
}
|
|
18939
20056
|
}
|
|
18940
|
-
if (result.
|
|
18941
|
-
note("Restart your AFT-using harness (OpenCode / Pi)
|
|
20057
|
+
if (result.installed > 0) {
|
|
20058
|
+
note("Restart your AFT-using harness (OpenCode / Pi) so semantic indexing uses the newly installed managed runtime.", "Next step");
|
|
18942
20059
|
}
|
|
18943
20060
|
return result;
|
|
18944
20061
|
}
|
|
18945
20062
|
var init_onnx_fix = __esm(() => {
|
|
20063
|
+
init_dist2();
|
|
18946
20064
|
init_fs_util();
|
|
18947
20065
|
init_prompts();
|
|
18948
20066
|
});
|
|
18949
20067
|
|
|
18950
20068
|
// src/lib/sessions.ts
|
|
18951
|
-
import { existsSync as
|
|
18952
|
-
import { createRequire as
|
|
18953
|
-
import { homedir as
|
|
18954
|
-
import { basename as basename4, join as
|
|
20069
|
+
import { existsSync as existsSync21, readdirSync as readdirSync9, readFileSync as readFileSync10, statSync as statSync13 } from "node:fs";
|
|
20070
|
+
import { createRequire as createRequire5 } from "node:module";
|
|
20071
|
+
import { homedir as homedir18 } from "node:os";
|
|
20072
|
+
import { basename as basename4, join as join22 } from "node:path";
|
|
18955
20073
|
function listRecentSessions(adapter) {
|
|
18956
20074
|
try {
|
|
18957
20075
|
if (adapter.kind === "opencode")
|
|
@@ -18980,12 +20098,12 @@ function mapOpenCodeSessionRows(rows) {
|
|
|
18980
20098
|
}).filter((session) => session !== null).sort((a3, b2) => b2.lastActivity - a3.lastActivity).slice(0, MAX_RECENT_SESSIONS);
|
|
18981
20099
|
}
|
|
18982
20100
|
function listRecentOpenCodeSessions() {
|
|
18983
|
-
const dbPath =
|
|
18984
|
-
if (!
|
|
20101
|
+
const dbPath = join22(getXdgDataHome(), "opencode", "opencode.db");
|
|
20102
|
+
if (!existsSync21(dbPath))
|
|
18985
20103
|
return [];
|
|
18986
20104
|
let db = null;
|
|
18987
20105
|
try {
|
|
18988
|
-
const require2 =
|
|
20106
|
+
const require2 = createRequire5(import.meta.url);
|
|
18989
20107
|
const sqlite = require2("node:sqlite");
|
|
18990
20108
|
db = new sqlite.DatabaseSync(dbPath, { readOnly: true });
|
|
18991
20109
|
const rows = db.prepare("SELECT id, title, time_updated FROM session ORDER BY time_updated DESC LIMIT 5").all();
|
|
@@ -19000,22 +20118,22 @@ function listRecentOpenCodeSessions() {
|
|
|
19000
20118
|
}
|
|
19001
20119
|
function getXdgDataHome() {
|
|
19002
20120
|
const xdgDataHome = process.env.XDG_DATA_HOME;
|
|
19003
|
-
return xdgDataHome && xdgDataHome.length > 0 ? xdgDataHome :
|
|
20121
|
+
return xdgDataHome && xdgDataHome.length > 0 ? xdgDataHome : join22(homedir18(), ".local", "share");
|
|
19004
20122
|
}
|
|
19005
20123
|
function listRecentPiSessions() {
|
|
19006
|
-
return listPiSessionsFromDir(
|
|
20124
|
+
return listPiSessionsFromDir(join22(getHomeDir(), ".pi", "agent", "sessions"));
|
|
19007
20125
|
}
|
|
19008
20126
|
function getHomeDir() {
|
|
19009
20127
|
const envHome = process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME;
|
|
19010
|
-
return envHome && envHome.length > 0 ? envHome :
|
|
20128
|
+
return envHome && envHome.length > 0 ? envHome : homedir18();
|
|
19011
20129
|
}
|
|
19012
20130
|
function listPiSessionsFromDir(sessionsDir) {
|
|
19013
20131
|
try {
|
|
19014
|
-
if (!
|
|
20132
|
+
if (!existsSync21(sessionsDir))
|
|
19015
20133
|
return [];
|
|
19016
20134
|
const files = collectJsonlFiles(sessionsDir).map((filePath) => {
|
|
19017
20135
|
try {
|
|
19018
|
-
const stats =
|
|
20136
|
+
const stats = statSync13(filePath);
|
|
19019
20137
|
return { filePath, mtimeMs: stats.mtimeMs };
|
|
19020
20138
|
} catch {
|
|
19021
20139
|
return null;
|
|
@@ -19044,12 +20162,12 @@ function collectJsonlFiles(root) {
|
|
|
19044
20162
|
continue;
|
|
19045
20163
|
let entries;
|
|
19046
20164
|
try {
|
|
19047
|
-
entries =
|
|
20165
|
+
entries = readdirSync9(dir, { withFileTypes: true });
|
|
19048
20166
|
} catch {
|
|
19049
20167
|
continue;
|
|
19050
20168
|
}
|
|
19051
20169
|
for (const entry of entries) {
|
|
19052
|
-
const path2 =
|
|
20170
|
+
const path2 = join22(dir, entry.name);
|
|
19053
20171
|
if (entry.isDirectory()) {
|
|
19054
20172
|
stack.push(path2);
|
|
19055
20173
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
@@ -19149,17 +20267,17 @@ __export(exports_doctor, {
|
|
|
19149
20267
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
19150
20268
|
import {
|
|
19151
20269
|
chmodSync as chmodSync4,
|
|
19152
|
-
existsSync as
|
|
20270
|
+
existsSync as existsSync22,
|
|
19153
20271
|
mkdirSync as mkdirSync7,
|
|
19154
20272
|
mkdtempSync,
|
|
19155
20273
|
readFileSync as readFileSync11,
|
|
19156
20274
|
realpathSync as realpathSync5,
|
|
19157
20275
|
rmSync as rmSync7,
|
|
19158
|
-
statSync as
|
|
20276
|
+
statSync as statSync14,
|
|
19159
20277
|
writeFileSync as writeFileSync5
|
|
19160
20278
|
} from "node:fs";
|
|
19161
|
-
import { tmpdir as
|
|
19162
|
-
import { join as
|
|
20279
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
20280
|
+
import { join as join23 } from "node:path";
|
|
19163
20281
|
async function runDoctor(options) {
|
|
19164
20282
|
if (options.issue) {
|
|
19165
20283
|
return runIssueFlow(options.argv);
|
|
@@ -19228,6 +20346,8 @@ async function runDoctor(options) {
|
|
|
19228
20346
|
}
|
|
19229
20347
|
if (h2.onnxRuntime.systemPath) {
|
|
19230
20348
|
parts.push(`system: ${h2.onnxRuntime.systemVersion ?? "unknown"}${h2.onnxRuntime.systemCompatible === false ? " (incompatible)" : ""}`);
|
|
20349
|
+
} else if (h2.onnxRuntime.ignoredSystemPath) {
|
|
20350
|
+
parts.push(`system: ${h2.onnxRuntime.ignoredSystemReason} at ${h2.onnxRuntime.ignoredSystemPath}`);
|
|
19231
20351
|
}
|
|
19232
20352
|
if (!h2.onnxRuntime.cachedPath && !h2.onnxRuntime.systemPath) {
|
|
19233
20353
|
parts.push(`not installed — ${h2.onnxRuntime.installHint}`);
|
|
@@ -19324,7 +20444,7 @@ function clearOldBinaries() {
|
|
|
19324
20444
|
errors: [],
|
|
19325
20445
|
keptVersion: keepTag
|
|
19326
20446
|
};
|
|
19327
|
-
if (!
|
|
20447
|
+
if (!existsSync22(info.path)) {
|
|
19328
20448
|
log2.info(`Binary cache: nothing to clear at ${info.path}`);
|
|
19329
20449
|
return result;
|
|
19330
20450
|
}
|
|
@@ -19334,10 +20454,10 @@ function clearOldBinaries() {
|
|
|
19334
20454
|
return result;
|
|
19335
20455
|
}
|
|
19336
20456
|
for (const version of stale) {
|
|
19337
|
-
const dir =
|
|
20457
|
+
const dir = join23(info.path, version);
|
|
19338
20458
|
let bytes = 0;
|
|
19339
20459
|
try {
|
|
19340
|
-
bytes =
|
|
20460
|
+
bytes = statSync14(dir).isDirectory() ? dirSize(dir) : 0;
|
|
19341
20461
|
} catch {
|
|
19342
20462
|
bytes = 0;
|
|
19343
20463
|
}
|
|
@@ -19511,12 +20631,12 @@ function buildDoctorFixPlan(adapters, report) {
|
|
|
19511
20631
|
if (candidate.storageOnnxBytes > 0) {
|
|
19512
20632
|
items.push({
|
|
19513
20633
|
kind: "onnx",
|
|
19514
|
-
message: `Will
|
|
20634
|
+
message: `Will replace AFT-managed ONNX cache at ${candidate.storageOnnxDir} (${formatBytes(candidate.storageOnnxBytes)}) and download a compatible runtime`
|
|
19515
20635
|
});
|
|
19516
20636
|
} else {
|
|
19517
20637
|
items.push({
|
|
19518
20638
|
kind: "onnx",
|
|
19519
|
-
message: `Will leave system ONNX untouched and
|
|
20639
|
+
message: `Will leave system ONNX untouched and download a compatible AFT-managed runtime for ${candidate.harness.displayName}`
|
|
19520
20640
|
});
|
|
19521
20641
|
}
|
|
19522
20642
|
}
|
|
@@ -19648,7 +20768,8 @@ function logDoctorIssues(report) {
|
|
|
19648
20768
|
}
|
|
19649
20769
|
function formatDoctorStorageStatus(h2) {
|
|
19650
20770
|
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
|
-
|
|
20771
|
+
const legacyDuplication = formatLegacyDuplication(h2.storageDir.legacyDuplication);
|
|
20772
|
+
return `${state} (${[formatStorageSizes(h2.storageDir.sizesByKey), legacyDuplication].filter((part) => Boolean(part)).join("; ")})`;
|
|
19652
20773
|
}
|
|
19653
20774
|
async function confirmBinaryDownloadDespitePluginSkew(report, argv) {
|
|
19654
20775
|
const skews = findPluginCliVersionSkews(report);
|
|
@@ -19678,7 +20799,7 @@ function ensureStorageDirsForRegisteredPlugins(adapters) {
|
|
|
19678
20799
|
if (!adapter.isInstalled() || !adapter.hasPluginEntry())
|
|
19679
20800
|
continue;
|
|
19680
20801
|
const storageDir = adapter.getStorageDir();
|
|
19681
|
-
if (
|
|
20802
|
+
if (existsSync22(storageDir))
|
|
19682
20803
|
continue;
|
|
19683
20804
|
mkdirSync7(storageDir, { recursive: true });
|
|
19684
20805
|
summary.created += 1;
|
|
@@ -19760,6 +20881,12 @@ function formatStorageSizes(sizes) {
|
|
|
19760
20881
|
const parts = Object.entries(sizes).filter(([, size]) => size > 0).map(([key, size]) => `${key}: ${formatBytes(size)}`);
|
|
19761
20882
|
return parts.length > 0 ? parts.join(", ") : "empty";
|
|
19762
20883
|
}
|
|
20884
|
+
function formatLegacyDuplication(summary) {
|
|
20885
|
+
if (!summary || summary.totalPartitions === 0)
|
|
20886
|
+
return null;
|
|
20887
|
+
const byHarness = summary.byHarness.map((entry) => `${entry.harness}: ${entry.partitions} partition(s) / ${formatBytes(entry.bytes)}`).join("; ");
|
|
20888
|
+
return `legacy duplication: ${summary.totalPartitions} partition(s), ${formatBytes(summary.totalBytes)} total [${byHarness}]`;
|
|
20889
|
+
}
|
|
19763
20890
|
function isInteractiveTerminal() {
|
|
19764
20891
|
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
19765
20892
|
}
|
|
@@ -19791,11 +20918,11 @@ function deriveIssueTitleFromBody(body) {
|
|
|
19791
20918
|
function writeIssueReviewFile(body) {
|
|
19792
20919
|
let reviewDir = null;
|
|
19793
20920
|
try {
|
|
19794
|
-
reviewDir = mkdtempSync(
|
|
20921
|
+
reviewDir = mkdtempSync(join23(tmpdir2(), "aft-issue-"));
|
|
19795
20922
|
if (process.platform !== "win32") {
|
|
19796
20923
|
chmodSync4(reviewDir, 448);
|
|
19797
20924
|
}
|
|
19798
|
-
const outPath =
|
|
20925
|
+
const outPath = join23(reviewDir, "issue.md");
|
|
19799
20926
|
writeFileSync5(outPath, `${body}
|
|
19800
20927
|
`, { encoding: "utf8", mode: 384, flag: "wx" });
|
|
19801
20928
|
return { path: outPath, realPath: realpathSync5(outPath) };
|