@camstack/system 1.2.2 → 1.2.3

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.
Files changed (50) hide show
  1. package/dist/addon-runner.js +2 -2
  2. package/dist/addon-runner.mjs +2 -2
  3. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/alerts/alerts.addon.js +1 -1
  8. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  9. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  10. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  11. package/dist/builtins/console-logging/index.js +1 -1
  12. package/dist/builtins/console-logging/index.mjs +1 -1
  13. package/dist/builtins/device-manager/device-manager.addon.js +1 -1
  14. package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
  15. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  16. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  17. package/dist/builtins/hub-forwarder/index.js +1 -1
  18. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  19. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  20. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  21. package/dist/builtins/local-network/local-network.addon.js +1 -1
  22. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  23. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  24. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  25. package/dist/builtins/platform-probe/index.js +1 -1
  26. package/dist/builtins/platform-probe/index.mjs +1 -1
  27. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  28. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  29. package/dist/builtins/snapshot/index.js +1 -1
  30. package/dist/builtins/snapshot/index.mjs +1 -1
  31. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  32. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  33. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +1 -1
  34. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
  35. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  36. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  37. package/dist/builtins/system-config/system-config.addon.js +1 -1
  38. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  39. package/dist/builtins/winston-logging/index.js +1 -1
  40. package/dist/builtins/winston-logging/index.mjs +1 -1
  41. package/dist/{dist-DTTTjPCL.mjs → dist-72yufD8v.mjs} +2 -1
  42. package/dist/{dist-CkdNC8US.js → dist-CQZxGJ8u.js} +2 -1
  43. package/dist/index.d.ts +1 -0
  44. package/dist/index.js +163 -21
  45. package/dist/index.mjs +156 -16
  46. package/dist/kernel/deps/ensure-native-prebuilds.d.ts +36 -0
  47. package/dist/kernel/deps/manifest-native-deps.d.ts +17 -0
  48. package/dist/{manifest-python-deps-s_-uULmp.mjs → manifest-python-deps-6__QF75g.mjs} +88 -2
  49. package/dist/{manifest-python-deps-DRq5MreI.js → manifest-python-deps-Cd7ocUBi.js} +93 -1
  50. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("./chunk-Cek0wNdY.js");
3
- const require_dist = require("./dist-CkdNC8US.js");
3
+ const require_dist = require("./dist-CQZxGJ8u.js");
4
4
  const require_model_download_service = require("./model-download-service-hf0ookyy.js");
5
- const require_manifest_python_deps = require("./manifest-python-deps-DRq5MreI.js");
5
+ const require_manifest_python_deps = require("./manifest-python-deps-Cd7ocUBi.js");
6
6
  const require_resource_monitor = require("./resource-monitor-DNNomR-i.js");
7
7
  const require_builtins_sqlite_storage_filesystem_storage_addon = require("./builtins/sqlite-storage/filesystem-storage.addon.js");
8
8
  const require_builtins_sqlite_storage_sqlite_settings_addon = require("./builtins/sqlite-storage/sqlite-settings.addon.js");
@@ -184,7 +184,7 @@ function proxyToUpstream(opts) {
184
184
  }
185
185
  //#endregion
186
186
  //#region src/python/python-env-manager.ts
