@camstack/system 1.2.416 → 1.2.418

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 (95) hide show
  1. package/dist/addon-runner.js +9969 -27
  2. package/dist/addon-runner.mjs +9930 -9
  3. package/dist/addon-utils.js +19 -20
  4. package/dist/addon-utils.mjs +1 -2
  5. package/dist/auth/auth-audit-log.d.ts +1 -1
  6. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  7. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  8. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  9. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  10. package/dist/builtins/alerts/alerts.addon.js +1 -1
  11. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  12. package/dist/builtins/autotrack/index.js +1 -1
  13. package/dist/builtins/autotrack/index.mjs +1 -1
  14. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
  15. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
  16. package/dist/builtins/calendars/calendars.addon.js +1 -1
  17. package/dist/builtins/calendars/calendars.addon.mjs +1 -1
  18. package/dist/builtins/camera-grid/index.js +1 -1
  19. package/dist/builtins/camera-grid/index.mjs +1 -1
  20. package/dist/builtins/composer/composer.addon.js +2 -2
  21. package/dist/builtins/composer/composer.addon.mjs +2 -2
  22. package/dist/builtins/console-logging/index.js +1 -1
  23. package/dist/builtins/console-logging/index.mjs +1 -1
  24. package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
  25. package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
  26. package/dist/builtins/device-manager/device-manager.addon.js +2 -2
  27. package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
  28. package/dist/builtins/hub-forwarder/index.js +1 -1
  29. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  30. package/dist/builtins/keychain/index.js +7 -9
  31. package/dist/builtins/keychain/index.mjs +7 -9
  32. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  33. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  34. package/dist/builtins/local-auth/local-auth.addon.js +5 -3
  35. package/dist/builtins/local-auth/local-auth.addon.mjs +5 -3
  36. package/dist/builtins/local-network/local-network.addon.js +2 -2
  37. package/dist/builtins/local-network/local-network.addon.mjs +2 -2
  38. package/dist/builtins/loki-logging/index.js +1 -1
  39. package/dist/builtins/loki-logging/index.mjs +1 -1
  40. package/dist/builtins/native-metrics/native-metrics.addon.js +102 -10
  41. package/dist/builtins/native-metrics/native-metrics.addon.mjs +92 -4
  42. package/dist/builtins/platform-probe/amd-npu.d.ts +6 -0
  43. package/dist/builtins/platform-probe/index.js +317 -19
  44. package/dist/builtins/platform-probe/index.mjs +318 -20
  45. package/dist/builtins/platform-probe/platform-scorer.d.ts +4 -0
  46. package/dist/builtins/platform-probe/windows-hardware.d.ts +77 -0
  47. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  48. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  49. package/dist/builtins/snapshot/index.js +1 -1
  50. package/dist/builtins/snapshot/index.mjs +1 -1
  51. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  52. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  53. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
  54. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
  55. package/dist/builtins/storage-orchestrator/index.mjs +1 -1
  56. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +83 -3
  57. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +79 -3
  58. package/dist/builtins/system-config/system-config.addon.js +2 -2
  59. package/dist/builtins/system-config/system-config.addon.mjs +2 -2
  60. package/dist/builtins/winston-logging/index.js +1 -1
  61. package/dist/builtins/winston-logging/index.mjs +1 -1
  62. package/dist/{composition-sources-DEZqZLPT.mjs → composition-sources-0cPw9E0M.mjs} +1 -1
  63. package/dist/{composition-sources-DBcOVpGn.js → composition-sources-BVjuMvpb.js} +1 -1
  64. package/dist/{constants-C4jZO_qO.js → constants-Aj0OBqlt.js} +1 -1
  65. package/dist/{constants-BSBtmzm3.mjs → constants-C8T7u1_Z.mjs} +1 -1
  66. package/dist/{event-loop-stall-monitor-LBZskC1S.mjs → custom-action-registry-BQnbN0DP.mjs} +57 -2
  67. package/dist/{event-loop-stall-monitor-E2hFvhDg.js → custom-action-registry-Bf_YnagS.js} +64 -3
  68. package/dist/{dist-DxiDI8hZ.js → dist-DVUg8e1T.js} +56 -182
  69. package/dist/{dist-DwE9yHdk.mjs → dist-DlmdESNT.mjs} +57 -153
  70. package/dist/index.js +22901 -10154
  71. package/dist/index.mjs +22616 -9869
  72. package/dist/{jwt-signing-key-DLbjTIuA.mjs → jwt-signing-key-CGg61A5v.mjs} +1 -1
  73. package/dist/{jwt-signing-key-CsC-FxSm.js → jwt-signing-key-Jyu81jZR.js} +1 -1
  74. package/dist/kernel/moleculer/broker-factory.d.ts +2 -4
  75. package/dist/kernel/transport/local-child-registry.d.ts +1 -1
  76. package/dist/logging/log-redactor.d.ts +1 -1
  77. package/dist/{resource-monitor-B2WZ8_q9.mjs → resource-monitor-Di9daRwI.mjs} +1 -1
  78. package/dist/{resource-monitor-BgWGRxN5.js → resource-monitor-mio9dSCT.js} +5 -5
  79. package/dist/{restore-archive-BtKjaVua.js → restore-archive-Bq5PpQ-H.js} +1 -1
  80. package/dist/{restore-archive-CImzbuRo.mjs → restore-archive-DVo5ooBt.mjs} +1 -1
  81. package/dist/{retired-settings-keys-Cl1tnkmq.js → retired-settings-keys-CihMX6h9.js} +1 -1
  82. package/dist/{retired-settings-keys-D1WsCdUY.mjs → retired-settings-keys-k_XuC-Mt.mjs} +1 -1
  83. package/dist/{tls-C0TRPfqc.js → tls-BgImdxCO.js} +4 -11
  84. package/dist/{tls-D-2dPY-5.mjs → tls-CaOLZ09W.mjs} +5 -12
  85. package/package.json +2 -2
  86. package/dist/amd-npu-B-QyyMyF.js +0 -53
  87. package/dist/amd-npu-Db_SoSuL.mjs +0 -52
  88. package/dist/child-cap-dispatch-B87B0FrC.js +0 -13986
  89. package/dist/child-cap-dispatch-CmfT-OR2.mjs +0 -12916
  90. package/dist/custom-action-registry-B4Cf4O_X.mjs +0 -57
  91. package/dist/custom-action-registry-acBY3mHA.js +0 -62
  92. package/dist/hub-cap-forward-CDiN1p98.mjs +0 -78
  93. package/dist/hub-cap-forward-W8oEm4ME.js +0 -101
  94. package/dist/proc-stat-CbC55Kqi.mjs +0 -92
  95. package/dist/proc-stat-DL-WUOhl.js +0 -127
