@camstack/system 1.1.25 → 1.1.27
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 +1 -1
- package/dist/addon-runner.mjs +1 -1
- package/dist/builtins/platform-probe/index.d.ts +0 -11
- package/dist/builtins/platform-probe/index.js +4 -309
- package/dist/builtins/platform-probe/index.mjs +5 -308
- package/dist/builtins/system-config/system-config.addon.js +51 -118
- package/dist/builtins/system-config/system-config.addon.mjs +51 -118
- package/dist/index.js +19 -22
- package/dist/index.mjs +19 -22
- package/dist/kernel/hwaccel/hwaccel-resolver.d.ts +9 -0
- package/dist/kernel/inference/inference-resolver.d.ts +16 -0
- package/dist/{manifest-python-deps-BqXCckob.js → manifest-python-deps-CCmnJmNf.js} +26 -1
- package/dist/{manifest-python-deps-Dxl4twM3.mjs → manifest-python-deps-DPA7N9UP.mjs} +26 -1
- package/package.json +1 -1
- package/dist/builtins/platform-probe/hardware-decode-accel-probe.d.ts +0 -37
- package/dist/builtins/platform-probe/hardware-encoder-probe.d.ts +0 -13
|
@@ -39,8 +39,7 @@ import { BaseAddon, errMsg, hydrateSchema } from "@camstack/types";
|
|
|
39
39
|
/** Section key → user-facing section title. */
|
|
40
40
|
var SECTION_TITLES = {
|
|
41
41
|
server: "Server",
|
|
42
|
-
auth: "Authentication"
|
|
43
|
-
ffmpeg: "FFmpeg"
|
|
42
|
+
auth: "Authentication"
|
|
44
43
|
};
|
|
45
44
|
/** Keys that map 1:1 to a given yml section — used by `updateGlobalSettings`
|
|
46
45
|
* to figure out which section owns each key in the incoming patch. */
|
|
@@ -48,10 +47,7 @@ var KEY_TO_SECTION = {
|
|
|
48
47
|
port: "server",
|
|
49
48
|
host: "server",
|
|
50
49
|
dataPath: "server",
|
|
51
|
-
tokenExpiry: "auth"
|
|
52
|
-
binaryPath: "ffmpeg",
|
|
53
|
-
hwAccel: "ffmpeg",
|
|
54
|
-
threadCount: "ffmpeg"
|
|
50
|
+
tokenExpiry: "auth"
|
|
55
51
|
};
|
|
56
52
|
var SystemConfigAddon = class extends BaseAddon {
|
|
57
53
|
id = "system-config";
|
|
@@ -62,119 +58,56 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
62
58
|
this.ctx.logger.info("Initialized — exposes yml-backed sections via getGlobalSettings");
|
|
63
59
|
}
|
|
64
60
|
buildGlobalSchema() {
|
|
65
|
-
return { sections: [
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
{
|
|
80
|
-
type: "text",
|
|
81
|
-
key: "port",
|
|
82
|
-
label: "Port",
|
|
83
|
-
description: "Listening port",
|
|
84
|
-
disabled: true
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
type: "text",
|
|
88
|
-
key: "host",
|
|
89
|
-
label: "Host",
|
|
90
|
-
description: "Bind address",
|
|
91
|
-
disabled: true
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
type: "text",
|
|
95
|
-
key: "dataPath",
|
|
96
|
-
label: "Data Path",
|
|
97
|
-
description: "Root data directory",
|
|
98
|
-
disabled: true,
|
|
99
|
-
span: 2
|
|
100
|
-
}
|
|
101
|
-
]
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
id: "system-config-auth",
|
|
105
|
-
title: SECTION_TITLES["auth"],
|
|
106
|
-
description: "Token and session settings.",
|
|
107
|
-
columns: 1,
|
|
108
|
-
fields: [{
|
|
61
|
+
return { sections: [{
|
|
62
|
+
id: "system-config-server",
|
|
63
|
+
title: SECTION_TITLES["server"],
|
|
64
|
+
description: "Core server connection settings — read-only, loaded from config.yaml at bootstrap.",
|
|
65
|
+
columns: 2,
|
|
66
|
+
fields: [
|
|
67
|
+
{
|
|
68
|
+
type: "info",
|
|
69
|
+
key: "server-restart-note",
|
|
70
|
+
label: "Restart required",
|
|
71
|
+
content: "Server settings are read-only. Change them in config.yaml and restart.",
|
|
72
|
+
variant: "warning"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
109
75
|
type: "text",
|
|
110
|
-
key: "
|
|
111
|
-
label: "
|
|
112
|
-
description: "
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
label: "None (CPU only)"
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
value: "videotoolbox",
|
|
149
|
-
label: "VideoToolbox (macOS)"
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
value: "vaapi",
|
|
153
|
-
label: "VA-API (Linux Intel/AMD)"
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
value: "qsv",
|
|
157
|
-
label: "QSV (Intel Quick Sync)"
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
value: "cuda",
|
|
161
|
-
label: "CUDA (NVIDIA)"
|
|
162
|
-
}
|
|
163
|
-
]
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
type: "number",
|
|
167
|
-
key: "threadCount",
|
|
168
|
-
label: "Thread Count",
|
|
169
|
-
description: "0 = auto (let FFmpeg decide)",
|
|
170
|
-
min: 0,
|
|
171
|
-
max: 16,
|
|
172
|
-
step: 1,
|
|
173
|
-
default: 0
|
|
174
|
-
}
|
|
175
|
-
]
|
|
176
|
-
}
|
|
177
|
-
] };
|
|
76
|
+
key: "port",
|
|
77
|
+
label: "Port",
|
|
78
|
+
description: "Listening port",
|
|
79
|
+
disabled: true
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
type: "text",
|
|
83
|
+
key: "host",
|
|
84
|
+
label: "Host",
|
|
85
|
+
description: "Bind address",
|
|
86
|
+
disabled: true
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
type: "text",
|
|
90
|
+
key: "dataPath",
|
|
91
|
+
label: "Data Path",
|
|
92
|
+
description: "Root data directory",
|
|
93
|
+
disabled: true,
|
|
94
|
+
span: 2
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
}, {
|
|
98
|
+
id: "system-config-auth",
|
|
99
|
+
title: SECTION_TITLES["auth"],
|
|
100
|
+
description: "Token and session settings.",
|
|
101
|
+
columns: 1,
|
|
102
|
+
fields: [{
|
|
103
|
+
type: "text",
|
|
104
|
+
key: "tokenExpiry",
|
|
105
|
+
label: "Token Expiry",
|
|
106
|
+
description: "JWT token lifetime (e.g. 24h, 7d, 1h)",
|
|
107
|
+
placeholder: "24h",
|
|
108
|
+
default: "24h"
|
|
109
|
+
}]
|
|
110
|
+
}] };
|
|
178
111
|
}
|
|
179
112
|
async getGlobalSettings() {
|
|
180
113
|
const schema = this.buildGlobalSchema();
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ const require_builtins_local_auth_local_auth_addon = require("./builtins/local-a
|
|
|
20
20
|
require("./builtins/local-auth/index.js");
|
|
21
21
|
const require_builtins_device_manager_device_manager_addon = require("./builtins/device-manager/device-manager.addon.js");
|
|
22
22
|
require("./builtins/device-manager/index.js");
|
|
23
|
-
const require_manifest_python_deps = require("./manifest-python-deps-
|
|
23
|
+
const require_manifest_python_deps = require("./manifest-python-deps-CCmnJmNf.js");
|
|
24
24
|
const require_custom_action_registry = require("./custom-action-registry-vLYEFTtv.js");
|
|
25
25
|
let _camstack_types_node = require("@camstack/types/node");
|
|
26
26
|
let node_http = require("node:http");
|
|
@@ -3339,32 +3339,30 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3339
3339
|
}
|
|
3340
3340
|
/** Install addon from a tgz file (uploaded or downloaded) */
|
|
3341
3341
|
async installFromTgz(tgzPath) {
|
|
3342
|
-
const
|
|
3342
|
+
const stagingRoot = node_path.join(this.addonsDir, ".staging");
|
|
3343
|
+
ensureDir(stagingRoot);
|
|
3344
|
+
await this.sweepGraveyard(stagingRoot);
|
|
3345
|
+
const stagingDir = node_path.join(stagingRoot, `install-${process.pid}-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`);
|
|
3346
|
+
ensureDir(stagingDir);
|
|
3343
3347
|
try {
|
|
3344
3348
|
await execFileAsync("tar", [
|
|
3345
3349
|
"-xzf",
|
|
3346
3350
|
tgzPath,
|
|
3347
3351
|
"-C",
|
|
3348
|
-
|
|
3349
|
-
], { timeout:
|
|
3350
|
-
const
|
|
3351
|
-
const pkgJsonPath =
|
|
3352
|
+
stagingDir
|
|
3353
|
+
], { timeout: 12e4 });
|
|
3354
|
+
const pkgDir = node_fs.existsSync(node_path.join(stagingDir, "package", "package.json")) ? node_path.join(stagingDir, "package") : stagingDir;
|
|
3355
|
+
const pkgJsonPath = node_path.join(pkgDir, "package.json");
|
|
3352
3356
|
if (!node_fs.existsSync(pkgJsonPath)) throw new Error("No package.json found in tgz archive");
|
|
3353
3357
|
const pkgView = readPackageJson(pkgJsonPath);
|
|
3354
3358
|
if (!pkgView) throw new Error(`Invalid package.json at ${pkgJsonPath}`);
|
|
3355
3359
|
if (!pkgView.camstackAddons) throw new Error(`Package ${pkgView.name} has no camstack.addons manifest`);
|
|
3356
3360
|
const targetDir = node_path.join(this.addonsDir, pkgView.name);
|
|
3357
|
-
await this.evictInstallDir(targetDir);
|
|
3358
|
-
ensureDir(targetDir);
|
|
3359
|
-
const sourceDir = node_path.dirname(pkgJsonPath);
|
|
3360
3361
|
const strippedManifest = stripCamstackDeps(pkgView.raw);
|
|
3361
|
-
await node_fs.promises.writeFile(
|
|
3362
|
-
const sourceDist = node_path.join(sourceDir, "dist");
|
|
3363
|
-
if (node_fs.existsSync(sourceDist)) await copyDirRecursive(sourceDist, node_path.join(targetDir, "dist"));
|
|
3364
|
-
await copyExtraFileDirs(pkgView.raw, sourceDir, targetDir);
|
|
3362
|
+
await node_fs.promises.writeFile(pkgJsonPath, JSON.stringify(strippedManifest, null, 2));
|
|
3365
3363
|
const strippedRuntimeDeps = strippedManifest["dependencies"];
|
|
3366
3364
|
if (strippedRuntimeDeps != null && typeof strippedRuntimeDeps === "object" && Object.keys(strippedRuntimeDeps).length > 0) {
|
|
3367
|
-
this.logger.info(`${pkgView.name} — installing runtime dependencies`, { meta: {
|
|
3365
|
+
this.logger.info(`${pkgView.name} — installing runtime dependencies`, { meta: { stagingDir: pkgDir } });
|
|
3368
3366
|
try {
|
|
3369
3367
|
await execFileAsync("npm", [
|
|
3370
3368
|
"install",
|
|
@@ -3375,7 +3373,7 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3375
3373
|
"--no-package-lock",
|
|
3376
3374
|
...this.registry ? ["--registry", this.registry] : []
|
|
3377
3375
|
], {
|
|
3378
|
-
cwd:
|
|
3376
|
+
cwd: pkgDir,
|
|
3379
3377
|
timeout: 24e4
|
|
3380
3378
|
});
|
|
3381
3379
|
} catch (err) {
|
|
@@ -3383,14 +3381,13 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3383
3381
|
}
|
|
3384
3382
|
}
|
|
3385
3383
|
try {
|
|
3386
|
-
await require_manifest_python_deps.installManifestNativeDeps(
|
|
3384
|
+
await require_manifest_python_deps.installManifestNativeDeps(pkgDir, pkgView.raw, this.logger, this.registry);
|
|
3387
3385
|
} catch (nativeErr) {
|
|
3388
|
-
await node_fs.promises.rm(targetDir, {
|
|
3389
|
-
recursive: true,
|
|
3390
|
-
force: true
|
|
3391
|
-
});
|
|
3392
3386
|
throw new Error(`${pkgView.name} — native deps install failed: ${(0, _camstack_types.errMsg)(nativeErr)}`, { cause: nativeErr });
|
|
3393
3387
|
}
|
|
3388
|
+
await this.evictInstallDir(targetDir);
|
|
3389
|
+
ensureDir(node_path.dirname(targetDir));
|
|
3390
|
+
await node_fs.promises.rename(pkgDir, targetDir);
|
|
3394
3391
|
this.manifest.upsert(pkgView.name, {
|
|
3395
3392
|
version: pkgView.version,
|
|
3396
3393
|
source: "bundled"
|
|
@@ -3400,10 +3397,10 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3400
3397
|
version: pkgView.version
|
|
3401
3398
|
};
|
|
3402
3399
|
} finally {
|
|
3403
|
-
await node_fs.promises.rm(
|
|
3400
|
+
await node_fs.promises.rm(stagingDir, {
|
|
3404
3401
|
recursive: true,
|
|
3405
3402
|
force: true
|
|
3406
|
-
});
|
|
3403
|
+
}).catch(() => void 0);
|
|
3407
3404
|
}
|
|
3408
3405
|
}
|
|
3409
3406
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -18,7 +18,7 @@ import { LocalAuthAddon, a as require_ms, c as __esmMin, d as __toCommonJS, f as
|
|
|
18
18
|
import "./builtins/local-auth/index.mjs";
|
|
19
19
|
import { DeviceManagerAddon } from "./builtins/device-manager/device-manager.addon.mjs";
|
|
20
20
|
import "./builtins/device-manager/index.mjs";
|
|
21
|
-
import { $ as buildUdsNativeCapProxy, A as createParentUnownedCallHandler, B as AGENT_CAP_FWD_SERVICE, C as buildLinkChain, D as HUB_CAP_FWD_ACTION, E as localProviderLink, F as createUdsLoggerWithControl, G as createLocalTransport, H as CapRouteError, I as LocalChildClient, J as SocketChannel, K as UdsLocalTransportClient, L as LocalChildRegistry, M as createUdsEventBus, N as udsChildLogToWorkerEntry, O as HUB_CAP_FWD_SERVICE, P as createUdsLogger, Q as buildNativeCapProxy, R as UDS_NO_ROUTE_PREFIX, S as brokerTransportLink, T as ipcParentLink, U as classifyCapRoute, V as CapRouteResolver, W as callWithServiceDiscovery, X as FrameDecoder, Y as localEndpointPath, Z as encodeFrame, _ as resolveHwAccel, _t as CapabilityUnavailableError, a as getWorkerDeviceRegistry, at as createAddonService, b as getCapUsageRegistry, c as setHubConnected, ct as capActionName, d as getMoleculerEventStats, dt as capServiceName, et as createBrokerDeviceManagerApi, f as registerEventBusService, ft as parseCapAction, g as createKernelHwAccel, gt as CapabilityHandle, h as AddonDepsManager, ht as DeviceRegistry, i as createUdsAddonContext, j as createUdsEventBridge, k as createHubCapForwardService, l as EVENT_TOPIC_PREFIX, lt as capActionSuffix, m as subscribePassthrough, mt as serializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as validateProviderRegistrations, p as setNodeEventInterest, pt as deserializeTypedArrays, q as UdsLocalTransportServer, r as createAddonContext, rt as mountNativeCapService, s as getOrInitReadinessRegistryForClient, st as NATIVE_PROVIDER_SERVICE_INFIX, t as installManifestPythonDeps, u as getBrokerEventBus, ut as capBareAction, v as CapUsageRegistry, vt as installManifestNativeDeps, w as ipcChildLink, x as brokerCallForCap, y as __resetCapUsageRegistryForTests, yt as resolveAddonClass, z as AGENT_CAP_FWD_ACTION } from "./manifest-python-deps-
|
|
21
|
+
import { $ as buildUdsNativeCapProxy, A as createParentUnownedCallHandler, B as AGENT_CAP_FWD_SERVICE, C as buildLinkChain, D as HUB_CAP_FWD_ACTION, E as localProviderLink, F as createUdsLoggerWithControl, G as createLocalTransport, H as CapRouteError, I as LocalChildClient, J as SocketChannel, K as UdsLocalTransportClient, L as LocalChildRegistry, M as createUdsEventBus, N as udsChildLogToWorkerEntry, O as HUB_CAP_FWD_SERVICE, P as createUdsLogger, Q as buildNativeCapProxy, R as UDS_NO_ROUTE_PREFIX, S as brokerTransportLink, T as ipcParentLink, U as classifyCapRoute, V as CapRouteResolver, W as callWithServiceDiscovery, X as FrameDecoder, Y as localEndpointPath, Z as encodeFrame, _ as resolveHwAccel, _t as CapabilityUnavailableError, a as getWorkerDeviceRegistry, at as createAddonService, b as getCapUsageRegistry, c as setHubConnected, ct as capActionName, d as getMoleculerEventStats, dt as capServiceName, et as createBrokerDeviceManagerApi, f as registerEventBusService, ft as parseCapAction, g as createKernelHwAccel, gt as CapabilityHandle, h as AddonDepsManager, ht as DeviceRegistry, i as createUdsAddonContext, j as createUdsEventBridge, k as createHubCapForwardService, l as EVENT_TOPIC_PREFIX, lt as capActionSuffix, m as subscribePassthrough, mt as serializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as validateProviderRegistrations, p as setNodeEventInterest, pt as deserializeTypedArrays, q as UdsLocalTransportServer, r as createAddonContext, rt as mountNativeCapService, s as getOrInitReadinessRegistryForClient, st as NATIVE_PROVIDER_SERVICE_INFIX, t as installManifestPythonDeps, u as getBrokerEventBus, ut as capBareAction, v as CapUsageRegistry, vt as installManifestNativeDeps, w as ipcChildLink, x as brokerCallForCap, y as __resetCapUsageRegistryForTests, yt as resolveAddonClass, z as AGENT_CAP_FWD_ACTION } from "./manifest-python-deps-DPA7N9UP.mjs";
|
|
22
22
|
import { t as CustomActionRegistry } from "./custom-action-registry-BEXwC-oo.mjs";
|
|
23
23
|
import { PYTHON_VERSION, buildBinaryPath, downloadBinary, ensureBinary, ensureFfmpeg, ensurePython, findInPath, getFfmpegDownloadUrl, getPlatformInfo, getPythonDownloadUrl, installPythonPackages, installPythonRequirements } from "@camstack/types/node";
|
|
24
24
|
import { request } from "node:http";
|
|
@@ -3331,32 +3331,30 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3331
3331
|
}
|
|
3332
3332
|
/** Install addon from a tgz file (uploaded or downloaded) */
|
|
3333
3333
|
async installFromTgz(tgzPath) {
|
|
3334
|
-
const
|
|
3334
|
+
const stagingRoot = path$39.join(this.addonsDir, ".staging");
|
|
3335
|
+
ensureDir(stagingRoot);
|
|
3336
|
+
await this.sweepGraveyard(stagingRoot);
|
|
3337
|
+
const stagingDir = path$39.join(stagingRoot, `install-${process.pid}-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`);
|
|
3338
|
+
ensureDir(stagingDir);
|
|
3335
3339
|
try {
|
|
3336
3340
|
await execFileAsync("tar", [
|
|
3337
3341
|
"-xzf",
|
|
3338
3342
|
tgzPath,
|
|
3339
3343
|
"-C",
|
|
3340
|
-
|
|
3341
|
-
], { timeout:
|
|
3342
|
-
const
|
|
3343
|
-
const pkgJsonPath =
|
|
3344
|
+
stagingDir
|
|
3345
|
+
], { timeout: 12e4 });
|
|
3346
|
+
const pkgDir = fs$17.existsSync(path$39.join(stagingDir, "package", "package.json")) ? path$39.join(stagingDir, "package") : stagingDir;
|
|
3347
|
+
const pkgJsonPath = path$39.join(pkgDir, "package.json");
|
|
3344
3348
|
if (!fs$17.existsSync(pkgJsonPath)) throw new Error("No package.json found in tgz archive");
|
|
3345
3349
|
const pkgView = readPackageJson(pkgJsonPath);
|
|
3346
3350
|
if (!pkgView) throw new Error(`Invalid package.json at ${pkgJsonPath}`);
|
|
3347
3351
|
if (!pkgView.camstackAddons) throw new Error(`Package ${pkgView.name} has no camstack.addons manifest`);
|
|
3348
3352
|
const targetDir = path$39.join(this.addonsDir, pkgView.name);
|
|
3349
|
-
await this.evictInstallDir(targetDir);
|
|
3350
|
-
ensureDir(targetDir);
|
|
3351
|
-
const sourceDir = path$39.dirname(pkgJsonPath);
|
|
3352
3353
|
const strippedManifest = stripCamstackDeps(pkgView.raw);
|
|
3353
|
-
await fs$17.promises.writeFile(
|
|
3354
|
-
const sourceDist = path$39.join(sourceDir, "dist");
|
|
3355
|
-
if (fs$17.existsSync(sourceDist)) await copyDirRecursive(sourceDist, path$39.join(targetDir, "dist"));
|
|
3356
|
-
await copyExtraFileDirs(pkgView.raw, sourceDir, targetDir);
|
|
3354
|
+
await fs$17.promises.writeFile(pkgJsonPath, JSON.stringify(strippedManifest, null, 2));
|
|
3357
3355
|
const strippedRuntimeDeps = strippedManifest["dependencies"];
|
|
3358
3356
|
if (strippedRuntimeDeps != null && typeof strippedRuntimeDeps === "object" && Object.keys(strippedRuntimeDeps).length > 0) {
|
|
3359
|
-
this.logger.info(`${pkgView.name} — installing runtime dependencies`, { meta: {
|
|
3357
|
+
this.logger.info(`${pkgView.name} — installing runtime dependencies`, { meta: { stagingDir: pkgDir } });
|
|
3360
3358
|
try {
|
|
3361
3359
|
await execFileAsync("npm", [
|
|
3362
3360
|
"install",
|
|
@@ -3367,7 +3365,7 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3367
3365
|
"--no-package-lock",
|
|
3368
3366
|
...this.registry ? ["--registry", this.registry] : []
|
|
3369
3367
|
], {
|
|
3370
|
-
cwd:
|
|
3368
|
+
cwd: pkgDir,
|
|
3371
3369
|
timeout: 24e4
|
|
3372
3370
|
});
|
|
3373
3371
|
} catch (err) {
|
|
@@ -3375,14 +3373,13 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3375
3373
|
}
|
|
3376
3374
|
}
|
|
3377
3375
|
try {
|
|
3378
|
-
await installManifestNativeDeps(
|
|
3376
|
+
await installManifestNativeDeps(pkgDir, pkgView.raw, this.logger, this.registry);
|
|
3379
3377
|
} catch (nativeErr) {
|
|
3380
|
-
await fs$17.promises.rm(targetDir, {
|
|
3381
|
-
recursive: true,
|
|
3382
|
-
force: true
|
|
3383
|
-
});
|
|
3384
3378
|
throw new Error(`${pkgView.name} — native deps install failed: ${errMsg(nativeErr)}`, { cause: nativeErr });
|
|
3385
3379
|
}
|
|
3380
|
+
await this.evictInstallDir(targetDir);
|
|
3381
|
+
ensureDir(path$39.dirname(targetDir));
|
|
3382
|
+
await fs$17.promises.rename(pkgDir, targetDir);
|
|
3386
3383
|
this.manifest.upsert(pkgView.name, {
|
|
3387
3384
|
version: pkgView.version,
|
|
3388
3385
|
source: "bundled"
|
|
@@ -3392,10 +3389,10 @@ var AddonInstaller = class AddonInstaller {
|
|
|
3392
3389
|
version: pkgView.version
|
|
3393
3390
|
};
|
|
3394
3391
|
} finally {
|
|
3395
|
-
await fs$17.promises.rm(
|
|
3392
|
+
await fs$17.promises.rm(stagingDir, {
|
|
3396
3393
|
recursive: true,
|
|
3397
3394
|
force: true
|
|
3398
|
-
});
|
|
3395
|
+
}).catch(() => void 0);
|
|
3399
3396
|
}
|
|
3400
3397
|
}
|
|
3401
3398
|
/**
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import { HwAccelBackend, HwAccelResolution } from '@camstack/types';
|
|
2
|
+
export interface PlatformSignals {
|
|
3
|
+
readonly platform: NodeJS.Platform;
|
|
4
|
+
readonly arch: string;
|
|
5
|
+
readonly hasNvidiaGpu: boolean;
|
|
6
|
+
readonly hasAmdGpu: boolean;
|
|
7
|
+
readonly hasIntelGpu: boolean;
|
|
8
|
+
readonly hasRenderNode: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function probePlatform(): PlatformSignals;
|
|
2
11
|
/**
|
|
3
12
|
* Resolve the preferred hardware acceleration backend order for the
|
|
4
13
|
* current host.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { IKernelInferenceEngine, KernelInferenceHardware } from '@camstack/types';
|
|
2
|
+
import { PlatformSignals } from '../hwaccel/hwaccel-resolver.js';
|
|
3
|
+
/**
|
|
4
|
+
* Map the shared platform GPU-vendor probe into the inference `gpu`/`npu` types
|
|
5
|
+
* the runtime scorer understands. NVIDIA → cuda; Intel iGPU (or a bare render
|
|
6
|
+
* node) → openvino; Apple Silicon → CoreML/ANE. The Intel NPU is not separately
|
|
7
|
+
* detected — an Intel iGPU already selects openvino (the NPU only bumps the
|
|
8
|
+
* score, never changes the winner). PURE — unit-tested.
|
|
9
|
+
*/
|
|
10
|
+
export declare function mapSignalsToInferenceHardware(signals: PlatformSignals): KernelInferenceHardware;
|
|
11
|
+
/**
|
|
12
|
+
* Build the local in-process inference-hardware resolver used to populate
|
|
13
|
+
* `ctx.kernel.inferenceEngine`. The exact model as `createKernelHwAccel`:
|
|
14
|
+
* deterministic per host, safe to call repeatedly, always the LOCAL node.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createKernelInferenceEngine(): IKernelInferenceEngine;
|
|
@@ -5661,6 +5661,29 @@ function createKernelHwAccel() {
|
|
|
5661
5661
|
return { resolve: async (prefer) => resolveHwAccel(prefer) };
|
|
5662
5662
|
}
|
|
5663
5663
|
//#endregion
|
|
5664
|
+
//#region src/kernel/inference/inference-resolver.ts
|
|
5665
|
+
/**
|
|
5666
|
+
* Map the shared platform GPU-vendor probe into the inference `gpu`/`npu` types
|
|
5667
|
+
* the runtime scorer understands. NVIDIA → cuda; Intel iGPU (or a bare render
|
|
5668
|
+
* node) → openvino; Apple Silicon → CoreML/ANE. The Intel NPU is not separately
|
|
5669
|
+
* detected — an Intel iGPU already selects openvino (the NPU only bumps the
|
|
5670
|
+
* score, never changes the winner). PURE — unit-tested.
|
|
5671
|
+
*/
|
|
5672
|
+
function mapSignalsToInferenceHardware(signals) {
|
|
5673
|
+
return {
|
|
5674
|
+
gpu: signals.hasNvidiaGpu ? { type: "nvidia" } : signals.hasIntelGpu || signals.hasRenderNode ? { type: "intel" } : null,
|
|
5675
|
+
npu: signals.platform === "darwin" && signals.arch === "arm64" ? { type: "apple-ane" } : null
|
|
5676
|
+
};
|
|
5677
|
+
}
|
|
5678
|
+
/**
|
|
5679
|
+
* Build the local in-process inference-hardware resolver used to populate
|
|
5680
|
+
* `ctx.kernel.inferenceEngine`. The exact model as `createKernelHwAccel`:
|
|
5681
|
+
* deterministic per host, safe to call repeatedly, always the LOCAL node.
|
|
5682
|
+
*/
|
|
5683
|
+
function createKernelInferenceEngine() {
|
|
5684
|
+
return { resolveHardware: async () => mapSignalsToInferenceHardware(probePlatform()) };
|
|
5685
|
+
}
|
|
5686
|
+
//#endregion
|
|
5664
5687
|
//#region src/kernel/moleculer/addon-data-plane-facility.ts
|
|
5665
5688
|
/**
|
|
5666
5689
|
* Kernel side of the addon HTTP **data-plane** (see {@link AddonDataPlane}).
|
|
@@ -6926,6 +6949,7 @@ async function buildAddonContext(runtime, declaration, dataDir, options) {
|
|
|
6926
6949
|
})
|
|
6927
6950
|
};
|
|
6928
6951
|
const hwaccel = createKernelHwAccel();
|
|
6952
|
+
const inferenceEngine = createKernelInferenceEngine();
|
|
6929
6953
|
return {
|
|
6930
6954
|
localNodeId: nodeId,
|
|
6931
6955
|
storage: options?.storageProvider ?? void 0,
|
|
@@ -6946,7 +6970,8 @@ async function buildAddonContext(runtime, declaration, dataDir, options) {
|
|
|
6946
6970
|
}),
|
|
6947
6971
|
...runtime.mode === "broker" ? { cluster: { broker: adaptBrokerToCluster(runtime.broker) } } : {},
|
|
6948
6972
|
streamProbe,
|
|
6949
|
-
hwaccel
|
|
6973
|
+
hwaccel,
|
|
6974
|
+
inferenceEngine
|
|
6950
6975
|
};
|
|
6951
6976
|
})(),
|
|
6952
6977
|
registerProvider(capabilityName, provider) {
|
|
@@ -5659,6 +5659,29 @@ function createKernelHwAccel() {
|
|
|
5659
5659
|
return { resolve: async (prefer) => resolveHwAccel(prefer) };
|
|
5660
5660
|
}
|
|
5661
5661
|
//#endregion
|
|
5662
|
+
//#region src/kernel/inference/inference-resolver.ts
|
|
5663
|
+
/**
|
|
5664
|
+
* Map the shared platform GPU-vendor probe into the inference `gpu`/`npu` types
|
|
5665
|
+
* the runtime scorer understands. NVIDIA → cuda; Intel iGPU (or a bare render
|
|
5666
|
+
* node) → openvino; Apple Silicon → CoreML/ANE. The Intel NPU is not separately
|
|
5667
|
+
* detected — an Intel iGPU already selects openvino (the NPU only bumps the
|
|
5668
|
+
* score, never changes the winner). PURE — unit-tested.
|
|
5669
|
+
*/
|
|
5670
|
+
function mapSignalsToInferenceHardware(signals) {
|
|
5671
|
+
return {
|
|
5672
|
+
gpu: signals.hasNvidiaGpu ? { type: "nvidia" } : signals.hasIntelGpu || signals.hasRenderNode ? { type: "intel" } : null,
|
|
5673
|
+
npu: signals.platform === "darwin" && signals.arch === "arm64" ? { type: "apple-ane" } : null
|
|
5674
|
+
};
|
|
5675
|
+
}
|
|
5676
|
+
/**
|
|
5677
|
+
* Build the local in-process inference-hardware resolver used to populate
|
|
5678
|
+
* `ctx.kernel.inferenceEngine`. The exact model as `createKernelHwAccel`:
|
|
5679
|
+
* deterministic per host, safe to call repeatedly, always the LOCAL node.
|
|
5680
|
+
*/
|
|
5681
|
+
function createKernelInferenceEngine() {
|
|
5682
|
+
return { resolveHardware: async () => mapSignalsToInferenceHardware(probePlatform()) };
|
|
5683
|
+
}
|
|
5684
|
+
//#endregion
|
|
5662
5685
|
//#region src/kernel/moleculer/addon-data-plane-facility.ts
|
|
5663
5686
|
/**
|
|
5664
5687
|
* Kernel side of the addon HTTP **data-plane** (see {@link AddonDataPlane}).
|
|
@@ -6924,6 +6947,7 @@ async function buildAddonContext(runtime, declaration, dataDir, options) {
|
|
|
6924
6947
|
})
|
|
6925
6948
|
};
|
|
6926
6949
|
const hwaccel = createKernelHwAccel();
|
|
6950
|
+
const inferenceEngine = createKernelInferenceEngine();
|
|
6927
6951
|
return {
|
|
6928
6952
|
localNodeId: nodeId,
|
|
6929
6953
|
storage: options?.storageProvider ?? void 0,
|
|
@@ -6944,7 +6968,8 @@ async function buildAddonContext(runtime, declaration, dataDir, options) {
|
|
|
6944
6968
|
}),
|
|
6945
6969
|
...runtime.mode === "broker" ? { cluster: { broker: adaptBrokerToCluster(runtime.broker) } } : {},
|
|
6946
6970
|
streamProbe,
|
|
6947
|
-
hwaccel
|
|
6971
|
+
hwaccel,
|
|
6972
|
+
inferenceEngine
|
|
6948
6973
|
};
|
|
6949
6974
|
})(),
|
|
6950
6975
|
registerProvider(capabilityName, provider) {
|
package/package.json
CHANGED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { HardwareDecodeAccels, IScopedLogger } from '@camstack/types';
|
|
2
|
-
/**
|
|
3
|
-
* Injectable runner for `ffmpeg -hwaccels`. Defaults to a real `execFile`;
|
|
4
|
-
* tests pass a fake to assert behaviour without spawning ffmpeg.
|
|
5
|
-
*/
|
|
6
|
-
export type HwAccelExecFn = (ffmpegPath: string, args: readonly string[]) => Promise<{
|
|
7
|
-
stdout: string;
|
|
8
|
-
}>;
|
|
9
|
-
/**
|
|
10
|
-
* Parse the output of `ffmpeg -hwaccels`. The listing looks like:
|
|
11
|
-
*
|
|
12
|
-
* Hardware acceleration methods:
|
|
13
|
-
* videotoolbox
|
|
14
|
-
*
|
|
15
|
-
* The header line is dropped; remaining non-empty trimmed lines are the
|
|
16
|
-
* method names, lowercased and de-duplicated (order preserved).
|
|
17
|
-
*/
|
|
18
|
-
export declare function parseHwAccelsOutput(stdout: string): string[];
|
|
19
|
-
/**
|
|
20
|
-
* Probes which `-hwaccel` decode backends the configured ffmpeg binary
|
|
21
|
-
* supports. Mirrors {@link HardwareEncoderProber} (configured binary, cached,
|
|
22
|
-
* single-flight, forceable). Never throws: a probe failure yields an empty
|
|
23
|
-
* method list so callers fall back to software decode.
|
|
24
|
-
*/
|
|
25
|
-
export declare class HardwareDecodeAccelProber {
|
|
26
|
-
private cached;
|
|
27
|
-
private inflight;
|
|
28
|
-
private readonly logger;
|
|
29
|
-
private readonly ffmpegPath;
|
|
30
|
-
private readonly execFn;
|
|
31
|
-
constructor(logger: IScopedLogger, ffmpegPath?: string, execFn?: HwAccelExecFn);
|
|
32
|
-
getCached(): HardwareDecodeAccels | null;
|
|
33
|
-
probe(options?: {
|
|
34
|
-
readonly force?: boolean;
|
|
35
|
-
}): Promise<HardwareDecodeAccels>;
|
|
36
|
-
private runProbe;
|
|
37
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { HardwareInfo, HardwareEncoders, IScopedLogger } from '@camstack/types';
|
|
2
|
-
export declare class HardwareEncoderProber {
|
|
3
|
-
private cached;
|
|
4
|
-
private inflight;
|
|
5
|
-
private readonly logger;
|
|
6
|
-
private readonly ffmpegPath;
|
|
7
|
-
constructor(logger: IScopedLogger, ffmpegPath?: string);
|
|
8
|
-
getCached(): HardwareEncoders | null;
|
|
9
|
-
probe(hardware: HardwareInfo, options?: {
|
|
10
|
-
readonly force?: boolean;
|
|
11
|
-
}): Promise<HardwareEncoders>;
|
|
12
|
-
private runProbe;
|
|
13
|
-
}
|