187
- var execFileAsync$3 = (0, node_util.promisify)(node_child_process.execFile);
187
+ var execFileAsync$4 = (0, node_util.promisify)(node_child_process.execFile);
188
188
  var PythonEnvManager = class {
189
189
  venvPath;
190
190
  cachedProbe = null;
@@ -194,12 +194,12 @@ var PythonEnvManager = class {
194
194
  async probe() {
195
195
  if (this.cachedProbe) return this.cachedProbe;
196
196
  for (const cmd of ["python3", "python"]) try {
197
- const { stdout } = await execFileAsync$3(cmd, ["--version"]);
197
+ const { stdout } = await execFileAsync$4(cmd, ["--version"]);
198
198
  const version = stdout.trim().replace("Python ", "");
199
199
  const major = parseInt(version.split(".")[0] ?? "0", 10);
200
200
  const minor = parseInt(version.split(".")[1] ?? "0", 10);
201
201
  if (major < 3 || major === 3 && minor < 10) continue;
202
- const { stdout: pathOut } = await execFileAsync$3(cmd, ["-c", "import sys; print(sys.executable)"]);
202
+ const { stdout: pathOut } = await execFileAsync$4(cmd, ["-c", "import sys; print(sys.executable)"]);
203
203
  this.cachedProbe = {
204
204
  available: true,
205
205
  version,
@@ -215,13 +215,13 @@ var PythonEnvManager = class {
215
215
  async ensure(options) {
216
216
  const probe = await this.probe();
217
217
  if (!probe.available || !probe.path) throw new Error("Python 3.10+ is required but not found on this system");
218
- if (!node_fs.existsSync(node_path.join(this.venvPath, "bin", "python"))) await execFileAsync$3(probe.path, [
218
+ if (!node_fs.existsSync(node_path.join(this.venvPath, "bin", "python"))) await execFileAsync$4(probe.path, [
219
219
  "-m",
220
220
  "venv",
221
221
  this.venvPath
222
222
  ]);
223
223
  const venvPython = node_path.join(this.venvPath, "bin", "python");
224
- if (options.packages.length > 0) await execFileAsync$3(venvPython, [
224
+ if (options.packages.length > 0) await execFileAsync$4(venvPython, [
225
225
  "-m",
226
226
  "pip",
227
227
  "install",
@@ -1692,7 +1692,7 @@ function matchPath(pattern, path) {
1692
1692
  }
1693
1693
  //#endregion
1694
1694
  //#region src/tls/cert-manager.ts
1695
- var execFileAsync$2 = (0, node_util.promisify)(node_child_process.execFile);
1695
+ var execFileAsync$3 = (0, node_util.promisify)(node_child_process.execFile);
1696
1696
  /**
1697
1697
  * Ensure a self-signed TLS certificate exists in the given directory.
1698
1698
  * Generates one if missing. Returns paths to cert and key files.
@@ -1729,7 +1729,7 @@ async function ensureTlsCert(dataDir, options) {
1729
1729
  for (const dns of sanDns) sanParts.push(`DNS:${dns}`);
1730
1730
  for (const ip of sanIps) sanParts.push(`IP:${ip}`);
1731
1731
  const sanString = sanParts.join(",");
1732
- await execFileAsync$2("openssl", [
1732
+ await execFileAsync$3("openssl", [
1733
1733
  "req",
1734
1734
  "-x509",
1735
1735
  "-newkey",
@@ -2597,7 +2597,7 @@ var AddonEngineManager = class {
2597
2597
  };
2598
2598
  //#endregion
2599
2599
  //#region src/kernel/fs-utils.ts
2600
- var execFileAsync$1 = (0, node_util.promisify)(node_child_process.execFile);
2600
+ var execFileAsync$2 = (0, node_util.promisify)(node_child_process.execFile);
2601
2601
  /**
2602
2602
  * Ensure a directory exists (recursive).
2603
2603
  * Single source of truth — replaces scattered mkdirSync calls.
@@ -2781,7 +2781,7 @@ function ensureLibraryBuilt(packageName, packagesDir) {
2781
2781
  async function installPackageFromNpm(packageName, targetDir) {
2782
2782
  const tmpDir = await node_fs.promises.mkdtemp(node_path.join(node_os.tmpdir(), "camstack-install-"));
2783
2783
  try {
2784
- const { stdout } = await execFileAsync$1("npm", [
2784
+ const { stdout } = await execFileAsync$2("npm", [
2785
2785
  "pack",
2786
2786
  packageName,
2787
2787
  "--pack-destination",
@@ -2795,7 +2795,7 @@ async function installPackageFromNpm(packageName, targetDir) {
2795
2795
  const tgzPath = node_path.join(tmpDir, tgzFilename);
2796
2796
  const extractDir = node_path.join(tmpDir, "extracted");
2797
2797
  ensureDir(extractDir);
2798
- await execFileAsync$1("tar", [
2798
+ await execFileAsync$2("tar", [
2799
2799
  "-xzf",
2800
2800
  tgzPath,
2801
2801
  "-C",
@@ -3031,7 +3031,7 @@ var AddonManifest = class {
3031
3031
  };
3032
3032
  //#endregion
3033
3033
  //#region src/kernel/addon-installer.ts
3034
- var execFileAsync = (0, node_util.promisify)(node_child_process.execFile);
3034
+ var execFileAsync$1 = (0, node_util.promisify)(node_child_process.execFile);
3035
3035
  function parseInstallSource(value) {
3036
3036
  switch (value) {
3037
3037
  case "npm":
@@ -3318,6 +3318,7 @@ var AddonInstaller = class AddonInstaller {
3318
3318
  await node_fs.promises.writeFile(node_path.join(targetDir, "package.json"), JSON.stringify(stripBundledDeps(pkgData), null, 2));
3319
3319
  await copyDirRecursive(distDir, node_path.join(targetDir, "dist"));
3320
3320
  await copyExtraFileDirs(pkgData, sourceDir, targetDir);
3321
+ require_manifest_python_deps.copyBundledNativeModules(sourceDir, targetDir, this.logger);
3321
3322
  await node_fs.promises.writeFile(node_path.join(targetDir, ".install-source"), "local");
3322
3323
  const localPkgVersion = require_dist.asString(pkgData.version, "0.0.0");
3323
3324
  this.manifest.upsert(packageName, {
@@ -3488,7 +3489,7 @@ var AddonInstaller = class AddonInstaller {
3488
3489
  const stagingDir = node_path.join(stagingRoot, `install-${process.pid}-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`);
3489
3490
  ensureDir(stagingDir);
3490
3491
  try {
3491
- await execFileAsync("tar", [
3492
+ await execFileAsync$1("tar", [
3492
3493
  "-xzf",
3493
3494
  tgzPath,
3494
3495
  "-C",
@@ -80143,7 +80144,7 @@ var require_compression = /* @__PURE__ */ require_chunk.__commonJSMin(((exports,
80143
80144
  var { defaultsDeep } = require_lodash();
80144
80145
  var { parseByteString } = require_utils$3();
80145
80146
  var zlib = require("zlib");
80146
- var { promisify } = require("util");
80147
+ var { promisify: promisify$1 } = require("util");
80147
80148
  /**
80148
80149
  * This is a transmission compression middleware. It supports
80149
80150
  * the `deflate`, `deflateRaw` & `gzip` compression methods.
@@ -80161,16 +80162,16 @@ var require_compression = /* @__PURE__ */ require_chunk.__commonJSMin(((exports,
80161
80162
  const threshold = parseByteString(opts.threshold);
80162
80163
  switch (opts.method) {
80163
80164
  case "deflate":
80164
- compress = promisify(zlib.deflate);
80165
- decompress = promisify(zlib.inflate);
80165
+ compress = promisify$1(zlib.deflate);
80166
+ decompress = promisify$1(zlib.inflate);
80166
80167
  break;
80167
80168
  case "deflateRaw":
80168
- compress = promisify(zlib.deflateRaw);
80169
- decompress = promisify(zlib.inflateRaw);
80169
+ compress = promisify$1(zlib.deflateRaw);
80170
+ decompress = promisify$1(zlib.inflateRaw);
80170
80171
  break;
80171
80172
  case "gzip":
80172
- compress = promisify(zlib.gzip);
80173
- decompress = promisify(zlib.gunzip);
80173
+ compress = promisify$1(zlib.gzip);
80174
+ decompress = promisify$1(zlib.gunzip);
80174
80175
  break;
80175
80176
  default:
80176
80177
  /* istanbul ignore next */
@@ -93397,6 +93398,145 @@ var LifecycleJobEngine = class {
93397
93398
  }
93398
93399
  };
93399
93400
  //#endregion
93401
+ //#region src/kernel/deps/ensure-native-prebuilds.ts
93402
+ /**
93403
+ * `ensureNativePrebuilds` — the post-install native-prebuild ENSURE step the
93404
+ * shared `RootUpdateService` runs while staging a `@camstack/server` closure,
93405
+ * BEFORE its `findMissingNativePrebuilds` validator (in `@camstack/node-root`)
93406
+ * decides whether to arm the swap.
93407
+ *
93408
+ * Why this exists (Mac desktop incident, 2026-07-21): a runtime
93409
+ * `applyServerUpdate` on a packaged desktop stages the closure with
93410
+ * `npm install @camstack/server@X` under the app's BUNDLED bare Node. The one
93411
+ * TRADITIONAL (non-N-API) native, `better-sqlite3`, resolves its `.node` via
93412
+ * its `install` script `prebuild-install || node-gyp rebuild`. On a user's Mac
93413
+ * with no build toolchain (and where the auto `prebuild-install` does not
93414
+ * target the bundled Node's ABI/arch the way the DMG build's EXPLICIT
93415
+ * `prebuild-install --runtime node --target <bundled> --arch <arch>` call does)
93416
+ * that leaves the module SOURCE-ONLY → the closure has no `better-sqlite3`
93417
+ * `.node` → the validator refuses the swap ("staged closure missing native
93418
+ * prebuilds: better-sqlite3"). The docker image never hits this: its Node ABI
93419
+ * has a published prebuild the auto path fetches cleanly, and it carries a
93420
+ * build toolchain fallback.
93421
+ *
93422
+ * This mirrors the DMG build's explicit re-fetch (`scripts/stage-deps.mjs`)
93423
+ * into the runtime staging path: for each traditional native that is present
93424
+ * in the closure but missing its compiled `.node`, fetch the prebuild for the
93425
+ * RUNNING Node ABI/arch (the same Node that will load the swapped closure).
93426
+ *
93427
+ * N-API natives (`sharp`, `node-av`) are ABI-stable and ship their binaries as
93428
+ * platform SIBLING packages that npm fetches reliably with no compile step, so
93429
+ * they are not in scope here — a genuine miss there is a broken install the
93430
+ * validator should still reject, not something a prebuild re-fetch can heal.
93431
+ *
93432
+ * Injected into the update service from the construction site so the zero-dep
93433
+ * `@camstack/node-root` layer never depends on npm/@camstack/system, and the
93434
+ * fetch is unit-testable with a fake fetcher.
93435
+ */
93436
+ var execFileAsync = (0, node_util.promisify)(node_child_process.execFile);
93437
+ /** Bounded recursive `.node` scan depth inside a module dir. */
93438
+ var NATIVE_SCAN_DEPTH = 4;
93439
+ /** Timeout for a single `prebuild-install` fetch. */
93440
+ var PREBUILD_FETCH_TIMEOUT_MS = 12e4;
93441
+ /**
93442
+ * Traditional (compile-or-prebuild) natives an installed closure must carry a
93443
+ * `.node` for. Only these are ENSURE-able by a prebuild re-fetch; N-API natives
93444
+ * are excluded (see file header).
93445
+ */
93446
+ var TRADITIONAL_NATIVE_PACKAGES = ["better-sqlite3"];
93447
+ /** Bounded recursive scan for ANY `*.node` file under `dir`. */
93448
+ function hasDotNode(dir, maxDepth) {
93449
+ let entries;
93450
+ try {
93451
+ entries = node_fs.readdirSync(dir, { withFileTypes: true });
93452
+ } catch {
93453
+ return false;
93454
+ }
93455
+ for (const entry of entries) if (entry.isFile() && entry.name.endsWith(".node")) return true;
93456
+ if (maxDepth <= 0) return false;
93457
+ for (const entry of entries) if (entry.isDirectory() && hasDotNode(node_path.join(dir, entry.name), maxDepth - 1)) return true;
93458
+ return false;
93459
+ }
93460
+ /** Locate the bundled `prebuild-install` bin.js inside the staged closure. */
93461
+ function resolvePrebuildInstallBin(closureDir, moduleDir) {
93462
+ return [node_path.join(moduleDir, "node_modules", "prebuild-install", "bin.js"), node_path.join(closureDir, "node_modules", "prebuild-install", "bin.js")].find((c) => node_fs.existsSync(c)) ?? null;
93463
+ }
93464
+ /**
93465
+ * Default fetcher: run the closure's own `prebuild-install` under the CURRENT
93466
+ * Node (`process.execPath`) — no reliance on `npx`/`npm` on PATH (a packaged
93467
+ * app ships a bare Node). Explicitly targets the running ABI/arch, mirroring
93468
+ * `scripts/stage-deps.mjs`.
93469
+ */
93470
+ function makeDefaultFetch(closureDir, logger) {
93471
+ return async (moduleDir, target) => {
93472
+ const bin = resolvePrebuildInstallBin(closureDir, moduleDir);
93473
+ if (bin === null) throw new Error(`prebuild-install not found in the staged closure for ${moduleDir}`);
93474
+ logger.info("fetching native prebuild via prebuild-install", { meta: {
93475
+ moduleDir,
93476
+ bin,
93477
+ nodeVersion: target.nodeVersion,
93478
+ arch: target.arch
93479
+ } });
93480
+ await execFileAsync(process.execPath, [
93481
+ bin,
93482
+ "--runtime",
93483
+ "node",
93484
+ "--target",
93485
+ target.nodeVersion,
93486
+ "--arch",
93487
+ target.arch
93488
+ ], {
93489
+ cwd: moduleDir,
93490
+ timeout: PREBUILD_FETCH_TIMEOUT_MS
93491
+ });
93492
+ };
93493
+ }
93494
+ /**
93495
+ * Ensure every traditional native in `<closureDir>/node_modules` carries its
93496
+ * compiled `.node`, fetching the prebuild for the running ABI when missing.
93497
+ *
93498
+ * A NO-OP when nothing is missing (docker / tests) and when a native package is
93499
+ * absent from the closure. Never throws for a single package's fetch failure —
93500
+ * it logs and continues so the downstream `findMissingNativePrebuilds`
93501
+ * validator makes the final swap/abort decision. Returns the packages whose
93502
+ * prebuild was successfully fetched (for logging/tests).
93503
+ */
93504
+ async function ensureNativePrebuilds(closureDir, options) {
93505
+ const nm = node_path.join(closureDir, "node_modules");
93506
+ const target = options.target ?? {
93507
+ nodeVersion: process.versions.node,
93508
+ arch: process.arch
93509
+ };
93510
+ const packages = options.packages ?? TRADITIONAL_NATIVE_PACKAGES;
93511
+ const fetchPrebuild = options.fetchPrebuild ?? makeDefaultFetch(closureDir, options.logger);
93512
+ const fetched = [];
93513
+ for (const pkg of packages) {
93514
+ const moduleDir = node_path.join(nm, pkg);
93515
+ if (!node_fs.existsSync(moduleDir)) continue;
93516
+ if (hasDotNode(moduleDir, NATIVE_SCAN_DEPTH)) continue;
93517
+ options.logger.warn("staged closure native prebuild missing — fetching for running ABI", { meta: {
93518
+ pkg,
93519
+ moduleDir,
93520
+ nodeVersion: target.nodeVersion,
93521
+ arch: target.arch
93522
+ } });
93523
+ try {
93524
+ await fetchPrebuild(moduleDir, target);
93525
+ } catch (err) {
93526
+ options.logger.error("native prebuild fetch failed (validator will decide)", { meta: {
93527
+ pkg,
93528
+ error: (0, _camstack_types_addon.errMsg)(err)
93529
+ } });
93530
+ continue;
93531
+ }
93532
+ if (hasDotNode(moduleDir, NATIVE_SCAN_DEPTH)) {
93533
+ fetched.push(pkg);
93534
+ options.logger.info("native prebuild fetched", { meta: { pkg } });
93535
+ } else options.logger.error("native prebuild still missing after fetch", { meta: { pkg } });
93536
+ }
93537
+ return fetched;
93538
+ }
93539
+ //#endregion
93400
93540
  exports.AGENT_CAP_FWD_ACTION = require_manifest_python_deps.AGENT_CAP_FWD_ACTION;
93401
93541
  exports.AGENT_CAP_FWD_SERVICE = require_manifest_python_deps.AGENT_CAP_FWD_SERVICE;
93402
93542
  exports.AGENT_READINESS_SERVICE_NAME = AGENT_READINESS_SERVICE_NAME;
@@ -93494,6 +93634,7 @@ exports.StorageOrchestratorAddon = require_builtins_storage_orchestrator_storage
93494
93634
  exports.StorageOrchestratorService = require_builtins_storage_orchestrator_storage_orchestrator_addon.StorageOrchestratorService;
93495
93635
  exports.SystemConfigAddon = require_builtins_system_config_system_config_addon.SystemConfigAddon;
93496
93636
  exports.SystemEventBus = SystemEventBus;
93637
+ exports.TRADITIONAL_NATIVE_PACKAGES = TRADITIONAL_NATIVE_PACKAGES;
93497
93638
  exports.ToastService = ToastService;
93498
93639
  exports.UDS_NO_ROUTE_PREFIX = require_manifest_python_deps.UDS_NO_ROUTE_PREFIX;
93499
93640
  exports.UdsLocalTransportClient = require_manifest_python_deps.UdsLocalTransportClient;
@@ -93586,6 +93727,7 @@ Object.defineProperty(exports, "ensureFfmpeg", {
93586
93727
  });
93587
93728
  exports.ensureLibraryBuilt = ensureLibraryBuilt;
93588
93729
  exports.ensureModel = require_model_download_service.ensureModel;
93730
+ exports.ensureNativePrebuilds = ensureNativePrebuilds;
93589
93731
  Object.defineProperty(exports, "ensurePython", {
93590
93732
  enumerable: true,
93591
93733
  get: function() {
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { At as EventCategory$1, Dt as resolveCapMount, Et as readinessKey, F as kebabToCamel, I as lifecycleJobSchema, K as procedureAuthKey, M as isCollectionArrayMethod, N as isObjectInput, O as extractNestedAddonId, Ot as scopeKey, P as isVoidInput, Tt as parseJsonUnknown$1, U as objectInputDeclaresAddonId, _t as asString$1, ct as DEVICE_STATUS_METHOD, ft as ReadinessRegistry, gt as asNumber, ht as asJsonObject$1, it as errMsg$1, j as isArrayOutputSchema, o as METHOD_ACCESS_MAP, ot as DATAPLANE_SECRET_HEADER$1, p as addonSettingsCapability, pt as ReadinessTimeoutError, s as RUNTIME_DEFAULTS, st as DEVICE_SETTINGS_CONTRIBUTION_METHODS, t as ALL_CAPABILITY_DEFINITIONS, vt as createEvent, wt as parseJsonObject, xt as expandCapMethods, yt as emitDownForOwnedCaps, z as looseSchema } from "./dist-DTTTjPCL.mjs";
1
+ import { At as EventCategory$1, Dt as resolveCapMount, Et as readinessKey, F as kebabToCamel, I as lifecycleJobSchema, K as procedureAuthKey, M as isCollectionArrayMethod, N as isObjectInput, O as extractNestedAddonId, Ot as scopeKey, P as isVoidInput, Tt as parseJsonUnknown$1, U as objectInputDeclaresAddonId, _t as asString$1, ct as DEVICE_STATUS_METHOD, ft as ReadinessRegistry, gt as asNumber, ht as asJsonObject$1, it as errMsg$1, j as isArrayOutputSchema, o as METHOD_ACCESS_MAP, ot as DATAPLANE_SECRET_HEADER$1, p as addonSettingsCapability, pt as ReadinessTimeoutError, s as RUNTIME_DEFAULTS, st as DEVICE_SETTINGS_CONTRIBUTION_METHODS, t as ALL_CAPABILITY_DEFINITIONS, vt as createEvent, wt as parseJsonObject, xt as expandCapMethods, yt as emitDownForOwnedCaps, z as looseSchema } from "./dist-72yufD8v.mjs";
2
2
  import { a as downloadModel, c as getModelFilePath, d as contentTypeFor, f as createAuthenticatedFileServer, h as resolveFilePath, i as downloadFile, l as isModelDownloaded, m as parseTokenizedUrl, n as collectModelFiles, o as ensureModel, p as parseRangeHeader, r as deleteModelFromDisk, s as fetchJson, t as ModelDownloadService, u as createFileDataPlaneHandler } from "./model-download-service-Cp9f4dk6.mjs";
3
- import { $ as buildNativeCapProxy, A as createHubCapForwardService, B as AGENT_CAP_FWD_ACTION, C as brokerTransportLink, Ct as createAddonDataPlaneFacility, D as localProviderLink, E as ipcParentLink, F as createUdsLogger, G as callWithServiceDiscovery, H as CapRouteResolver, I as createUdsLoggerWithControl, J as UdsLocalTransportServer, K as createLocalTransport, L as LocalChildClient, M as createUdsEventBridge, N as createUdsEventBus, O as HUB_CAP_FWD_ACTION, P as udsChildLogToWorkerEntry, Q as encodeFrame, R as LocalChildRegistry, S as brokerCallForCap, St as resolveAddonClass, T as ipcChildLink, U as CapRouteError, V as AGENT_CAP_FWD_SERVICE, W as classifyCapRoute, X as localEndpointPath, Y as SocketChannel, Z as FrameDecoder, _ as createKernelHwAccel, _t as CapabilityHandle, a as getWorkerDeviceRegistry, b as __resetCapUsageRegistryForTests, bt as resolveNpmInvocation, c as setHubConnected, ct as NATIVE_PROVIDER_SERVICE_INFIX, d as getBrokerEventBus, dt as capBareAction, et as buildUdsNativeCapProxy, f as getMoleculerEventStats, ft as capServiceName, g as AddonDepsManager, gt as DeviceRegistry, h as subscribePassthrough, ht as serializeTypedArrays, i as createUdsAddonContext, it as mountNativeCapService, j as createParentUnownedCallHandler, k as HUB_CAP_FWD_SERVICE, l as EVENT_TOPIC_PREFIX, lt as capActionName, m as setNodeEventInterest, mt as deserializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as createAddonService, p as registerEventBusService, pt as parseCapAction, q as UdsLocalTransportClient, r as createAddonContext, s as getOrInitReadinessRegistryForClient, st as validateProviderRegistrations, t as installManifestPythonDeps, tt as createBrokerDeviceManagerApi, u as clusterEventTopic, ut as capActionSuffix, v as resolveHwAccel, vt as CapabilityUnavailableError, w as buildLinkChain, x as getCapUsageRegistry, xt as runNpm, y as CapUsageRegistry, yt as installManifestNativeDeps, z as UDS_NO_ROUTE_PREFIX } from "./manifest-python-deps-s_-uULmp.mjs";
3
+ import { $ as buildNativeCapProxy, A as createHubCapForwardService, B as AGENT_CAP_FWD_ACTION, C as brokerTransportLink, Ct as resolveAddonClass, D as localProviderLink, E as ipcParentLink, F as createUdsLogger, G as callWithServiceDiscovery, H as CapRouteResolver, I as createUdsLoggerWithControl, J as UdsLocalTransportServer, K as createLocalTransport, L as LocalChildClient, M as createUdsEventBridge, N as createUdsEventBus, O as HUB_CAP_FWD_ACTION, P as udsChildLogToWorkerEntry, Q as encodeFrame, R as LocalChildRegistry, S as brokerCallForCap, St as runNpm, T as ipcChildLink, U as CapRouteError, V as AGENT_CAP_FWD_SERVICE, W as classifyCapRoute, X as localEndpointPath, Y as SocketChannel, Z as FrameDecoder, _ as createKernelHwAccel, _t as CapabilityHandle, a as getWorkerDeviceRegistry, b as __resetCapUsageRegistryForTests, bt as installManifestNativeDeps, c as setHubConnected, ct as NATIVE_PROVIDER_SERVICE_INFIX, d as getBrokerEventBus, dt as capBareAction, et as buildUdsNativeCapProxy, f as getMoleculerEventStats, ft as capServiceName, g as AddonDepsManager, gt as DeviceRegistry, h as subscribePassthrough, ht as serializeTypedArrays, i as createUdsAddonContext, it as mountNativeCapService, j as createParentUnownedCallHandler, k as HUB_CAP_FWD_SERVICE, l as EVENT_TOPIC_PREFIX, lt as capActionName, m as setNodeEventInterest, mt as deserializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as createAddonService, p as registerEventBusService, pt as parseCapAction, q as UdsLocalTransportClient, r as createAddonContext, s as getOrInitReadinessRegistryForClient, st as validateProviderRegistrations, t as installManifestPythonDeps, tt as createBrokerDeviceManagerApi, u as clusterEventTopic, ut as capActionSuffix, v as resolveHwAccel, vt as CapabilityUnavailableError, w as buildLinkChain, wt as createAddonDataPlaneFacility, x as getCapUsageRegistry, xt as resolveNpmInvocation, y as CapUsageRegistry, yt as copyBundledNativeModules, z as UDS_NO_ROUTE_PREFIX } from "./manifest-python-deps-6__QF75g.mjs";
4
4
  import { n as getSinglePidStats, t as getPidStats } from "./resource-monitor-Le3l0qS2.mjs";
5
5
  import { FilesystemStorageAddon, t as FilesystemStorageProvider } from "./builtins/sqlite-storage/filesystem-storage.addon.mjs";
6
6
  import { SqliteSettingsAddon, t as SqliteSettingsBackend } from "./builtins/sqlite-storage/sqlite-settings.addon.mjs";
@@ -29,7 +29,7 @@ import { accessSync, constants, existsSync, mkdirSync, readFileSync } from "node
29
29
  import * as path$39 from "node:path";
30
30
  import { dirname, isAbsolute, join, posix, resolve, win32 } from "node:path";
31
31
  import { X509Certificate, createHash, randomUUID, timingSafeEqual } from "node:crypto";
32
- import { asJsonObject, parseJsonUnknown } from "@camstack/types/addon";
32
+ import { asJsonObject, errMsg, parseJsonUnknown } from "@camstack/types/addon";
33
33
  import { execFile, spawn } from "node:child_process";
34
34
  import * as util$10 from "node:util";
35
35
  import { promisify } from "node:util";
@@ -176,7 +176,7 @@ function proxyToUpstream(opts) {
176
176
  }
177
177
  //#endregion
178
178
  //#region src/python/python-env-manager.ts
179
- var execFileAsync$3 = promisify(execFile);
179
+ var execFileAsync$4 = promisify(execFile);
180
180
  var PythonEnvManager = class {
181
181
  venvPath;
182
182
  cachedProbe = null;
@@ -186,12 +186,12 @@ var PythonEnvManager = class {
186
186
  async probe() {
187
187
  if (this.cachedProbe) return this.cachedProbe;
188
188
  for (const cmd of ["python3", "python"]) try {
189
- const { stdout } = await execFileAsync$3(cmd, ["--version"]);
189
+ const { stdout } = await execFileAsync$4(cmd, ["--version"]);
190
190
  const version = stdout.trim().replace("Python ", "");
191
191
  const major = parseInt(version.split(".")[0] ?? "0", 10);
192
192
  const minor = parseInt(version.split(".")[1] ?? "0", 10);
193
193
  if (major < 3 || major === 3 && minor < 10) continue;
194
- const { stdout: pathOut } = await execFileAsync$3(cmd, ["-c", "import sys; print(sys.executable)"]);
194
+ const { stdout: pathOut } = await execFileAsync$4(cmd, ["-c", "import sys; print(sys.executable)"]);
195
195
  this.cachedProbe = {
196
196
  available: true,
197
197
  version,
@@ -207,13 +207,13 @@ var PythonEnvManager = class {
207
207
  async ensure(options) {
208
208
  const probe = await this.probe();
209
209
  if (!probe.available || !probe.path) throw new Error("Python 3.10+ is required but not found on this system");
210
- if (!fs$17.existsSync(path$39.join(this.venvPath, "bin", "python"))) await execFileAsync$3(probe.path, [
210
+ if (!fs$17.existsSync(path$39.join(this.venvPath, "bin", "python"))) await execFileAsync$4(probe.path, [
211
211
  "-m",
212
212
  "venv",
213
213
  this.venvPath
214
214
  ]);
215
215
  const venvPython = path$39.join(this.venvPath, "bin", "python");
216
- if (options.packages.length > 0) await execFileAsync$3(venvPython, [
216
+ if (options.packages.length > 0) await execFileAsync$4(venvPython, [
217
217
  "-m",
218
218
  "pip",
219
219
  "install",
@@ -1684,7 +1684,7 @@ function matchPath(pattern, path) {
1684
1684
  }
1685
1685
  //#endregion
1686
1686
  //#region src/tls/cert-manager.ts
1687
- var execFileAsync$2 = promisify(execFile);
1687
+ var execFileAsync$3 = promisify(execFile);
1688
1688
  /**
1689
1689
  * Ensure a self-signed TLS certificate exists in the given directory.
1690
1690
  * Generates one if missing. Returns paths to cert and key files.
@@ -1721,7 +1721,7 @@ async function ensureTlsCert(dataDir, options) {
1721
1721
  for (const dns of sanDns) sanParts.push(`DNS:${dns}`);
1722
1722
  for (const ip of sanIps) sanParts.push(`IP:${ip}`);
1723
1723
  const sanString = sanParts.join(",");
1724
- await execFileAsync$2("openssl", [
1724
+ await execFileAsync$3("openssl", [
1725
1725
  "req",
1726
1726
  "-x509",
1727
1727
  "-newkey",
@@ -2589,7 +2589,7 @@ var AddonEngineManager = class {
2589
2589
  };
2590
2590
  //#endregion
2591
2591
  //#region src/kernel/fs-utils.ts
2592
- var execFileAsync$1 = promisify(execFile);
2592
+ var execFileAsync$2 = promisify(execFile);
2593
2593
  /**
2594
2594
  * Ensure a directory exists (recursive).
2595
2595
  * Single source of truth — replaces scattered mkdirSync calls.
@@ -2773,7 +2773,7 @@ function ensureLibraryBuilt(packageName, packagesDir) {
2773
2773
  async function installPackageFromNpm(packageName, targetDir) {
2774
2774
  const tmpDir = await fs$17.promises.mkdtemp(path$39.join(os$18.tmpdir(), "camstack-install-"));
2775
2775
  try {
2776
- const { stdout } = await execFileAsync$1("npm", [
2776
+ const { stdout } = await execFileAsync$2("npm", [
2777
2777
  "pack",
2778
2778
  packageName,
2779
2779
  "--pack-destination",
@@ -2787,7 +2787,7 @@ async function installPackageFromNpm(packageName, targetDir) {
2787
2787
  const tgzPath = path$39.join(tmpDir, tgzFilename);
2788
2788
  const extractDir = path$39.join(tmpDir, "extracted");
2789
2789
  ensureDir(extractDir);
2790
- await execFileAsync$1("tar", [
2790
+ await execFileAsync$2("tar", [
2791
2791
  "-xzf",
2792
2792
  tgzPath,
2793
2793
  "-C",
@@ -3023,7 +3023,7 @@ var AddonManifest = class {
3023
3023
  };
3024
3024
  //#endregion
3025
3025
  //#region src/kernel/addon-installer.ts
3026
- var execFileAsync = promisify(execFile);
3026
+ var execFileAsync$1 = promisify(execFile);
3027
3027
  function parseInstallSource(value) {
3028
3028
  switch (value) {
3029
3029
  case "npm":
@@ -3310,6 +3310,7 @@ var AddonInstaller = class AddonInstaller {
3310
3310
  await fs$17.promises.writeFile(path$39.join(targetDir, "package.json"), JSON.stringify(stripBundledDeps(pkgData), null, 2));
3311
3311
  await copyDirRecursive(distDir, path$39.join(targetDir, "dist"));
3312
3312
  await copyExtraFileDirs(pkgData, sourceDir, targetDir);
3313
+ copyBundledNativeModules(sourceDir, targetDir, this.logger);
3313
3314
  await fs$17.promises.writeFile(path$39.join(targetDir, ".install-source"), "local");
3314
3315
  const localPkgVersion = asString$1(pkgData.version, "0.0.0");
3315
3316
  this.manifest.upsert(packageName, {
@@ -3480,7 +3481,7 @@ var AddonInstaller = class AddonInstaller {
3480
3481
  const stagingDir = path$39.join(stagingRoot, `install-${process.pid}-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`);
3481
3482
  ensureDir(stagingDir);
3482
3483
  try {
3483
- await execFileAsync("tar", [
3484
+ await execFileAsync$1("tar", [
3484
3485
  "-xzf",
3485
3486
  tgzPath,
3486
3487
  "-C",
@@ -93389,4 +93390,143 @@ var LifecycleJobEngine = class {
93389
93390
  }
93390
93391
  };
93391
93392
  //#endregion
93392
- export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AGENT_READINESS_SERVICE_NAME, ALL_CAPABILITY_DEFINITIONS, 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, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LifecycleJobEngine, LifecycleStateMachine, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, METHOD_ACCESS_MAP, 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, addonSettingsCapability, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildStorageLocationRegistry, buildUdsNativeCapProxy, builderMountedCapNames, callRegisterNodeWithRetry, callWithServiceDiscovery, capActionName, capActionSuffix, capBareAction, capServiceName, classifyCapRoute, clearPendingRestart, clusterEventTopic, clusterSecretMatches, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonDataPlaneFacility, createAddonService, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCoreCapService, createFileDataPlaneHandler, createHubCapForwardService, createHubService, 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, expandCapMethods, fetchJson, findInPath, formatLogLine, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getModelFilePath, getMoleculerEventStats, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hashClusterSecret, installManifestNativeDeps, installManifestPythonDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcChildLink, ipcParentLink, isAddonDeploySource, isArrayOutputSchema, isClusterSecretMismatchError, isCollectionArrayMethod, isInfraCapability, isModelDownloaded, isSourceNewer, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, parseCapAction, parseRangeHeader, parseTokenizedUrl, proxyToUpstream, readPendingRestart, readinessKey, registerEventBusService, resolveFilePath, resolveHwAccel, resolveNpmInvocation, runNpm, scheduleSelfRestart, scopeKey, scopesAllowDeviceCap, serializeTypedArrays, setHubConnected, setNodeEventInterest, stripCamstackDeps, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, writePendingRestart };
93393
+ //#region src/kernel/deps/ensure-native-prebuilds.ts
93394
+ /**
93395
+ * `ensureNativePrebuilds` — the post-install native-prebuild ENSURE step the
93396
+ * shared `RootUpdateService` runs while staging a `@camstack/server` closure,
93397
+ * BEFORE its `findMissingNativePrebuilds` validator (in `@camstack/node-root`)
93398
+ * decides whether to arm the swap.
93399
+ *
93400
+ * Why this exists (Mac desktop incident, 2026-07-21): a runtime
93401
+ * `applyServerUpdate` on a packaged desktop stages the closure with
93402
+ * `npm install @camstack/server@X` under the app's BUNDLED bare Node. The one
93403
+ * TRADITIONAL (non-N-API) native, `better-sqlite3`, resolves its `.node` via
93404
+ * its `install` script `prebuild-install || node-gyp rebuild`. On a user's Mac
93405
+ * with no build toolchain (and where the auto `prebuild-install` does not
93406
+ * target the bundled Node's ABI/arch the way the DMG build's EXPLICIT
93407
+ * `prebuild-install --runtime node --target <bundled> --arch <arch>` call does)
93408
+ * that leaves the module SOURCE-ONLY → the closure has no `better-sqlite3`
93409
+ * `.node` → the validator refuses the swap ("staged closure missing native
93410
+ * prebuilds: better-sqlite3"). The docker image never hits this: its Node ABI
93411
+ * has a published prebuild the auto path fetches cleanly, and it carries a
93412
+ * build toolchain fallback.
93413
+ *
93414
+ * This mirrors the DMG build's explicit re-fetch (`scripts/stage-deps.mjs`)
93415
+ * into the runtime staging path: for each traditional native that is present
93416
+ * in the closure but missing its compiled `.node`, fetch the prebuild for the
93417
+ * RUNNING Node ABI/arch (the same Node that will load the swapped closure).
93418
+ *
93419
+ * N-API natives (`sharp`, `node-av`) are ABI-stable and ship their binaries as
93420
+ * platform SIBLING packages that npm fetches reliably with no compile step, so
93421
+ * they are not in scope here — a genuine miss there is a broken install the
93422
+ * validator should still reject, not something a prebuild re-fetch can heal.
93423
+ *
93424
+ * Injected into the update service from the construction site so the zero-dep
93425
+ * `@camstack/node-root` layer never depends on npm/@camstack/system, and the
93426
+ * fetch is unit-testable with a fake fetcher.
93427
+ */
93428
+ var execFileAsync = promisify(execFile);
93429
+ /** Bounded recursive `.node` scan depth inside a module dir. */
93430
+ var NATIVE_SCAN_DEPTH = 4;
93431
+ /** Timeout for a single `prebuild-install` fetch. */
93432
+ var PREBUILD_FETCH_TIMEOUT_MS = 12e4;
93433
+ /**
93434
+ * Traditional (compile-or-prebuild) natives an installed closure must carry a
93435
+ * `.node` for. Only these are ENSURE-able by a prebuild re-fetch; N-API natives
93436
+ * are excluded (see file header).
93437
+ */
93438
+ var TRADITIONAL_NATIVE_PACKAGES = ["better-sqlite3"];
93439
+ /** Bounded recursive scan for ANY `*.node` file under `dir`. */
93440
+ function hasDotNode(dir, maxDepth) {
93441
+ let entries;
93442
+ try {
93443
+ entries = fs$17.readdirSync(dir, { withFileTypes: true });
93444
+ } catch {
93445
+ return false;
93446
+ }
93447
+ for (const entry of entries) if (entry.isFile() && entry.name.endsWith(".node")) return true;
93448
+ if (maxDepth <= 0) return false;
93449
+ for (const entry of entries) if (entry.isDirectory() && hasDotNode(path$39.join(dir, entry.name), maxDepth - 1)) return true;
93450
+ return false;
93451
+ }
93452
+ /** Locate the bundled `prebuild-install` bin.js inside the staged closure. */
93453
+ function resolvePrebuildInstallBin(closureDir, moduleDir) {
93454
+ return [path$39.join(moduleDir, "node_modules", "prebuild-install", "bin.js"), path$39.join(closureDir, "node_modules", "prebuild-install", "bin.js")].find((c) => fs$17.existsSync(c)) ?? null;
93455
+ }
93456
+ /**
93457
+ * Default fetcher: run the closure's own `prebuild-install` under the CURRENT
93458
+ * Node (`process.execPath`) — no reliance on `npx`/`npm` on PATH (a packaged
93459
+ * app ships a bare Node). Explicitly targets the running ABI/arch, mirroring
93460
+ * `scripts/stage-deps.mjs`.
93461
+ */
93462
+ function makeDefaultFetch(closureDir, logger) {
93463
+ return async (moduleDir, target) => {
93464
+ const bin = resolvePrebuildInstallBin(closureDir, moduleDir);
93465
+ if (bin === null) throw new Error(`prebuild-install not found in the staged closure for ${moduleDir}`);
93466
+ logger.info("fetching native prebuild via prebuild-install", { meta: {
93467
+ moduleDir,
93468
+ bin,
93469
+ nodeVersion: target.nodeVersion,
93470
+ arch: target.arch
93471
+ } });
93472
+ await execFileAsync(process.execPath, [
93473
+ bin,
93474
+ "--runtime",
93475
+ "node",
93476
+ "--target",
93477
+ target.nodeVersion,
93478
+ "--arch",
93479
+ target.arch
93480
+ ], {
93481
+ cwd: moduleDir,
93482
+ timeout: PREBUILD_FETCH_TIMEOUT_MS
93483
+ });
93484
+ };
93485
+ }
93486
+ /**
93487
+ * Ensure every traditional native in `<closureDir>/node_modules` carries its
93488
+ * compiled `.node`, fetching the prebuild for the running ABI when missing.
93489
+ *
93490
+ * A NO-OP when nothing is missing (docker / tests) and when a native package is
93491
+ * absent from the closure. Never throws for a single package's fetch failure —
93492
+ * it logs and continues so the downstream `findMissingNativePrebuilds`
93493
+ * validator makes the final swap/abort decision. Returns the packages whose
93494
+ * prebuild was successfully fetched (for logging/tests).
93495
+ */
93496
+ async function ensureNativePrebuilds(closureDir, options) {
93497
+ const nm = path$39.join(closureDir, "node_modules");
93498
+ const target = options.target ?? {
93499
+ nodeVersion: process.versions.node,
93500
+ arch: process.arch
93501
+ };
93502
+ const packages = options.packages ?? TRADITIONAL_NATIVE_PACKAGES;
93503
+ const fetchPrebuild = options.fetchPrebuild ?? makeDefaultFetch(closureDir, options.logger);
93504
+ const fetched = [];
93505
+ for (const pkg of packages) {
93506
+ const moduleDir = path$39.join(nm, pkg);
93507
+ if (!fs$17.existsSync(moduleDir)) continue;
93508
+ if (hasDotNode(moduleDir, NATIVE_SCAN_DEPTH)) continue;
93509
+ options.logger.warn("staged closure native prebuild missing — fetching for running ABI", { meta: {
93510
+ pkg,
93511
+ moduleDir,
93512
+ nodeVersion: target.nodeVersion,
93513
+ arch: target.arch
93514
+ } });
93515
+ try {
93516
+ await fetchPrebuild(moduleDir, target);
93517
+ } catch (err) {
93518
+ options.logger.error("native prebuild fetch failed (validator will decide)", { meta: {
93519
+ pkg,
93520
+ error: errMsg(err)
93521
+ } });
93522
+ continue;
93523
+ }
93524
+ if (hasDotNode(moduleDir, NATIVE_SCAN_DEPTH)) {
93525
+ fetched.push(pkg);
93526
+ options.logger.info("native prebuild fetched", { meta: { pkg } });
93527
+ } else options.logger.error("native prebuild still missing after fetch", { meta: { pkg } });
93528
+ }
93529
+ return fetched;
93530
+ }
93531
+ //#endregion
93532
+ export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AGENT_READINESS_SERVICE_NAME, ALL_CAPABILITY_DEFINITIONS, 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, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LifecycleJobEngine, LifecycleStateMachine, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, METHOD_ACCESS_MAP, 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, TRADITIONAL_NATIVE_PACKAGES, ToastService, UDS_NO_ROUTE_PREFIX, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, __resetCapUsageRegistryForTests, adaptBrokerToCluster, addonSettingsCapability, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildStorageLocationRegistry, buildUdsNativeCapProxy, builderMountedCapNames, callRegisterNodeWithRetry, callWithServiceDiscovery, capActionName, capActionSuffix, capBareAction, capServiceName, classifyCapRoute, clearPendingRestart, clusterEventTopic, clusterSecretMatches, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonDataPlaneFacility, createAddonService, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCoreCapService, createFileDataPlaneHandler, createHubCapForwardService, createHubService, 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, ensureNativePrebuilds, ensurePython, ensureTlsCert, expandCapMethods, fetchJson, findInPath, formatLogLine, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getModelFilePath, getMoleculerEventStats, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hashClusterSecret, installManifestNativeDeps, installManifestPythonDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcChildLink, ipcParentLink, isAddonDeploySource, isArrayOutputSchema, isClusterSecretMismatchError, isCollectionArrayMethod, isInfraCapability, isModelDownloaded, isSourceNewer, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, parseCapAction, parseRangeHeader, parseTokenizedUrl, proxyToUpstream, readPendingRestart, readinessKey, registerEventBusService, resolveFilePath, resolveHwAccel, resolveNpmInvocation, runNpm, scheduleSelfRestart, scopeKey, scopesAllowDeviceCap, serializeTypedArrays, setHubConnected, setNodeEventInterest, stripCamstackDeps, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, writePendingRestart };
@@ -0,0 +1,36 @@
1
+ import { IScopedLogger } from '@camstack/types';
2
+ /**
3
+ * Traditional (compile-or-prebuild) natives an installed closure must carry a
4
+ * `.node` for. Only these are ENSURE-able by a prebuild re-fetch; N-API natives
5
+ * are excluded (see file header).
6
+ */
7
+ export declare const TRADITIONAL_NATIVE_PACKAGES: readonly string[];
8
+ /** The running Node ABI/arch the fetched prebuild must match. */
9
+ export interface PrebuildTarget {
10
+ /** Node version, e.g. `process.versions.node` (`24.16.0`). */
11
+ readonly nodeVersion: string;
12
+ /** CPU arch, e.g. `process.arch` (`arm64` | `x64`). */
13
+ readonly arch: string;
14
+ }
15
+ /** Fetch a `<moduleDir>`'s prebuild for `target`. Test seam. */
16
+ export type PrebuildFetchFn = (moduleDir: string, target: PrebuildTarget) => Promise<void>;
17
+ export interface EnsureNativePrebuildsOptions {
18
+ readonly logger: IScopedLogger;
19
+ /** Defaults to the running process (`process.versions.node` / `process.arch`). */
20
+ readonly target?: PrebuildTarget;
21
+ /** Override the native package set (tests). */
22
+ readonly packages?: readonly string[];
23
+ /** Override the fetcher (tests). Production uses the bundled `prebuild-install`. */
24
+ readonly fetchPrebuild?: PrebuildFetchFn;
25
+ }
26
+ /**
27
+ * Ensure every traditional native in `<closureDir>/node_modules` carries its
28
+ * compiled `.node`, fetching the prebuild for the running ABI when missing.
29
+ *
30
+ * A NO-OP when nothing is missing (docker / tests) and when a native package is
31
+ * absent from the closure. Never throws for a single package's fetch failure —
32
+ * it logs and continues so the downstream `findMissingNativePrebuilds`
33
+ * validator makes the final swap/abort decision. Returns the packages whose
34
+ * prebuild was successfully fetched (for logging/tests).
35
+ */
36
+ export declare function ensureNativePrebuilds(closureDir: string, options: EnsureNativePrebuildsOptions): Promise<readonly string[]>;