@@ -1,5 +1,5 @@
1
- import { o as __toESM } from "../../chunk-CNf5ZN-e.mjs";
2
- import { Et as enumerateInferenceDevices, Mr as emitReadiness, Nn as scoreRuntimes, _n as platformProbeCapability, ai as EventCategory, fr as errMsg, pr as BaseAddon } from "../../dist-DwE9yHdk.mjs";
1
+ import { o as __toESM, r as __exportAll } from "../../chunk-CNf5ZN-e.mjs";
2
+ import { Ct as enumerateInferenceDevices, On as scoreRuntimes, Or as emitReadiness, cr as BaseAddon, ei as EventCategory, fn as platformProbeCapability, sr as errMsg } from "../../dist-DlmdESNT.mjs";
3
3
  import * as os from "node:os";
4
4
  import * as fs from "node:fs";
5
5
  import { execFile } from "node:child_process";
@@ -53,7 +53,257 @@ function classifyCoralAccelerator(fsx) {
53
53
  return null;
54
54
  }
55
55
  //#endregion
56
+ //#region src/builtins/platform-probe/amd-npu.ts
57
+ var amd_npu_exports = /* @__PURE__ */ __exportAll({
58
+ classifyAmdNpu: () => classifyAmdNpu,
59
+ xdnaInfoForDevice: () => xdnaInfoForDevice
60
+ });
61
+ var ACCEL_CLASS = "/sys/class/accel";
62
+ var ACCEL_DEV = "/dev/accel";
63
+ var AMD_PCI_VENDOR = "0x1022";
64
+ /** Phoenix / Hawk Point XDNA1. */
65
+ var XDNA1_DEVICES = new Set(["0x1502"]);
66
+ /** Strix / Krackan XDNA2. */
67
+ var XDNA2_DEVICES = new Set(["0x17f0"]);
68
+ function normalizePciId(raw) {
69
+ const t = raw.trim().toLowerCase();
70
+ if (t.startsWith("0x")) return t;
71
+ if (t.length > 0 && [...t].every((c) => "0123456789abcdef".includes(c))) return "0x" + t;
72
+ return t;
73
+ }
74
+ function hasAccelCharDevice(fsx) {
75
+ if (fsx.listDir(ACCEL_DEV).some((n) => n.startsWith("accel"))) return true;
76
+ return fsx.exists("/dev/accel/accel0");
77
+ }
78
+ /**
79
+ * Detect an AMD XDNA NPU and report it as **present only**.
80
+ *
81
+ * Inference is NOT offered until P2 (Ryzen AI on Linux is Strix-first;
82
+ * Phoenix is not a production path today). The probe still names the
83
+ * generation so the UI and fleet census can show the hardware.
84
+ */
85
+ function classifyAmdNpu(ctx, fsx) {
86
+ if (ctx.platform !== "linux" || ctx.arch !== "x64" || !ctx.amdPresent) return null;
87
+ if (!hasAccelCharDevice(fsx)) return null;
88
+ for (const name of fsx.listDir(ACCEL_CLASS)) {
89
+ if (!name.startsWith("accel")) continue;
90
+ const vendor = normalizePciId(fsx.readFile("/sys/class/accel/" + name + "/device/vendor"));
91
+ const device = normalizePciId(fsx.readFile("/sys/class/accel/" + name + "/device/device"));
92
+ if (vendor !== AMD_PCI_VENDOR) continue;
93
+ return xdnaInfoForDevice(device);
94
+ }
95
+ return null;
96
+ }
97
+ /**
98
+ * The NPU descriptor for an AMD PCI device id (`0x1502` or `1502`). Shared by
99
+ * the Linux sysfs probe and the Windows PnP probe so both name the same
100
+ * silicon the same way.
101
+ */
102
+ function xdnaInfoForDevice(rawDeviceId) {
103
+ const device = normalizePciId(rawDeviceId);
104
+ if (XDNA1_DEVICES.has(device)) return {
105
+ type: "amd-xdna",
106
+ name: "AMD XDNA1 NPU",
107
+ generation: "xdna1"
108
+ };
109
+ if (XDNA2_DEVICES.has(device)) return {
110
+ type: "amd-xdna",
111
+ name: "AMD XDNA2 NPU",
112
+ generation: "xdna2"
113
+ };
114
+ return {
115
+ type: "amd-xdna",
116
+ name: "AMD XDNA NPU"
117
+ };
118
+ }
119
+ //#endregion
120
+ //#region src/builtins/platform-probe/windows-hardware.ts
121
+ var PCI_VENDOR_NVIDIA = "10DE";
122
+ var PCI_VENDOR_INTEL = "8086";
123
+ /** Radeon graphics are 1002; the XDNA NPU is a 1022 device. */
124
+ var PCI_VENDORS_AMD = new Set(["1002", "1022"]);
125
+ /** Adapters that are not hardware: RDP, hypervisor, capture and spoofing drivers. */
126
+ var VIRTUAL_ADAPTER = /basic display|basic render|remote display|hyper-v|vmware|virtualbox|parallels|citrix|parsec|indirect display|displaylink|mirror driver|virtual/i;
127
+ /** One PowerShell process answers both: video controllers and AMD PCI devices. */
128
+ var POWERSHELL_SCRIPT = [
129
+ "$ErrorActionPreference = 'SilentlyContinue'",
130
+ "$gpu = @(Get-CimInstance Win32_VideoController | Select-Object Name, PNPDeviceID)",
131
+ "$npu = @(Get-CimInstance Win32_PnPEntity | Where-Object { $_.PNPDeviceID -match 'VEN_1022&DEV_(1502|17F0)' } | Select-Object Name, PNPDeviceID)",
132
+ "@{ gpu = $gpu; npu = $npu } | ConvertTo-Json -Compress -Depth 3"
133
+ ].join("; ");
134
+ function powershellInvocation(systemRoot) {
135
+ return [`${systemRoot ?? "C:\\Windows"}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`, [
136
+ "-NoProfile",
137
+ "-NonInteractive",
138
+ "-ExecutionPolicy",
139
+ "Bypass",
140
+ "-Command",
141
+ POWERSHELL_SCRIPT
142
+ ]];
143
+ }
144
+ var WMIC_VIDEO_ARGS = [
145
+ "path",
146
+ "Win32_VideoController",
147
+ "get",
148
+ "Name,PNPDeviceID",
149
+ "/format:csv"
150
+ ];
151
+ var WMIC_AMD_PNP_ARGS = [
152
+ "path",
153
+ "Win32_PnPEntity",
154
+ "where",
155
+ "PNPDeviceID like 'PCI\\\\VEN_1022&DEV_%'",
156
+ "get",
157
+ "Name,PNPDeviceID",
158
+ "/format:csv"
159
+ ];
160
+ function asRecordList(value) {
161
+ if (Array.isArray(value)) return value.filter((v) => v !== null && typeof v === "object" && !Array.isArray(v));
162
+ return value !== null && typeof value === "object" ? [Object.fromEntries(Object.entries(value))] : [];
163
+ }
164
+ function str(value) {
165
+ return typeof value === "string" ? value : "";
166
+ }
167
+ /** PowerShell prepends a BOM on some hosts, which `JSON.parse` rejects. */
168
+ function parseJson(text) {
169
+ return JSON.parse(text.replace(/^\uFEFF/, "").trim());
170
+ }
171
+ /**
172
+ * `{"gpu":[...],"npu":[...]}` as the script emits it. A single result comes
173
+ * back as an object rather than a one-element array, and an empty one as
174
+ * `null` — all three are handled.
175
+ */
176
+ function parsePowershellOutput(text) {
177
+ const root = parseJson(text);
178
+ const gpu = root !== null && typeof root === "object" ? Reflect.get(root, "gpu") : void 0;
179
+ const npu = root !== null && typeof root === "object" ? Reflect.get(root, "npu") : void 0;
180
+ const toDevice = (r) => ({
181
+ name: str(r["Name"]),
182
+ pnpDeviceId: str(r["PNPDeviceID"])
183
+ });
184
+ return {
185
+ controllers: asRecordList(gpu).map(toDevice),
186
+ pnp: asRecordList(npu).map(toDevice)
187
+ };
188
+ }
189
+ /**
190
+ * `wmic ... /format:csv` — a blank line, then `Node,<cols alphabetical>`, then
191
+ * one row per object. The device name can contain commas, so only the FIRST
192
+ * column boundaries are trusted: columns after `Node` are `Name,PNPDeviceID`
193
+ * and the PNP id (no commas) is taken from the END of the row.
194
+ */
195
+ function parseWmicCsv(text) {
196
+ const lines = text.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0);
197
+ const headerIndex = lines.findIndex((l) => /^node,/i.test(l));
198
+ if (headerIndex < 0) return [];
199
+ const out = [];
200
+ for (const line of lines.slice(headerIndex + 1)) {
201
+ const parts = line.split(",");
202
+ if (parts.length < 3) continue;
203
+ const pnpDeviceId = (parts[parts.length - 1] ?? "").trim();
204
+ const name = parts.slice(1, -1).join(",").trim();
205
+ if (pnpDeviceId.length > 0) out.push({
206
+ name,
207
+ pnpDeviceId
208
+ });
209
+ }
210
+ return out;
211
+ }
212
+ /** The PCI vendor id (`10DE`) out of a PnP id like `PCI\VEN_10DE&DEV_2504&...`. */
213
+ function pciVendorOf(pnpDeviceId) {
214
+ const m = /VEN_([0-9A-F]{4})/i.exec(pnpDeviceId);
215
+ return m?.[1] ? m[1].toUpperCase() : null;
216
+ }
217
+ function pciDeviceOf(pnpDeviceId) {
218
+ const m = /DEV_([0-9A-F]{4})/i.exec(pnpDeviceId);
219
+ return m?.[1] ? m[1].toLowerCase() : null;
220
+ }
221
+ function gpuVendor(c) {
222
+ const vendor = pciVendorOf(c.pnpDeviceId);
223
+ if (vendor === PCI_VENDOR_NVIDIA) return "nvidia";
224
+ if (vendor === PCI_VENDOR_INTEL) return "intel";
225
+ if (vendor !== null && PCI_VENDORS_AMD.has(vendor)) return "amd";
226
+ if (/nvidia|geforce|quadro|rtx/i.test(c.name)) return "nvidia";
227
+ if (/intel/i.test(c.name)) return "intel";
228
+ if (/amd|radeon/i.test(c.name)) return "amd";
229
+ return null;
230
+ }
231
+ /**
232
+ * The accelerator the node should treat as its GPU. Same preference as the
233
+ * Linux probe — NVIDIA, then Intel, then AMD — so a laptop with an Intel iGPU
234
+ * and a discrete card is described the way the rest of the system already
235
+ * expects. Virtual adapters never count.
236
+ */
237
+ function classifyWindowsGpu(controllers) {
238
+ const real = controllers.filter((c) => c.name.length > 0 && !VIRTUAL_ADAPTER.test(c.name));
239
+ for (const wanted of [
240
+ "nvidia",
241
+ "intel",
242
+ "amd"
243
+ ]) {
244
+ const hit = real.find((c) => gpuVendor(c) === wanted);
245
+ if (hit) return {
246
+ type: wanted,
247
+ name: hit.name
248
+ };
249
+ }
250
+ return null;
251
+ }
252
+ /**
253
+ * An AMD XDNA NPU from PnP ids: `PCI\VEN_1022&DEV_1502` (Phoenix / Hawk Point)
254
+ * or `DEV_17F0` (Strix / Krackan). Present-only, exactly like the Linux probe.
255
+ */
256
+ function classifyWindowsAmdNpu(devices) {
257
+ for (const d of devices) {
258
+ if (pciVendorOf(d.pnpDeviceId) !== "1022") continue;
259
+ const device = pciDeviceOf(d.pnpDeviceId);
260
+ if (device === "1502" || device === "17f0") return xdnaInfoForDevice(device);
261
+ }
262
+ return null;
263
+ }
264
+ async function viaPowershell(run, systemRoot) {
265
+ const [file, args] = powershellInvocation(systemRoot);
266
+ const parsed = parsePowershellOutput(await run(file, args));
267
+ return {
268
+ gpu: classifyWindowsGpu(parsed.controllers),
269
+ npu: classifyWindowsAmdNpu(parsed.pnp),
270
+ source: "powershell"
271
+ };
272
+ }
273
+ async function viaWmic(run) {
274
+ const [video, amd] = await Promise.all([run("wmic", WMIC_VIDEO_ARGS), run("wmic", WMIC_AMD_PNP_ARGS).catch(() => "")]);
275
+ return {
276
+ gpu: classifyWindowsGpu(parseWmicCsv(video)),
277
+ npu: classifyWindowsAmdNpu(parseWmicCsv(amd)),
278
+ source: "wmic"
279
+ };
280
+ }
281
+ /**
282
+ * GPU + AMD NPU on a Windows host. NEVER throws: a probe that cannot run is
283
+ * `{ gpu: null, npu: null, source: 'none' }` and boot goes on — the node then
284
+ * scores as a CPU node, which is correct for hardware we could not see.
285
+ */
286
+ async function probeWindowsHardware(run, options = {}) {
287
+ try {
288
+ return await viaPowershell(run, options.systemRoot);
289
+ } catch (powershellError) {
290
+ options.onFallback?.(`PowerShell probe failed (${powershellError instanceof Error ? powershellError.message : String(powershellError)}); trying wmic`);
291
+ }
292
+ try {
293
+ return await viaWmic(run);
294
+ } catch (wmicError) {
295
+ options.onFallback?.(`wmic probe failed (${wmicError instanceof Error ? wmicError.message : String(wmicError)}); hardware unknown`);
296
+ return {
297
+ gpu: null,
298
+ npu: null,
299
+ source: "none"
300
+ };
301
+ }
302
+ }
303
+ //#endregion
56
304
  //#region src/builtins/platform-probe/platform-scorer.ts
