@camstack/system 1.0.7 → 1.0.8
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/addon-runner.js +3 -3
- package/dist/addon-runner.mjs +3 -3
- package/dist/builtins/device-manager/device-manager.addon.js +8 -8
- package/dist/builtins/device-manager/device-manager.addon.mjs +8 -8
- package/dist/builtins/platform-probe/index.js +27 -139
- package/dist/builtins/platform-probe/index.mjs +28 -140
- package/dist/builtins/platform-probe/platform-scorer.d.ts +17 -10
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +2 -2
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +2 -2
- package/dist/index.js +82 -74
- package/dist/index.mjs +83 -75
- package/dist/kernel/config-manager.d.ts +4 -4
- package/dist/kernel/fs-utils.d.ts +16 -6
- package/dist/kernel/index.d.ts +1 -1
- package/dist/kernel/transport/child-cap-protocol.d.ts +10 -0
- package/dist/{manifest-python-deps-eBDj5HEY.js → manifest-python-deps-BWURo7dc.js} +34 -17
- package/dist/{manifest-python-deps-CoJXeb9u.mjs → manifest-python-deps-BcrTzHH_.mjs} +54 -37
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -19,7 +19,7 @@ import { LocalAuthAddon, a as require_safe_buffer, i as AuthManager, n as ApiKey
|
|
|
19
19
|
import "./builtins/local-auth/index.mjs";
|
|
20
20
|
import { DeviceManagerAddon } from "./builtins/device-manager/device-manager.addon.mjs";
|
|
21
21
|
import "./builtins/device-manager/index.mjs";
|
|
22
|
-
import { A as createUdsLoggerWithControl, B as createLocalTransport, C as ipcParentLink, D as createUdsEventBus, E as createUdsEventBridge, F as CapRouteError, G as FrameDecoder, H as UdsLocalTransportServer, I as classifyCapRoute, J as buildUdsNativeCapProxy, K as encodeFrame, L as LocalChildClient, M as AGENT_CAP_FWD_SERVICE, N as CapRouteResolver, O as udsChildLogToWorkerEntry, P as callWithServiceDiscovery, Q as mountNativeCapService, R as LocalChildRegistry, S as ipcChildLink, T as createParentUnownedCallHandler, U as SocketChannel, V as UdsLocalTransportClient, W as localEndpointPath, Y as createBrokerDeviceManagerApi, _ as __resetCapUsageRegistryForTests, a as getWorkerDeviceRegistry, at as capBareAction, b as brokerTransportLink, c as setHubConnected, ct as deserializeTypedArrays, d as registerEventBusService, dt as CapabilityHandle, et as createAddonService, f as AddonDepsManager, ft as CapabilityUnavailableError, g as CapUsageRegistry, h as createHwAccelService, i as createUdsAddonContext, it as capActionSuffix, j as AGENT_CAP_FWD_ACTION, k as createUdsLogger, l as EVENT_TOPIC_PREFIX, lt as serializeTypedArrays, m as resolveHwAccel, mt as resolveAddonClass, n as adaptBrokerToCluster, nt as NATIVE_PROVIDER_SERVICE_INFIX, o as getOrInitReadinessRegistry, ot as capServiceName, p as createKernelHwAccel, pt as installManifestNativeDeps, q as buildNativeCapProxy, r as createAddonContext, rt as capActionName, s as getOrInitReadinessRegistryForClient, st as parseCapAction, t as installManifestPythonDeps, tt as validateProviderRegistrations, u as getBrokerEventBus, ut as DeviceRegistry, v as getCapUsageRegistry, w as localProviderLink, x as buildLinkChain, y as brokerCallForCap, z as UDS_NO_ROUTE_PREFIX } from "./manifest-python-deps-
|
|
22
|
+
import { A as createUdsLoggerWithControl, B as createLocalTransport, C as ipcParentLink, D as createUdsEventBus, E as createUdsEventBridge, F as CapRouteError, G as FrameDecoder, H as UdsLocalTransportServer, I as classifyCapRoute, J as buildUdsNativeCapProxy, K as encodeFrame, L as LocalChildClient, M as AGENT_CAP_FWD_SERVICE, N as CapRouteResolver, O as udsChildLogToWorkerEntry, P as callWithServiceDiscovery, Q as mountNativeCapService, R as LocalChildRegistry, S as ipcChildLink, T as createParentUnownedCallHandler, U as SocketChannel, V as UdsLocalTransportClient, W as localEndpointPath, Y as createBrokerDeviceManagerApi, _ as __resetCapUsageRegistryForTests, a as getWorkerDeviceRegistry, at as capBareAction, b as brokerTransportLink, c as setHubConnected, ct as deserializeTypedArrays, d as registerEventBusService, dt as CapabilityHandle, et as createAddonService, f as AddonDepsManager, ft as CapabilityUnavailableError, g as CapUsageRegistry, h as createHwAccelService, i as createUdsAddonContext, it as capActionSuffix, j as AGENT_CAP_FWD_ACTION, k as createUdsLogger, l as EVENT_TOPIC_PREFIX, lt as serializeTypedArrays, m as resolveHwAccel, mt as resolveAddonClass, n as adaptBrokerToCluster, nt as NATIVE_PROVIDER_SERVICE_INFIX, o as getOrInitReadinessRegistry, ot as capServiceName, p as createKernelHwAccel, pt as installManifestNativeDeps, q as buildNativeCapProxy, r as createAddonContext, rt as capActionName, s as getOrInitReadinessRegistryForClient, st as parseCapAction, t as installManifestPythonDeps, tt as validateProviderRegistrations, u as getBrokerEventBus, ut as DeviceRegistry, v as getCapUsageRegistry, w as localProviderLink, x as buildLinkChain, y as brokerCallForCap, z as UDS_NO_ROUTE_PREFIX } from "./manifest-python-deps-BcrTzHH_.mjs";
|
|
23
23
|
import { t as CustomActionRegistry } from "./custom-action-registry-BEXwC-oo.mjs";
|
|
24
24
|
import { n as require_src, t as require_graceful_fs } from "./graceful-fs-BoR9GuPS.mjs";
|
|
25
25
|
import { PYTHON_VERSION, buildBinaryPath, downloadBinary, ensureBinary, ensureFfmpeg, ensurePython, findInPath, getFfmpegDownloadUrl, getPlatformInfo, getPythonDownloadUrl, installPythonPackages, installPythonRequirements } from "@camstack/types/node";
|
|
@@ -30,7 +30,7 @@ import * as path$40 from "node:path";
|
|
|
30
30
|
import { dirname, isAbsolute, join, posix, resolve, win32 } from "node:path";
|
|
31
31
|
import { DATAPLANE_SECRET_HEADER, EventCategory, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, asJsonObject, asNumber, asString, createEvent, emitDownForOwnedCaps, errMsg, lifecycleJobSchema, parseJsonObject, parseJsonUnknown, readinessKey, scopeKey } from "@camstack/types";
|
|
32
32
|
import { X509Certificate, createHash, randomUUID, timingSafeEqual } from "node:crypto";
|
|
33
|
-
import { execFile,
|
|
33
|
+
import { execFile, spawn } from "node:child_process";
|
|
34
34
|
import * as util$8 from "node:util";
|
|
35
35
|
import { promisify } from "node:util";
|
|
36
36
|
import * as vm from "node:vm";
|
|
@@ -177,7 +177,7 @@ function proxyToUpstream(opts) {
|
|
|
177
177
|
}
|
|
178
178
|
//#endregion
|
|
179
179
|
//#region src/python/python-env-manager.ts
|
|
180
|
-
var execFileAsync$
|
|
180
|
+
var execFileAsync$3 = promisify(execFile);
|
|
181
181
|
var PythonEnvManager = class {
|
|
182
182
|
venvPath;
|
|
183
183
|
cachedProbe = null;
|
|
@@ -187,12 +187,12 @@ var PythonEnvManager = class {
|
|
|
187
187
|
async probe() {
|
|
188
188
|
if (this.cachedProbe) return this.cachedProbe;
|
|
189
189
|
for (const cmd of ["python3", "python"]) try {
|
|
190
|
-
const { stdout } = await execFileAsync$
|
|
190
|
+
const { stdout } = await execFileAsync$3(cmd, ["--version"]);
|
|
191
191
|
const version = stdout.trim().replace("Python ", "");
|
|
192
192
|
const major = parseInt(version.split(".")[0] ?? "0", 10);
|
|
193
193
|
const minor = parseInt(version.split(".")[1] ?? "0", 10);
|
|
194
194
|
if (major < 3 || major === 3 && minor < 10) continue;
|
|
195
|
-
const { stdout: pathOut } = await execFileAsync$
|
|
195
|
+
const { stdout: pathOut } = await execFileAsync$3(cmd, ["-c", "import sys; print(sys.executable)"]);
|
|
196
196
|
this.cachedProbe = {
|
|
197
197
|
available: true,
|
|
198
198
|
version,
|
|
@@ -208,13 +208,13 @@ var PythonEnvManager = class {
|
|
|
208
208
|
async ensure(options) {
|
|
209
209
|
const probe = await this.probe();
|
|
210
210
|
if (!probe.available || !probe.path) throw new Error("Python 3.10+ is required but not found on this system");
|
|
211
|
-
if (!fs$17.existsSync(path$40.join(this.venvPath, "bin", "python"))) await execFileAsync$
|
|
211
|
+
if (!fs$17.existsSync(path$40.join(this.venvPath, "bin", "python"))) await execFileAsync$3(probe.path, [
|
|
212
212
|
"-m",
|
|
213
213
|
"venv",
|
|
214
214
|
this.venvPath
|
|
215
215
|
]);
|
|
216
216
|
const venvPython = path$40.join(this.venvPath, "bin", "python");
|
|
217
|
-
if (options.packages.length > 0) await execFileAsync$
|
|
217
|
+
if (options.packages.length > 0) await execFileAsync$3(venvPython, [
|
|
218
218
|
"-m",
|
|
219
219
|
"pip",
|
|
220
220
|
"install",
|
|
@@ -1413,12 +1413,11 @@ var StorageManager = class {
|
|
|
1413
1413
|
return namespace ? this.createNamespacedLocation(location, namespace) : location;
|
|
1414
1414
|
}
|
|
1415
1415
|
createLegacyShim() {
|
|
1416
|
-
const self = this;
|
|
1417
1416
|
return {
|
|
1418
1417
|
async initialize() {},
|
|
1419
1418
|
async shutdown() {},
|
|
1420
|
-
getLocation(name) {
|
|
1421
|
-
return
|
|
1419
|
+
getLocation: (name) => {
|
|
1420
|
+
return this.getLocation(name);
|
|
1422
1421
|
}
|
|
1423
1422
|
};
|
|
1424
1423
|
}
|
|
@@ -1694,7 +1693,7 @@ function matchPath(pattern, path) {
|
|
|
1694
1693
|
}
|
|
1695
1694
|
//#endregion
|
|
1696
1695
|
//#region src/tls/cert-manager.ts
|
|
1697
|
-
var execFileAsync$
|
|
1696
|
+
var execFileAsync$2 = promisify(execFile);
|
|
1698
1697
|
/**
|
|
1699
1698
|
* Ensure a self-signed TLS certificate exists in the given directory.
|
|
1700
1699
|
* Generates one if missing. Returns paths to cert and key files.
|
|
@@ -1731,7 +1730,7 @@ async function ensureTlsCert(dataDir, options) {
|
|
|
1731
1730
|
for (const dns of sanDns) sanParts.push(`DNS:${dns}`);
|
|
1732
1731
|
for (const ip of sanIps) sanParts.push(`IP:${ip}`);
|
|
1733
1732
|
const sanString = sanParts.join(",");
|
|
1734
|
-
await execFileAsync$
|
|
1733
|
+
await execFileAsync$2("openssl", [
|
|
1735
1734
|
"req",
|
|
1736
1735
|
"-x509",
|
|
1737
1736
|
"-newkey",
|
|
@@ -2564,6 +2563,7 @@ var AddonEngineManager = class {
|
|
|
2564
2563
|
};
|
|
2565
2564
|
//#endregion
|
|
2566
2565
|
//#region src/kernel/fs-utils.ts
|
|
2566
|
+
var execFileAsync$1 = promisify(execFile);
|
|
2567
2567
|
/**
|
|
2568
2568
|
* Ensure a directory exists (recursive).
|
|
2569
2569
|
* Single source of truth — replaces scattered mkdirSync calls.
|
|
@@ -2572,18 +2572,20 @@ function ensureDir(dirPath) {
|
|
|
2572
2572
|
fs$17.mkdirSync(dirPath, { recursive: true });
|
|
2573
2573
|
}
|
|
2574
2574
|
/**
|
|
2575
|
-
* Copy a directory recursively.
|
|
2576
|
-
*
|
|
2575
|
+
* Copy a directory recursively — ASYNC so it never blocks the event loop.
|
|
2576
|
+
*
|
|
2577
|
+
* The hub installs addons into `/data/addons`, which on Unraid is a slow
|
|
2578
|
+
* shfs/FUSE mount. The former synchronous `fs.copyFileSync`-per-file loop
|
|
2579
|
+
* blocked the Node event loop for the whole copy of a large bundle (e.g.
|
|
2580
|
+
* `addon-pipeline`), which froze the hub's HTTP listener mid-`camstack deploy`
|
|
2581
|
+
* (accept backlog piling up, existing connections stuck in CLOSE_WAIT). Using
|
|
2582
|
+
* `fs.promises.cp` keeps the I/O off the event loop. (Node ≥18 stable.)
|
|
2577
2583
|
*/
|
|
2578
|
-
function copyDirRecursive(src, dest) {
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
const destPath = path$40.join(dest, entry.name);
|
|
2584
|
-
if (entry.isDirectory()) copyDirRecursive(srcPath, destPath);
|
|
2585
|
-
else fs$17.copyFileSync(srcPath, destPath);
|
|
2586
|
-
}
|
|
2584
|
+
async function copyDirRecursive(src, dest) {
|
|
2585
|
+
await fs$17.promises.cp(src, dest, {
|
|
2586
|
+
recursive: true,
|
|
2587
|
+
force: true
|
|
2588
|
+
});
|
|
2587
2589
|
}
|
|
2588
2590
|
/**
|
|
2589
2591
|
* Strip @camstack/* dependencies and devDependencies from a package.json object.
|
|
@@ -2613,7 +2615,7 @@ function stripCamstackDeps(pkg) {
|
|
|
2613
2615
|
* Copies directories (not individual files) from source to destination.
|
|
2614
2616
|
* Skips "dist" (already handled) and glob patterns.
|
|
2615
2617
|
*/
|
|
2616
|
-
function copyExtraFileDirs(pkgJson, sourceDir, destDir) {
|
|
2618
|
+
async function copyExtraFileDirs(pkgJson, sourceDir, destDir) {
|
|
2617
2619
|
const rawFiles = pkgJson.files;
|
|
2618
2620
|
if (!Array.isArray(rawFiles)) return;
|
|
2619
2621
|
for (const fileEntry of rawFiles) {
|
|
@@ -2622,11 +2624,11 @@ function copyExtraFileDirs(pkgJson, sourceDir, destDir) {
|
|
|
2622
2624
|
const srcPath = path$40.join(sourceDir, fileEntry);
|
|
2623
2625
|
if (!fs$17.existsSync(srcPath)) continue;
|
|
2624
2626
|
const destPath = path$40.join(destDir, fileEntry);
|
|
2625
|
-
const stat = fs$17.
|
|
2626
|
-
if (stat.isDirectory()) copyDirRecursive(srcPath, destPath);
|
|
2627
|
+
const stat = await fs$17.promises.stat(srcPath);
|
|
2628
|
+
if (stat.isDirectory()) await copyDirRecursive(srcPath, destPath);
|
|
2627
2629
|
else if (stat.isFile()) {
|
|
2628
2630
|
ensureDir(path$40.dirname(destPath));
|
|
2629
|
-
fs$17.
|
|
2631
|
+
await fs$17.promises.copyFile(srcPath, destPath);
|
|
2630
2632
|
}
|
|
2631
2633
|
}
|
|
2632
2634
|
}
|
|
@@ -2671,12 +2673,16 @@ function ensureLibraryBuilt(packageName, packagesDir) {
|
|
|
2671
2673
|
/**
|
|
2672
2674
|
* Install a single npm package into a target directory (package.json + dist/).
|
|
2673
2675
|
* No validation on camstack.addons -- works for any @camstack/* package.
|
|
2674
|
-
*
|
|
2676
|
+
*
|
|
2677
|
+
* ASYNC: uses `execFile`/`fs.promises` throughout so a package install on a
|
|
2678
|
+
* live node never blocks the event loop (the `npm pack` + tar extract + copy to
|
|
2679
|
+
* the slow shfs/FUSE `/data` would otherwise freeze the HTTP listener). See
|
|
2680
|
+
* `copyDirRecursive` for the wedge this prevents.
|
|
2675
2681
|
*/
|
|
2676
|
-
function
|
|
2677
|
-
const tmpDir = fs$17.
|
|
2682
|
+
async function installPackageFromNpm(packageName, targetDir) {
|
|
2683
|
+
const tmpDir = await fs$17.promises.mkdtemp(path$40.join(os$17.tmpdir(), "camstack-install-"));
|
|
2678
2684
|
try {
|
|
2679
|
-
const
|
|
2685
|
+
const { stdout } = await execFileAsync$1("npm", [
|
|
2680
2686
|
"pack",
|
|
2681
2687
|
packageName,
|
|
2682
2688
|
"--pack-destination",
|
|
@@ -2684,12 +2690,13 @@ function installPackageFromNpmSync(packageName, targetDir) {
|
|
|
2684
2690
|
], {
|
|
2685
2691
|
timeout: 12e4,
|
|
2686
2692
|
encoding: "utf-8"
|
|
2687
|
-
})
|
|
2693
|
+
});
|
|
2694
|
+
const tgzFilename = stdout.trim().split("\n").pop()?.trim();
|
|
2688
2695
|
if (!tgzFilename) throw new Error("npm pack produced no output");
|
|
2689
2696
|
const tgzPath = path$40.join(tmpDir, tgzFilename);
|
|
2690
2697
|
const extractDir = path$40.join(tmpDir, "extracted");
|
|
2691
2698
|
ensureDir(extractDir);
|
|
2692
|
-
|
|
2699
|
+
await execFileAsync$1("tar", [
|
|
2693
2700
|
"-xzf",
|
|
2694
2701
|
tgzPath,
|
|
2695
2702
|
"-C",
|
|
@@ -2697,20 +2704,20 @@ function installPackageFromNpmSync(packageName, targetDir) {
|
|
|
2697
2704
|
], { timeout: 3e4 });
|
|
2698
2705
|
const packageSubDir = path$40.join(extractDir, "package");
|
|
2699
2706
|
const srcPkgJsonDir = fs$17.existsSync(path$40.join(packageSubDir, "package.json")) ? packageSubDir : extractDir;
|
|
2700
|
-
fs$17.
|
|
2707
|
+
await fs$17.promises.rm(targetDir, {
|
|
2701
2708
|
recursive: true,
|
|
2702
2709
|
force: true
|
|
2703
2710
|
});
|
|
2704
2711
|
ensureDir(targetDir);
|
|
2705
|
-
fs$17.
|
|
2712
|
+
await fs$17.promises.copyFile(path$40.join(srcPkgJsonDir, "package.json"), path$40.join(targetDir, "package.json"));
|
|
2706
2713
|
const distSrc = path$40.join(srcPkgJsonDir, "dist");
|
|
2707
|
-
if (fs$17.existsSync(distSrc)) copyDirRecursive(distSrc, path$40.join(targetDir, "dist"));
|
|
2714
|
+
if (fs$17.existsSync(distSrc)) await copyDirRecursive(distSrc, path$40.join(targetDir, "dist"));
|
|
2708
2715
|
try {
|
|
2709
|
-
const npmPkg = asJsonObject(parseJsonUnknown(fs$17.
|
|
2710
|
-
if (npmPkg) copyExtraFileDirs(npmPkg, srcPkgJsonDir, targetDir);
|
|
2716
|
+
const npmPkg = asJsonObject(parseJsonUnknown(await fs$17.promises.readFile(path$40.join(srcPkgJsonDir, "package.json"), "utf-8")));
|
|
2717
|
+
if (npmPkg) await copyExtraFileDirs(npmPkg, srcPkgJsonDir, targetDir);
|
|
2711
2718
|
} catch {}
|
|
2712
2719
|
} finally {
|
|
2713
|
-
fs$17.
|
|
2720
|
+
await fs$17.promises.rm(tmpDir, {
|
|
2714
2721
|
recursive: true,
|
|
2715
2722
|
force: true
|
|
2716
2723
|
});
|
|
@@ -3160,15 +3167,15 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3160
3167
|
await this.ensureBuilt(packageName, sourceDir, pkgData);
|
|
3161
3168
|
const distDir = path$40.join(sourceDir, "dist");
|
|
3162
3169
|
if (!fs$17.existsSync(distDir)) throw new Error(`${packageName} has no dist/ after build`);
|
|
3163
|
-
fs$17.
|
|
3170
|
+
await fs$17.promises.rm(targetDir, {
|
|
3164
3171
|
recursive: true,
|
|
3165
3172
|
force: true
|
|
3166
3173
|
});
|
|
3167
3174
|
ensureDir(targetDir);
|
|
3168
|
-
fs$17.
|
|
3169
|
-
copyDirRecursive(distDir, path$40.join(targetDir, "dist"));
|
|
3170
|
-
copyExtraFileDirs(pkgData, sourceDir, targetDir);
|
|
3171
|
-
fs$17.
|
|
3175
|
+
await fs$17.promises.writeFile(path$40.join(targetDir, "package.json"), JSON.stringify(stripCamstackDeps(pkgData), null, 2));
|
|
3176
|
+
await copyDirRecursive(distDir, path$40.join(targetDir, "dist"));
|
|
3177
|
+
await copyExtraFileDirs(pkgData, sourceDir, targetDir);
|
|
3178
|
+
await fs$17.promises.writeFile(path$40.join(targetDir, ".install-source"), "local");
|
|
3172
3179
|
const localPkgVersion = asString(pkgData.version, "0.0.0");
|
|
3173
3180
|
this.manifest.upsert(packageName, {
|
|
3174
3181
|
version: localPkgVersion,
|
|
@@ -3288,17 +3295,17 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3288
3295
|
if (!pkgView) throw new Error(`Invalid package.json at ${pkgJsonPath}`);
|
|
3289
3296
|
if (!pkgView.camstackAddons) throw new Error(`Package ${pkgView.name} has no camstack.addons manifest`);
|
|
3290
3297
|
const targetDir = path$40.join(this.addonsDir, pkgView.name);
|
|
3291
|
-
fs$17.
|
|
3298
|
+
await fs$17.promises.rm(targetDir, {
|
|
3292
3299
|
recursive: true,
|
|
3293
3300
|
force: true
|
|
3294
3301
|
});
|
|
3295
3302
|
ensureDir(targetDir);
|
|
3296
3303
|
const sourceDir = path$40.dirname(pkgJsonPath);
|
|
3297
3304
|
const strippedManifest = stripCamstackDeps(pkgView.raw);
|
|
3298
|
-
fs$17.
|
|
3305
|
+
await fs$17.promises.writeFile(path$40.join(targetDir, "package.json"), JSON.stringify(strippedManifest, null, 2));
|
|
3299
3306
|
const sourceDist = path$40.join(sourceDir, "dist");
|
|
3300
|
-
if (fs$17.existsSync(sourceDist)) copyDirRecursive(sourceDist, path$40.join(targetDir, "dist"));
|
|
3301
|
-
copyExtraFileDirs(pkgView.raw, sourceDir, targetDir);
|
|
3307
|
+
if (fs$17.existsSync(sourceDist)) await copyDirRecursive(sourceDist, path$40.join(targetDir, "dist"));
|
|
3308
|
+
await copyExtraFileDirs(pkgView.raw, sourceDir, targetDir);
|
|
3302
3309
|
const strippedRuntimeDeps = strippedManifest["dependencies"];
|
|
3303
3310
|
if (strippedRuntimeDeps != null && typeof strippedRuntimeDeps === "object" && Object.keys(strippedRuntimeDeps).length > 0) {
|
|
3304
3311
|
this.logger.info(`${pkgView.name} — installing runtime dependencies`, { meta: { targetDir } });
|
|
@@ -3322,7 +3329,7 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3322
3329
|
try {
|
|
3323
3330
|
await installManifestNativeDeps(targetDir, pkgView.raw, this.logger, this.registry);
|
|
3324
3331
|
} catch (nativeErr) {
|
|
3325
|
-
fs$17.
|
|
3332
|
+
await fs$17.promises.rm(targetDir, {
|
|
3326
3333
|
recursive: true,
|
|
3327
3334
|
force: true
|
|
3328
3335
|
});
|
|
@@ -3337,7 +3344,7 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3337
3344
|
version: pkgView.version
|
|
3338
3345
|
};
|
|
3339
3346
|
} finally {
|
|
3340
|
-
fs$17.
|
|
3347
|
+
await fs$17.promises.rm(tmpDir, {
|
|
3341
3348
|
recursive: true,
|
|
3342
3349
|
force: true
|
|
3343
3350
|
});
|
|
@@ -4105,7 +4112,7 @@ var CapabilityRegistry = class CapabilityRegistry {
|
|
|
4105
4112
|
const bare = this.bareAddonId(addonId);
|
|
4106
4113
|
const nodeMap = this.singletonNodeOverrides.get(capabilityName);
|
|
4107
4114
|
if (nodeMap) {
|
|
4108
|
-
for (const [nodeId, ov] of
|
|
4115
|
+
for (const [nodeId, ov] of Array.from(nodeMap)) if (ov === bare) nodeMap.delete(nodeId);
|
|
4109
4116
|
if (nodeMap.size === 0) this.singletonNodeOverrides.delete(capabilityName);
|
|
4110
4117
|
}
|
|
4111
4118
|
this.logger.info("Provider unregistered from capability", {
|
|
@@ -7382,20 +7389,20 @@ var ConfigManager = class ConfigManager {
|
|
|
7382
7389
|
setSettingsStore(store) {
|
|
7383
7390
|
this.settingsStore = store;
|
|
7384
7391
|
}
|
|
7385
|
-
get(
|
|
7386
|
-
return this.resolveConfigValue(
|
|
7392
|
+
get(configPath) {
|
|
7393
|
+
return this.resolveConfigValue(configPath);
|
|
7387
7394
|
}
|
|
7388
|
-
resolveConfigValue(
|
|
7389
|
-
const bootstrapValue = this.getFromBootstrap(
|
|
7395
|
+
resolveConfigValue(configPath) {
|
|
7396
|
+
const bootstrapValue = this.getFromBootstrap(configPath);
|
|
7390
7397
|
if (bootstrapValue !== void 0) return bootstrapValue;
|
|
7391
7398
|
if (this.settingsStore !== null) {
|
|
7392
|
-
const storeValue = this.settingsStore.getSystem(
|
|
7399
|
+
const storeValue = this.settingsStore.getSystem(configPath);
|
|
7393
7400
|
if (storeValue !== void 0) return storeValue;
|
|
7394
|
-
const nested = this.getNestedFromSystemSettings(
|
|
7401
|
+
const nested = this.getNestedFromSystemSettings(configPath);
|
|
7395
7402
|
if (nested !== null) return nested;
|
|
7396
7403
|
}
|
|
7397
|
-
if (
|
|
7398
|
-
return this.getFromRuntimeDefaults(
|
|
7404
|
+
if (configPath in RUNTIME_DEFAULTS) return RUNTIME_DEFAULTS[configPath];
|
|
7405
|
+
return this.getFromRuntimeDefaults(configPath) ?? void 0;
|
|
7399
7406
|
}
|
|
7400
7407
|
/**
|
|
7401
7408
|
* Write a value to the settings-store.
|
|
@@ -7611,8 +7618,8 @@ var ConfigManager = class ConfigManager {
|
|
|
7611
7618
|
};
|
|
7612
7619
|
this.saveRuntimeState();
|
|
7613
7620
|
}
|
|
7614
|
-
getBootstrap(
|
|
7615
|
-
return this.getFromBootstrap(
|
|
7621
|
+
getBootstrap(configPath) {
|
|
7622
|
+
return this.getFromBootstrap(configPath);
|
|
7616
7623
|
}
|
|
7617
7624
|
/** Features accessor -- reads from settings-store when available, falls back to RUNTIME_DEFAULTS */
|
|
7618
7625
|
get features() {
|
|
@@ -7702,8 +7709,8 @@ var ConfigManager = class ConfigManager {
|
|
|
7702
7709
|
* Deep-set a value in a nested plain object using a dot-notation path.
|
|
7703
7710
|
* Returns a new object (immutable).
|
|
7704
7711
|
*/
|
|
7705
|
-
setNested(obj,
|
|
7706
|
-
const [head, ...rest] =
|
|
7712
|
+
setNested(obj, configPath, value) {
|
|
7713
|
+
const [head, ...rest] = configPath.split(".");
|
|
7707
7714
|
if (!head) return obj;
|
|
7708
7715
|
if (rest.length === 0) return {
|
|
7709
7716
|
...obj,
|
|
@@ -7743,8 +7750,8 @@ var ConfigManager = class ConfigManager {
|
|
|
7743
7750
|
warnDefaultCredentials() {
|
|
7744
7751
|
if (this.bootstrapConfig.auth.adminPassword === "changeme") console.warn("[ConfigManager] Warning: Using default admin password \"changeme\". Set auth.adminPassword in your config.yaml or the CAMSTACK_ADMIN_PASS env var.");
|
|
7745
7752
|
}
|
|
7746
|
-
getFromBootstrap(
|
|
7747
|
-
const keys =
|
|
7753
|
+
getFromBootstrap(configPath) {
|
|
7754
|
+
const keys = configPath.split(".");
|
|
7748
7755
|
let current = this.bootstrapConfig;
|
|
7749
7756
|
for (const key of keys) {
|
|
7750
7757
|
if (!isRecord(current)) return void 0;
|
|
@@ -7752,8 +7759,8 @@ var ConfigManager = class ConfigManager {
|
|
|
7752
7759
|
}
|
|
7753
7760
|
return current;
|
|
7754
7761
|
}
|
|
7755
|
-
getFromRuntimeDefaults(
|
|
7756
|
-
const prefix =
|
|
7762
|
+
getFromRuntimeDefaults(configPath) {
|
|
7763
|
+
const prefix = configPath + ".";
|
|
7757
7764
|
const result = {};
|
|
7758
7765
|
let found = false;
|
|
7759
7766
|
for (const [key, value] of Object.entries(RUNTIME_DEFAULTS)) if (key.startsWith(prefix)) {
|
|
@@ -7768,10 +7775,10 @@ var ConfigManager = class ConfigManager {
|
|
|
7768
7775
|
* e.g. path='features' matches keys 'features.streaming', 'features.notifications', etc.
|
|
7769
7776
|
* Returns an object keyed by the sub-key, or undefined if nothing is found.
|
|
7770
7777
|
*/
|
|
7771
|
-
getNestedFromSystemSettings(
|
|
7778
|
+
getNestedFromSystemSettings(configPath) {
|
|
7772
7779
|
if (this.settingsStore === null) return null;
|
|
7773
7780
|
const all = this.settingsStore.getAllSystem();
|
|
7774
|
-
const prefix =
|
|
7781
|
+
const prefix = configPath + ".";
|
|
7775
7782
|
const result = {};
|
|
7776
7783
|
let found = false;
|
|
7777
7784
|
for (const [key, value] of Object.entries(all)) if (key.startsWith(prefix)) {
|
|
@@ -90932,7 +90939,7 @@ function createProcessService(parentNodeId, dataDir, deps, parentTcpPort, parent
|
|
|
90932
90939
|
respawned.restartCount = prevRestartCount + 1;
|
|
90933
90940
|
});
|
|
90934
90941
|
restarted.push(name);
|
|
90935
|
-
} catch
|
|
90942
|
+
} catch {
|
|
90936
90943
|
failed.push(name);
|
|
90937
90944
|
}
|
|
90938
90945
|
return {
|
|
@@ -91327,8 +91334,8 @@ var LifecycleJobEngine = class {
|
|
|
91327
91334
|
} finally {
|
|
91328
91335
|
clearTimeout(timer);
|
|
91329
91336
|
}
|
|
91330
|
-
if (packages.length === 0) throw new Error("stageFramework returned no packages");
|
|
91331
91337
|
const [firstPackage] = packages;
|
|
91338
|
+
if (!firstPackage) throw new Error("stageFramework returned no packages");
|
|
91332
91339
|
this.advance(job.jobId, task, "staged", { stagedPath: firstPackage.stagedPath });
|
|
91333
91340
|
requestFrameworkSwap({
|
|
91334
91341
|
jobId: job.jobId,
|
|
@@ -91351,14 +91358,15 @@ var LifecycleJobEngine = class {
|
|
|
91351
91358
|
*/
|
|
91352
91359
|
async fetchAddonsBounded(job, addonTasks) {
|
|
91353
91360
|
const limit = Math.max(1, this.deps.fetchConcurrency ?? DEFAULT_FETCH_CONCURRENCY);
|
|
91354
|
-
const outcomes =
|
|
91361
|
+
const outcomes = Array.from({ length: addonTasks.length });
|
|
91355
91362
|
let nextIndex = 0;
|
|
91356
91363
|
const worker = async () => {
|
|
91357
91364
|
for (;;) {
|
|
91358
91365
|
const index = nextIndex;
|
|
91359
91366
|
nextIndex += 1;
|
|
91360
|
-
|
|
91361
|
-
|
|
91367
|
+
const addonTask = addonTasks[index];
|
|
91368
|
+
if (addonTask === void 0) return;
|
|
91369
|
+
outcomes[index] = await this.fetchAddonTask(job, addonTask);
|
|
91362
91370
|
}
|
|
91363
91371
|
};
|
|
91364
91372
|
const workerCount = Math.min(limit, addonTasks.length);
|
|
@@ -91484,4 +91492,4 @@ async function stageFrameworkLockstep(input) {
|
|
|
91484
91492
|
return results;
|
|
91485
91493
|
}
|
|
91486
91494
|
//#endregion
|
|
91487
|
-
export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REJECTED_EXIT_CODE, CORE_CAP_SERVICE_NAME, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CustomActionRegistry, DEFAULT_DATA_PATH, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FRAMEWORK_LOCKSTEP, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LifecycleJobEngine, LifecycleStateMachine, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, RESTART_MARKER_FILE, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, ScopedLogger, ScopedTokenManager, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, ToastService, UDS_NO_ROUTE_PREFIX, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, __resetCapUsageRegistryForTests, adaptBrokerToCluster, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildStorageLocationRegistry, buildUdsNativeCapProxy, callRegisterNodeWithRetry, callWithServiceDiscovery, capActionName, capActionSuffix, capBareAction, capServiceName, classifyCapRoute, clearPendingRestart, clusterSecretMatches, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonService, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCoreCapService, createFileDataPlaneHandler, createHubService, createHwAccelService, createKernelHwAccel, createLocalTransport, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, detectWorkspacePackagesDir, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, encodeFrame, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensurePython, ensureTlsCert, fetchJson, findInPath, formatLogLine, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getModelFilePath, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hashClusterSecret, installManifestNativeDeps, installManifestPythonDeps,
|
|
91495
|
+
export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REJECTED_EXIT_CODE, CORE_CAP_SERVICE_NAME, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CustomActionRegistry, DEFAULT_DATA_PATH, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FRAMEWORK_LOCKSTEP, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LifecycleJobEngine, LifecycleStateMachine, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, RESTART_MARKER_FILE, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, ScopedLogger, ScopedTokenManager, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, ToastService, UDS_NO_ROUTE_PREFIX, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, __resetCapUsageRegistryForTests, adaptBrokerToCluster, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildStorageLocationRegistry, buildUdsNativeCapProxy, callRegisterNodeWithRetry, callWithServiceDiscovery, capActionName, capActionSuffix, capBareAction, capServiceName, classifyCapRoute, clearPendingRestart, clusterSecretMatches, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonService, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCoreCapService, createFileDataPlaneHandler, createHubService, createHwAccelService, createKernelHwAccel, createLocalTransport, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, detectWorkspacePackagesDir, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, encodeFrame, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensurePython, ensureTlsCert, fetchJson, findInPath, formatLogLine, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getModelFilePath, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hashClusterSecret, installManifestNativeDeps, installManifestPythonDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcChildLink, ipcParentLink, isClusterSecretMismatchError, isInfraCapability, isModelDownloaded, isSourceNewer, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, parseCapAction, parseRangeHeader, parseTokenizedUrl, proxyToUpstream, readPendingRestart, readinessKey, registerEventBusService, resolveFilePath, resolveHwAccel, scheduleSelfRestart, scopeKey, scopesAllowDeviceCap, serializeTypedArrays, setHubConnected, stageFrameworkLockstep, stripCamstackDeps, udsChildLogToWorkerEntry, validateProviderRegistrations, writePendingRestart };
|
|
@@ -79,8 +79,8 @@ export declare class ConfigManager {
|
|
|
79
79
|
* as a convenience alias for legacy call sites; it performs NO runtime
|
|
80
80
|
* check and is the one documented type-level bridge in this function.
|
|
81
81
|
*/
|
|
82
|
-
get(
|
|
83
|
-
get<T>(
|
|
82
|
+
get(configPath: string): unknown;
|
|
83
|
+
get<T>(configPath: string): T | undefined;
|
|
84
84
|
private resolveConfigValue;
|
|
85
85
|
/**
|
|
86
86
|
* Write a value to the settings-store.
|
|
@@ -171,8 +171,8 @@ export declare class ConfigManager {
|
|
|
171
171
|
/** Get a value from the parsed bootstrap config.
|
|
172
172
|
* Generic overload is a documented type-level bridge — callers are responsible
|
|
173
173
|
* for passing a T that matches the config.yaml shape. */
|
|
174
|
-
getBootstrap(
|
|
175
|
-
getBootstrap<T>(
|
|
174
|
+
getBootstrap(configPath: string): unknown;
|
|
175
|
+
getBootstrap<T>(configPath: string): T | undefined;
|
|
176
176
|
/** Features accessor -- reads from settings-store when available, falls back to RUNTIME_DEFAULTS */
|
|
177
177
|
get features(): FeatureManifest;
|
|
178
178
|
/**
|
|
@@ -4,10 +4,16 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export declare function ensureDir(dirPath: string): void;
|
|
6
6
|
/**
|
|
7
|
-
* Copy a directory recursively.
|
|
8
|
-
*
|
|
7
|
+
* Copy a directory recursively — ASYNC so it never blocks the event loop.
|
|
8
|
+
*
|
|
9
|
+
* The hub installs addons into `/data/addons`, which on Unraid is a slow
|
|
10
|
+
* shfs/FUSE mount. The former synchronous `fs.copyFileSync`-per-file loop
|
|
11
|
+
* blocked the Node event loop for the whole copy of a large bundle (e.g.
|
|
12
|
+
* `addon-pipeline`), which froze the hub's HTTP listener mid-`camstack deploy`
|
|
13
|
+
* (accept backlog piling up, existing connections stuck in CLOSE_WAIT). Using
|
|
14
|
+
* `fs.promises.cp` keeps the I/O off the event loop. (Node ≥18 stable.)
|
|
9
15
|
*/
|
|
10
|
-
export declare function copyDirRecursive(src: string, dest: string): void
|
|
16
|
+
export declare function copyDirRecursive(src: string, dest: string): Promise<void>;
|
|
11
17
|
/**
|
|
12
18
|
* Strip @camstack/* dependencies and devDependencies from a package.json object.
|
|
13
19
|
* Used when installing addons into the addons directory — @camstack packages
|
|
@@ -21,7 +27,7 @@ export declare function stripCamstackDeps(pkg: Record<string, unknown>): Record<
|
|
|
21
27
|
* Copies directories (not individual files) from source to destination.
|
|
22
28
|
* Skips "dist" (already handled) and glob patterns.
|
|
23
29
|
*/
|
|
24
|
-
export declare function copyExtraFileDirs(pkgJson: Record<string, unknown>, sourceDir: string, destDir: string): void
|
|
30
|
+
export declare function copyExtraFileDirs(pkgJson: Record<string, unknown>, sourceDir: string, destDir: string): Promise<void>;
|
|
25
31
|
/**
|
|
26
32
|
* Check if any file in src/ is newer than dist/.
|
|
27
33
|
* Returns true if rebuild is needed.
|
|
@@ -36,6 +42,10 @@ export declare function ensureLibraryBuilt(packageName: string, packagesDir: str
|
|
|
36
42
|
/**
|
|
37
43
|
* Install a single npm package into a target directory (package.json + dist/).
|
|
38
44
|
* No validation on camstack.addons -- works for any @camstack/* package.
|
|
39
|
-
*
|
|
45
|
+
*
|
|
46
|
+
* ASYNC: uses `execFile`/`fs.promises` throughout so a package install on a
|
|
47
|
+
* live node never blocks the event loop (the `npm pack` + tar extract + copy to
|
|
48
|
+
* the slow shfs/FUSE `/data` would otherwise freeze the HTTP listener). See
|
|
49
|
+
* `copyDirRecursive` for the wedge this prevents.
|
|
40
50
|
*/
|
|
41
|
-
export declare function
|
|
51
|
+
export declare function installPackageFromNpm(packageName: string, targetDir: string): Promise<void>;
|
package/dist/kernel/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type { AddonInstallerConfig, InstallSource, InstalledPackage } from './ad
|
|
|
5
5
|
export { AddonInstaller } from './addon-installer.js';
|
|
6
6
|
export type { AddonInstallSource, AddonManifestEntry, AddonManifestFile } from './addon-manifest.js';
|
|
7
7
|
export { AddonManifest } from './addon-manifest.js';
|
|
8
|
-
export { copyDirRecursive, ensureDir, stripCamstackDeps, copyExtraFileDirs, ensureLibraryBuilt,
|
|
8
|
+
export { copyDirRecursive, ensureDir, stripCamstackDeps, copyExtraFileDirs, ensureLibraryBuilt, installPackageFromNpm, isSourceNewer, } from './fs-utils.js';
|
|
9
9
|
export { detectWorkspacePackagesDir } from './workspace-detect.js';
|
|
10
10
|
export { RESTART_MARKER_FILE, clearPendingRestart, getRestartMarkerPath, readPendingRestart, scheduleSelfRestart, writePendingRestart, } from './restart-coordinator.js';
|
|
11
11
|
export type { PendingRestartMarker, RestartKind, ScheduleSelfRestartOptions, } from './restart-coordinator.js';
|
|
@@ -23,6 +23,14 @@ export interface CapCallOutMessage {
|
|
|
23
23
|
readonly method: string;
|
|
24
24
|
readonly args: unknown;
|
|
25
25
|
readonly deviceId?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Optional per-call node pin (out-of-band; NOT part of the validated method
|
|
28
|
+
* args). When set, the parent routes this singleton/in-process cap call to
|
|
29
|
+
* the named node's provider instead of the default (hub) resolution — used to
|
|
30
|
+
* query a remote agent's in-process singleton (e.g. the agent's own
|
|
31
|
+
* `platform-probe` hardware). Set via `ctx.api`'s `onNode(nodeId)` modifier.
|
|
32
|
+
*/
|
|
33
|
+
readonly nodeId?: string;
|
|
26
34
|
}
|
|
27
35
|
/** Child → parent: a system event produced by the child to be forwarded to the hub event bus. */
|
|
28
36
|
export interface ChildEventMessage {
|
|
@@ -59,6 +67,8 @@ export interface CapCallMessage {
|
|
|
59
67
|
readonly method: string;
|
|
60
68
|
readonly args: unknown;
|
|
61
69
|
readonly deviceId?: number;
|
|
70
|
+
/** Optional per-call node pin (out-of-band routing hint; see {@link CapCallOutMessage.nodeId}). */
|
|
71
|
+
readonly nodeId?: string;
|
|
62
72
|
}
|
|
63
73
|
/** Parent → child: a system event delivered by the hub for the child to handle locally. */
|
|
64
74
|
export interface ParentEventMessage {
|
|
@@ -5,6 +5,7 @@ let node_fs = require("node:fs");
|
|
|
5
5
|
node_fs = require_chunk.__toESM(node_fs);
|
|
6
6
|
let node_path = require("node:path");
|
|
7
7
|
node_path = require_chunk.__toESM(node_path);
|
|
8
|
+
let _camstack_types = require("@camstack/types");
|
|
8
9
|
let node_crypto = require("node:crypto");
|
|
9
10
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
10
11
|
let node_child_process = require("node:child_process");
|
|
@@ -3647,7 +3648,8 @@ var LocalChildRegistry = class {
|
|
|
3647
3648
|
capName: out.capName,
|
|
3648
3649
|
method: out.method,
|
|
3649
3650
|
args: out.args,
|
|
3650
|
-
...out.deviceId !== void 0 ? { deviceId: out.deviceId } : {}
|
|
3651
|
+
...out.deviceId !== void 0 ? { deviceId: out.deviceId } : {},
|
|
3652
|
+
...out.nodeId !== void 0 ? { nodeId: out.nodeId } : {}
|
|
3651
3653
|
};
|
|
3652
3654
|
if (this.resolveChildId(out.capName, out.deviceId) !== null) {
|
|
3653
3655
|
if (!this.egressRoutedCaps.has(out.capName)) {
|
|
@@ -3892,7 +3894,8 @@ var LocalChildClient = class {
|
|
|
3892
3894
|
capName: input.capName,
|
|
3893
3895
|
method: input.method,
|
|
3894
3896
|
args: input.args,
|
|
3895
|
-
...input.deviceId !== void 0 ? { deviceId: input.deviceId } : {}
|
|
3897
|
+
...input.deviceId !== void 0 ? { deviceId: input.deviceId } : {},
|
|
3898
|
+
...input.nodeId !== void 0 ? { nodeId: input.nodeId } : {}
|
|
3896
3899
|
};
|
|
3897
3900
|
return this.channel.request(msg);
|
|
3898
3901
|
}
|
|
@@ -4586,7 +4589,10 @@ function createParentUnownedCallHandler(deps) {
|
|
|
4586
4589
|
const deviceId = input.deviceId ?? extractDeviceId(input.args);
|
|
4587
4590
|
const resolver = deps.getResolver();
|
|
4588
4591
|
if (resolver !== null) try {
|
|
4589
|
-
const route = resolver.resolveCapRoute(input.capName,
|
|
4592
|
+
const route = resolver.resolveCapRoute(input.capName, {
|
|
4593
|
+
...input.nodeId !== void 0 ? { nodeId: input.nodeId } : {},
|
|
4594
|
+
...deviceId !== void 0 ? { deviceId } : {}
|
|
4595
|
+
});
|
|
4590
4596
|
return await resolver.dispatch(route, input.method, input.args);
|
|
4591
4597
|
} catch (err) {
|
|
4592
4598
|
if (!(err instanceof CapRouteError) || err.reason !== "no-provider") throw err;
|
|
@@ -4623,7 +4629,7 @@ function createParentUnownedCallHandler(deps) {
|
|
|
4623
4629
|
return await brokerCallForCap(deps.broker, input.capName, input.method, input.args);
|
|
4624
4630
|
} catch (cause) {
|
|
4625
4631
|
const reason = cause instanceof Error ? cause.message : String(cause);
|
|
4626
|
-
throw new Error(`parent could not route child unowned cap call "${input.capName}.${input.method}": ${reason}`,
|
|
4632
|
+
throw new Error(`parent could not route child unowned cap call "${input.capName}.${input.method}": ${reason}`, { cause });
|
|
4627
4633
|
}
|
|
4628
4634
|
};
|
|
4629
4635
|
}
|
|
@@ -5031,11 +5037,13 @@ function ipcParentLink(getCallOut) {
|
|
|
5031
5037
|
const input = op.input;
|
|
5032
5038
|
const inputObj = input && typeof input === "object" && !Array.isArray(input) ? input : null;
|
|
5033
5039
|
const deviceId = inputObj && typeof Reflect.get(inputObj, "deviceId") === "number" ? Reflect.get(inputObj, "deviceId") : void 0;
|
|
5040
|
+
const pinnedNodeId = (0, _camstack_types.readNodePin)(op.context);
|
|
5034
5041
|
const capCallInput = {
|
|
5035
5042
|
capName: parsed.capName,
|
|
5036
5043
|
method: parsed.method,
|
|
5037
5044
|
args: op.input,
|
|
5038
|
-
...deviceId !== void 0 ? { deviceId } : {}
|
|
5045
|
+
...deviceId !== void 0 ? { deviceId } : {},
|
|
5046
|
+
...pinnedNodeId !== void 0 ? { nodeId: pinnedNodeId } : {}
|
|
5039
5047
|
};
|
|
5040
5048
|
return observable((observer) => {
|
|
5041
5049
|
callOut(capCallInput).then((data) => {
|
|
@@ -5100,7 +5108,7 @@ var CapUsageRegistry = class {
|
|
|
5100
5108
|
let window = byCap.get(rec.capName);
|
|
5101
5109
|
if (!window) {
|
|
5102
5110
|
window = {
|
|
5103
|
-
buckets:
|
|
5111
|
+
buckets: Array.from({ length: this.retentionSeconds }, () => 0),
|
|
5104
5112
|
lastCallAtMs: 0
|
|
5105
5113
|
};
|
|
5106
5114
|
byCap.set(rec.capName, window);
|
|
@@ -6277,16 +6285,25 @@ async function buildAddonContext(runtime, declaration, dataDir, options) {
|
|
|
6277
6285
|
};
|
|
6278
6286
|
const writeBlob = async (coll, key, value, namespace) => {
|
|
6279
6287
|
if (!settingsApi) return;
|
|
6280
|
-
|
|
6281
|
-
namespace
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
|
|
6288
|
+
try {
|
|
6289
|
+
await settingsApi.set.mutate(namespace !== void 0 ? {
|
|
6290
|
+
namespace,
|
|
6291
|
+
collection: coll,
|
|
6292
|
+
key,
|
|
6293
|
+
value
|
|
6294
|
+
} : {
|
|
6295
|
+
collection: coll,
|
|
6296
|
+
key,
|
|
6297
|
+
value
|
|
6298
|
+
});
|
|
6299
|
+
} catch (err) {
|
|
6300
|
+
const isTrpcError = err instanceof _trpc_client.TRPCClientError;
|
|
6301
|
+
scopedLogger.warn(`settings write failed (${coll}/${key}) — ${isTrpcError ? "transport error" : "store error"}`, { meta: {
|
|
6302
|
+
collection: coll,
|
|
6303
|
+
key,
|
|
6304
|
+
error: (0, _camstack_types_addon.errMsg)(err)
|
|
6305
|
+
} });
|
|
6306
|
+
}
|
|
6290
6307
|
};
|
|
6291
6308
|
const rmwChains = /* @__PURE__ */ new Map();
|
|
6292
6309
|
const serializeRmw = (coll, key, op) => {
|
|
@@ -6295,7 +6312,7 @@ async function buildAddonContext(runtime, declaration, dataDir, options) {
|
|
|
6295
6312
|
rmwChains.set(chainKey, next);
|
|
6296
6313
|
next.finally(() => {
|
|
6297
6314
|
if (rmwChains.get(chainKey) === next) rmwChains.delete(chainKey);
|
|
6298
|
-
});
|
|
6315
|
+
}).catch(() => void 0);
|
|
6299
6316
|
return next;
|
|
6300
6317
|
};
|
|
6301
6318
|
const settingsView = {
|