305
+ /** WMI can be slow on a cold machine, but never worth stalling boot for. */
306
+ var WINDOWS_PROBE_TIMEOUT_MS = 15e3;
57
307
  /**
58
308
  * Promisified `execFile`. Used across the scorer so every subprocess
59
309
  * spawn yields the event loop — critical at boot because a single sync
@@ -231,24 +481,25 @@ var PlatformScorer = class {
231
481
  };
232
482
  npu = { type: "apple-ane" };
233
483
  }
484
+ if (platform === "win32") {
485
+ const nvidia = await this.probeNvidiaSmi();
486
+ const win = await this.probeWindowsHardwareSafely();
487
+ gpu = nvidia ?? win.gpu;
488
+ npu = win.npu;
489
+ if (gpu) this.logger.info("Windows GPU detected", { meta: {
490
+ type: gpu.type,
491
+ name: gpu.name
492
+ } });
493
+ if (npu && win.source !== "none") this.logger.info("AMD XDNA NPU detected (present only)", { meta: {
494
+ type: npu.type,
495
+ name: npu.name,
496
+ generation: npu.generation,
497
+ source: win.source
498
+ } });
499
+ }
234
500
  if (platform === "linux") {
235
- try {
236
- const { stdout } = await execFileAsync("nvidia-smi", ["--query-gpu=name,memory.total", "--format=csv,noheader"], {
237
- encoding: "utf8",
238
- timeout: 5e3
239
- });
240
- const output = stdout.trim();
241
- if (output) {
242
- const [name, mem] = output.split(",").map((s) => s.trim());
243
- gpu = {
244
- type: "nvidia",
245
- name: name ?? "NVIDIA GPU",
246
- memoryMB: parseInt(mem ?? "0")
247
- };
248
- }
249
- } catch (err) {
250
- this.logger.debug("NVIDIA GPU detection failed", { meta: { error: errMsg(err) } });
251
- }
501
+ const nvidia = await this.probeNvidiaSmi();
502
+ if (nvidia) gpu = nvidia;
252
503
  const listRenderNodes = () => {
253
504
  try {
254
505
  return fs.readdirSync("/dev/dri").filter((n) => n.startsWith("renderD")).map((n) => `/dev/dri/${n}`);
@@ -307,7 +558,7 @@ var PlatformScorer = class {
307
558
  } });
308
559
  }
309
560
  if (!npu) {
310
- const { classifyAmdNpu } = await import("../../amd-npu-Db_SoSuL.mjs");
561
+ const { classifyAmdNpu } = await Promise.resolve().then(() => amd_npu_exports);
311
562
  npu = classifyAmdNpu({
312
563
  platform,
313
564
  arch,
@@ -342,6 +593,53 @@ var PlatformScorer = class {
342
593
  coral
343
594
  };
344
595
  }
596
+ /** NVIDIA's own tool: exact model and VRAM. Null when absent or failing. */
597
+ async probeNvidiaSmi() {
598
+ try {
599
+ const { stdout } = await execFileAsync("nvidia-smi", ["--query-gpu=name,memory.total", "--format=csv,noheader"], {
600
+ encoding: "utf8",
601
+ timeout: 5e3,
602
+ windowsHide: true
603
+ });
604
+ const output = stdout.trim();
605
+ if (!output) return null;
606
+ const [name, mem] = output.split(",").map((s) => s.trim());
607
+ return {
608
+ type: "nvidia",
609
+ name: name ?? "NVIDIA GPU",
610
+ memoryMB: parseInt(mem ?? "0")
611
+ };
612
+ } catch (err) {
613
+ this.logger.debug("NVIDIA GPU detection failed", { meta: { error: errMsg(err) } });
614
+ return null;
615
+ }
616
+ }
617
+ /** Windows WMI probe; bounded, and a failure is a log line, never a boot failure. */
618
+ async probeWindowsHardwareSafely() {
619
+ const run = async (file, args) => {
620
+ const { stdout } = await execFileAsync(file, [...args], {
621
+ encoding: "utf8",
622
+ timeout: WINDOWS_PROBE_TIMEOUT_MS,
623
+ windowsHide: true,
624
+ maxBuffer: 4 * 1024 * 1024
625
+ });
626
+ return stdout;
627
+ };
628
+ const systemRoot = process.env["SystemRoot"];
629
+ try {
630
+ return await probeWindowsHardware(run, {
631
+ ...systemRoot === void 0 ? {} : { systemRoot },
632
+ onFallback: (reason) => this.logger.warn("Windows hardware probe degraded", { meta: { reason } })
633
+ });
634
+ } catch (err) {
635
+ this.logger.warn("Windows hardware probe failed — scoring as a CPU node", { meta: { error: errMsg(err) } });
636
+ return {
637
+ gpu: null,
638
+ npu: null,
639
+ source: "none"
640
+ };
641
+ }
642
+ }
345
643
  /**
346
644
  * Locates a Python interpreter without importing any module.
347
645
  *
@@ -26,6 +26,10 @@ export declare class PlatformScorer {
26
26
  */
27
27
  probe(onPhase?: (phase: string, payload?: Record<string, unknown>) => void): Promise<PlatformCapabilities>;
28
28
  probeHardware(): Promise<HardwareInfo>;
29
+ /** NVIDIA's own tool: exact model and VRAM. Null when absent or failing. */
30
+ private probeNvidiaSmi;
31
+ /** Windows WMI probe; bounded, and a failure is a log line, never a boot failure. */
32
+ private probeWindowsHardwareSafely;
29
33
  /**
30
34
  * Locates a Python interpreter without importing any module.
31
35
  *
@@ -0,0 +1,77 @@
1
+ import type { GpuInfo, NpuInfo } from "@camstack/types";
2
+ /**
3
+ * Windows hardware probe — the same `hw.gpu` / `hw.npu` model the Linux probe
4
+ * fills from `/sys` and `/dev`, read from WMI instead.
5
+ *
6
+ * Two sources, tried in order, neither able to block boot:
7
+ * 1. PowerShell + `Get-CimInstance` (every supported Windows ships it; one
8
+ * process answers both questions).
9
+ * 2. `wmic` — deprecated and absent from newer images, but present on the
10
+ * Windows 10/11 releases that lack nothing else, and the only thing left
11
+ * when PowerShell is locked down by policy.
12
+ *
13
+ * Everything here is PURE over the text a runner returns, so the parsing and
14
+ * the classification are tested on any OS. What this cannot prove — and a
15
+ * Mac cannot — is the shape of the real WMI output on a real Windows host; the
16
+ * parsers are written to accept both the object and the array form PowerShell
17
+ * produces, and the wmic CSV header order wmic actually uses.
18
+ */
19
+ /** Runs a program and resolves with its stdout; rejects on failure or timeout. */
20
+ export type WindowsProbeRunner = (file: string, args: readonly string[]) => Promise<string>;
21
+ export interface WindowsVideoController {
22
+ readonly name: string;
23
+ readonly pnpDeviceId: string;
24
+ }
25
+ export interface WindowsPnpDevice {
26
+ readonly name: string;
27
+ readonly pnpDeviceId: string;
28
+ }
29
+ export interface WindowsHardware {
30
+ readonly gpu: GpuInfo | null;
31
+ readonly npu: NpuInfo | null;
32
+ /** Which source answered — for the boot log; `none` when neither could. */
33
+ readonly source: "powershell" | "wmic" | "none";
34
+ }
35
+ export declare function powershellInvocation(systemRoot: string | undefined): readonly [string, readonly string[]];
36
+ export declare const WMIC_VIDEO_ARGS: readonly string[];
37
+ export declare const WMIC_AMD_PNP_ARGS: readonly string[];
38
+ export interface ParsedPowershell {
39
+ readonly controllers: readonly WindowsVideoController[];
40
+ readonly pnp: readonly WindowsPnpDevice[];
41
+ }
42
+ /**
43
+ * `{"gpu":[...],"npu":[...]}` as the script emits it. A single result comes
44
+ * back as an object rather than a one-element array, and an empty one as
45
+ * `null` — all three are handled.
46
+ */
47
+ export declare function parsePowershellOutput(text: string): ParsedPowershell;
48
+ /**
49
+ * `wmic ... /format:csv` — a blank line, then `Node,<cols alphabetical>`, then
50
+ * one row per object. The device name can contain commas, so only the FIRST
51
+ * column boundaries are trusted: columns after `Node` are `Name,PNPDeviceID`
52
+ * and the PNP id (no commas) is taken from the END of the row.
53
+ */
54
+ export declare function parseWmicCsv(text: string): readonly WindowsPnpDevice[];
55
+ /** The PCI vendor id (`10DE`) out of a PnP id like `PCI\VEN_10DE&DEV_2504&...`. */
56
+ export declare function pciVendorOf(pnpDeviceId: string): string | null;
57
+ /**
58
+ * The accelerator the node should treat as its GPU. Same preference as the
59
+ * Linux probe — NVIDIA, then Intel, then AMD — so a laptop with an Intel iGPU
60
+ * and a discrete card is described the way the rest of the system already
61
+ * expects. Virtual adapters never count.
62
+ */
63
+ export declare function classifyWindowsGpu(controllers: readonly WindowsVideoController[]): GpuInfo | null;
64
+ /**
65
+ * An AMD XDNA NPU from PnP ids: `PCI\VEN_1022&DEV_1502` (Phoenix / Hawk Point)
66
+ * or `DEV_17F0` (Strix / Krackan). Present-only, exactly like the Linux probe.
67
+ */
68
+ export declare function classifyWindowsAmdNpu(devices: readonly WindowsPnpDevice[]): NpuInfo | null;
69
+ /**
70
+ * GPU + AMD NPU on a Windows host. NEVER throws: a probe that cannot run is
71
+ * `{ gpu: null, npu: null, source: 'none' }` and boot goes on — the node then
72
+ * scores as a CPU node, which is correct for hardware we could not see.
73
+ */
74
+ export declare function probeWindowsHardware(run: WindowsProbeRunner, options?: {
75
+ readonly systemRoot?: string;
76
+ readonly onFallback?: (reason: string) => void;
77
+ }): Promise<WindowsHardware>;
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DxiDI8hZ.js");
6
+ const require_dist = require("../../dist-DVUg8e1T.js");
7
7
  //#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
8
8
  /**
9
9
  * Reconcile the durable `enabledProviders` set against authoritative
@@ -1,4 +1,4 @@
1
- import { ai as EventCategory, pr as BaseAddon } from "../../dist-DwE9yHdk.mjs";
1
+ import { cr as BaseAddon, ei as EventCategory } from "../../dist-DlmdESNT.mjs";
2
2
  //#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
3
3
  /**
4
4
  * Reconcile the durable `enabledProviders` set against authoritative
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DxiDI8hZ.js");
6
+ const require_dist = require("../../dist-DVUg8e1T.js");
7
7
  const require_snapshot_courtesy = require("../../snapshot-courtesy-D_C5-nC0.js");
8
8
  let zod = require("zod");
9
9
  let node_crypto = require("node:crypto");
@@ -1,4 +1,4 @@
1
- import { $ as bareAddonId, Hn as streamQualityLabel, In as snapshotCapability, Ur as nodePin, a as BatteryStatusSchema, ai as EventCategory, bt as deriveBatteryPresence, dr as DeviceType, et as batteryCapability, fr as errMsg, lr as DeviceFeature, on as memoizePinnedFfmpeg, pr as BaseAddon } from "../../dist-DwE9yHdk.mjs";
1
+ import { Ln as streamQualityLabel, X as bareAddonId, Z as batteryCapability, _t as deriveBatteryPresence, a as BatteryStatusSchema, cr as BaseAddon, ei as EventCategory, ir as DeviceFeature, jn as snapshotCapability, or as DeviceType, sr as errMsg, tn as memoizePinnedFfmpeg, zr as nodePin } from "../../dist-DlmdESNT.mjs";
2
2
  import { i as renderCourtesyOverlayJpeg, n as courtesyCacheKey, r as renderCourtesyJpeg } from "../../snapshot-courtesy-CyFs1M3I.mjs";
3
3
  import { z } from "zod";
4
4
  import { randomUUID } from "node:crypto";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DxiDI8hZ.js");
6
+ const require_dist = require("../../dist-DVUg8e1T.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  let node_fs_promises = require("node:fs/promises");
9
9
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { Bn as storageProviderCapability, Pt as filesystemBrowseCapability, pr as BaseAddon } from "../../dist-DwE9yHdk.mjs";
1
+ import { Fn as storageProviderCapability, cr as BaseAddon, jt as filesystemBrowseCapability } from "../../dist-DlmdESNT.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { mkdir, readdir, realpath, statfs } from "node:fs/promises";
4
4
  import * as path$1 from "node:path";
@@ -1,2 +1,2 @@
1
- import { StorageOrchestratorAddon, i as SqliteLocationStore, r as StorageMigrationCoordinator, t as StorageOrchestratorService } from "./storage-orchestrator.addon.mjs";
1
+ import { StorageOrchestratorAddon, c as SqliteLocationStore, s as StorageMigrationCoordinator, t as StorageOrchestratorService } from "./storage-orchestrator.addon.mjs";
2
2
  export { SqliteLocationStore, StorageMigrationCoordinator, StorageOrchestratorAddon, StorageOrchestratorAddon as default, StorageOrchestratorService };
@@ -3,8 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DxiDI8hZ.js");
7
- const require_hub_cap_forward = require("../../hub-cap-forward-W8oEm4ME.js");
6
+ const require_dist = require("../../dist-DVUg8e1T.js");
8
7
  let zod = require("zod");
9
8
  let node_crypto = require("node:crypto");
10
9
  let _camstack_types_node = require("@camstack/types/node");
@@ -1380,6 +1379,83 @@ var SqliteDrainStateStore = class {
1380
1379
  }
1381
1380
  };
1382
1381
  //#endregion
1382
+ //#region src/kernel/transport/hub-cap-forward.ts
1383
+ /** The Moleculer service name the hub registers for agent→hub cap forwarding. */
1384
+ var HUB_CAP_FWD_SERVICE = "$hub-cap-fwd";
1385
+ /** The Moleculer action (service.action) for hub cap forwarding. */
1386
+ var HUB_CAP_FWD_ACTION = `${HUB_CAP_FWD_SERVICE}.forward`;
1387
+ /**
1388
+ * Drop a `caller` the forwarded args carry. `caller` is the USER identity the
1389
+ * hub's tRPC router injects for `caller: 'required'` methods
1390
+ * (`cap-router-builder.ts`), and providers trust it — `keychainAdmin.reveal`
1391
+ * reads `input.caller.userId`. A call that arrives over the mesh has no user
1392
+ * session behind it, so whatever `caller` it carries is forged (D802). The
1393
+ * args' `callerAddonId` is overwritten or stripped further down by
1394
+ * `stampCallerAddonId`; `caller` had no such guard.
1395
+ */
1396
+ function stripForwardedCaller(args) {
1397
+ if (args === null || typeof args !== "object" || Array.isArray(args)) return args;
1398
+ if (!Object.prototype.hasOwnProperty.call(args, "caller")) return args;
1399
+ const rest = {};
1400
+ for (const [key, value] of Object.entries(args)) if (key !== "caller") rest[key] = value;
1401
+ return rest;
1402
+ }
1403
+ /**
1404
+ * Narrow Moleculer's loosely-typed `ctx.params` to {@link HubCapForwardParams}
1405
+ * without unsafe casts — mirrors `agent-cap-dispatch-service.ts:narrowParams`.
1406
+ */
1407
+ function narrowParams(raw) {
1408
+ if (raw === null || typeof raw !== "object") throw new Error("$hub-cap-fwd.forward: invalid params — capName and method are required strings");
1409
+ const capName = Reflect.get(raw, "capName");
1410
+ const method = Reflect.get(raw, "method");
1411
+ if (typeof capName !== "string" || typeof method !== "string") throw new Error("$hub-cap-fwd.forward: invalid params — capName and method are required strings");
1412
+ const deviceId = Reflect.get(raw, "deviceId");
1413
+ const nodeId = Reflect.get(raw, "nodeId");
1414
+ const native = Reflect.get(raw, "native");
1415
+ const callerAddonId = Reflect.get(raw, "callerAddonId");
1416
+ return {
1417
+ capName,
1418
+ method,
1419
+ args: stripForwardedCaller(Reflect.get(raw, "args")),
1420
+ deviceId: typeof deviceId === "number" ? deviceId : void 0,
1421
+ nodeId: typeof nodeId === "string" && nodeId.length > 0 ? nodeId : void 0,
1422
+ native: native === true ? true : void 0,
1423
+ callerAddonId: typeof callerAddonId === "string" && callerAddonId.length > 0 ? callerAddonId : void 0
1424
+ };
1425
+ }
1426
+ /**
1427
+ * Build the `$hub-cap-fwd` Moleculer `ServiceSchema`. The hub registers this on
1428
+ * its broker (only the hub registers it → an agent's `broker.call` for
1429
+ * `$hub-cap-fwd.forward` discovers it on the hub with no explicit nodeID pin).
1430
+ *
1431
+ * @param onUnownedCall The hub's cap routing handler (from
1432
+ * `createParentUnownedCallHandler`). Reused verbatim so
1433
+ * forwarded calls route exactly like a hub-local child's.
1434
+ */
1435
+ function createHubCapForwardService(onUnownedCall, options = {}) {
1436
+ return {
1437
+ name: HUB_CAP_FWD_SERVICE,
1438
+ actions: { forward: { handler: async (ctx) => {
1439
+ const { capName, method, args, deviceId, nodeId, native, callerAddonId } = narrowParams(ctx.params);
1440
+ const sender = typeof ctx.nodeID === "string" ? ctx.nodeID : null;
1441
+ let caller = callerAddonId;
1442
+ if (caller !== void 0 && options.isCallerOnNode !== void 0 && (sender === null || !options.isCallerOnNode(sender, caller))) {
1443
+ options.onRejectedCaller?.(sender ?? "(unknown node)", caller);
1444
+ caller = void 0;
1445
+ }
1446
+ return onUnownedCall({
1447
+ capName,
1448
+ method,
1449
+ args,
1450
+ ...deviceId !== void 0 ? { deviceId } : {},
1451
+ ...nodeId !== void 0 ? { nodeId } : {},
1452
+ ...native === true ? { native: true } : {},
1453
+ ...caller !== void 0 ? { callerAddonId: caller } : {}
1454
+ });
1455
+ } } }
1456
+ };
1457
+ }
1458
+ //#endregion
1383
1459
  //#region src/builtins/storage-orchestrator/hub-settings-forward.ts
1384
1460
  /**
1385
1461
  * The data door with the HUB behind it — an agent's `settings-store` provider.
@@ -1513,7 +1589,7 @@ function resolveHubSettingsForward(options) {
1513
1589
  const broker = options.broker;
1514
1590
  if (!broker) return null;
1515
1591
  options.logger.info("storage-orchestrator: no local data-store engine on this node — the data door forwards to the hub");
1516
- return createHubSettingsForward((envelope) => broker.call(require_hub_cap_forward.HUB_CAP_FWD_ACTION, {
1592
+ return createHubSettingsForward((envelope) => broker.call(HUB_CAP_FWD_ACTION, {
1517
1593
  capName: envelope.capName,
1518
1594
  method: envelope.method,
1519
1595
  args: envelope.args
@@ -4513,9 +4589,13 @@ function parseOrphanStatus(raw) {
4513
4589
  };
4514
4590
  }
4515
4591
  //#endregion
4592
+ exports.HUB_CAP_FWD_ACTION = HUB_CAP_FWD_ACTION;
4593
+ exports.HUB_CAP_FWD_SERVICE = HUB_CAP_FWD_SERVICE;
4516
4594
  exports.SqliteLocationStore = SqliteLocationStore;
4517
4595
  exports.StorageMigrationCoordinator = StorageMigrationCoordinator;
4518
4596
  exports.StorageOrchestratorAddon = StorageOrchestratorAddon;
4519
4597
  exports.default = StorageOrchestratorAddon;
4520
4598
  exports.StorageOrchestratorService = StorageOrchestratorService;
4521
4599
  exports.buildStorageLocationRegistry = buildStorageLocationRegistry;
4600
+ exports.createHubCapForwardService = createHubCapForwardService;
4601
+ exports.stripForwardedCaller = stripForwardedCaller;