@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
@@ -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_proc_stat = require("../../proc-stat-DL-WUOhl.js");
6
+ const require_dist = require("../../dist-DVUg8e1T.js");
8
7
  let node_fs_promises = require("node:fs/promises");
9
8
  let node_os = require("node:os");
10
9
  node_os = require_chunk.__toESM(node_os);
@@ -2126,7 +2125,7 @@ var NativeMetricsProvider = class {
2126
2125
  return getCpuTemperatureInternal();
2127
2126
  }
2128
2127
  async getProcessStats(input) {
2129
- const { getPidStats } = await Promise.resolve().then(() => require("../../resource-monitor-BgWGRxN5.js")).then((n) => n.resource_monitor_exports);
2128
+ const { getPidStats } = await Promise.resolve().then(() => require("../../resource-monitor-mio9dSCT.js")).then((n) => n.resource_monitor_exports);
2130
2129
  const raw = await getPidStats(input.pids);
2131
2130
  const result = [];
2132
2131
  for (const [pid, s] of raw) result.push({
@@ -2462,6 +2461,95 @@ function execAsync(cmd, args, timeoutMs = 5e3) {
2462
2461
  });
2463
2462
  });
2464
2463
  }
2464
+ /**
2465
+ * Parse one `/proc/<pid>/stat` line. `null` for a line that does not parse —
2466
+ * a process that exited between the readdir and the read leaves a truncated
2467
+ * or empty file, and that is normal, not an error.
2468
+ */
2469
+ function parseProcStat(line) {
2470
+ const close = line.lastIndexOf(")");
2471
+ const open = line.indexOf("(");
2472
+ if (close < 0 || open < 0 || close < open) return null;
2473
+ const pid = Number(line.slice(0, open).trim());
2474
+ const comm = line.slice(open + 1, close);
2475
+ const rest = line.slice(close + 1).trim().split(/\s+/);
2476
+ const state = rest[0];
2477
+ const ppid = Number(rest[1]);
2478
+ const pgid = Number(rest[2]);
2479
+ const utime = Number(rest[11]);
2480
+ const stime = Number(rest[12]);
2481
+ const startTicks = Number(rest[19]);
2482
+ const rssPages = Number(rest[21]);
2483
+ if (state === void 0 || state === "") return null;
2484
+ if (![
2485
+ pid,
2486
+ ppid,
2487
+ pgid,
2488
+ utime,
2489
+ stime,
2490
+ startTicks,
2491
+ rssPages
2492
+ ].every(Number.isFinite)) return null;
2493
+ return {
2494
+ pid,
2495
+ comm,
2496
+ state,
2497
+ ppid,
2498
+ pgid,
2499
+ ticks: utime + stime,
2500
+ startTicks,
2501
+ rssPages
2502
+ };
2503
+ }
2504
+ function statusKb(status, key) {
2505
+ const match = status.match(new RegExp(`^${key}:\\s+(\\d+)`, "m"));
2506
+ return match ? parseInt(match[1], 10) * 1024 : void 0;
2507
+ }
2508
+ /** Read `VmRSS` / `RssAnon` / `RssFile` (kB in the file) out of `/proc/<pid>/status`. */
2509
+ function parseProcStatusRss(status) {
2510
+ return {
2511
+ rssBytes: statusKb(status, "VmRSS"),
2512
+ privateBytes: statusKb(status, "RssAnon"),
2513
+ sharedBytes: statusKb(status, "RssFile")
2514
+ };
2515
+ }
2516
+ /** Seconds the process has been alive — `ps etime`, whole seconds. */
2517
+ function elapsedSecSince(input) {
2518
+ return Math.max(0, Math.floor(input.uptimeSec - input.startTicks / 100));
2519
+ }
2520
+ /**
2521
+ * `ps pcpu`: CPU time over elapsed time, as a percentage with one decimal.
2522
+ *
2523
+ * This is deliberately the LIFETIME average `ps` prints, not an instantaneous
2524
+ * rate: the columns fed from it have always shown that quantity, and the
2525
+ * instantaneous split is a different number with a different owner
2526
+ * (`cpuMainPercent` / `cpuGcPercent` from `thread-cpu-sampler.ts`). A process
2527
+ * with no elapsed window yet reports 0, never a division by zero.
2528
+ */
2529
+ function lifetimeCpuPercent(input) {
2530
+ const elapsedSec = input.uptimeSec - input.startTicks / 100;
2531
+ if (!(elapsedSec > 0)) return 0;
2532
+ const cpuSec = input.ticks / 100;
2533
+ return Math.round(cpuSec / elapsedSec * 1e3) / 10;
2534
+ }
2535
+ var PID_RE = /^\d+$/;
2536
+ var nodeProcReader = {
2537
+ listPids: async () => (await (0, node_fs_promises.readdir)("/proc")).filter((entry) => PID_RE.test(entry)).map((entry) => Number(entry)),
2538
+ readStat: (pid) => (0, node_fs_promises.readFile)(`/proc/${pid}/stat`, "latin1"),
2539
+ readStatus: (pid) => (0, node_fs_promises.readFile)(`/proc/${pid}/status`, "latin1"),
2540
+ readCmdline: (pid) => (0, node_fs_promises.readFile)(`/proc/${pid}/cmdline`, "latin1"),
2541
+ readUptimeSec: async () => {
2542
+ const [first] = (await (0, node_fs_promises.readFile)("/proc/uptime", "latin1")).trim().split(/\s+/);
2543
+ const seconds = Number(first);
2544
+ if (!Number.isFinite(seconds)) throw new Error(`/proc/uptime unreadable: ${String(first)}`);
2545
+ return seconds;
2546
+ }
2547
+ };
2548
+ /** `ps command=`: argv joined by spaces, or `[comm]` when there is no argv. */
2549
+ function commandFromCmdline(cmdline, comm) {
2550
+ const joined = cmdline.split("\0").filter((part) => part.length > 0).join(" ");
2551
+ return joined.length > 0 ? joined : `[${comm}]`;
2552
+ }
2465
2553
  //#endregion
2466
2554
  //#region src/builtins/native-metrics/proc-process-table.ts
2467
2555
  /**
@@ -2493,28 +2581,28 @@ async function readProcRow(pid, uptimeSec, reader) {
2493
2581
  } catch {
2494
2582
  return null;
2495
2583
  }
2496
- const parsed = require_proc_stat.parseProcStat(stat);
2584
+ const parsed = parseProcStat(stat);
2497
2585
  if (parsed === null) return null;
2498
- const rss = require_proc_stat.parseProcStatusRss(status);
2586
+ const rss = parseProcStatusRss(status);
2499
2587
  return {
2500
2588
  pid: parsed.pid,
2501
2589
  ppid: parsed.ppid,
2502
2590
  pgid: parsed.pgid,
2503
- cpuPercent: require_proc_stat.lifetimeCpuPercent({
2591
+ cpuPercent: lifetimeCpuPercent({
2504
2592
  ticks: parsed.ticks,
2505
2593
  startTicks: parsed.startTicks,
2506
2594
  uptimeSec
2507
2595
  }),
2508
2596
  memoryRssBytes: rss.rssBytes ?? 0,
2509
- uptimeSec: require_proc_stat.elapsedSecSince({
2597
+ uptimeSec: elapsedSecSince({
2510
2598
  startTicks: parsed.startTicks,
2511
2599
  uptimeSec
2512
2600
  }),
2513
- command: require_proc_stat.commandFromCmdline(cmdline, parsed.comm)
2601
+ command: commandFromCmdline(cmdline, parsed.comm)
2514
2602
  };
2515
2603
  }
2516
2604
  /** Every process in `/proc`, as the rows `ps -eo …` would have printed. */
2517
- async function readProcProcessTable(reader = require_proc_stat.nodeProcReader) {
2605
+ async function readProcProcessTable(reader = nodeProcReader) {
2518
2606
  const [pids, uptimeSec] = await Promise.all([reader.listPids(), reader.readUptimeSec()]);
2519
2607
  return (await Promise.all(pids.map((pid) => readProcRow(pid, uptimeSec, reader)))).filter((row) => row !== null);
2520
2608
  }
@@ -2569,7 +2657,7 @@ async function spawnPsTable() {
2569
2657
  }
2570
2658
  var defaultDeps = {
2571
2659
  platform: (0, node_os.platform)(),
2572
- reader: require_proc_stat.nodeProcReader,
2660
+ reader: nodeProcReader,
2573
2661
  spawnPs: spawnPsTable
2574
2662
  };
2575
2663
  /**
@@ -3481,3 +3569,7 @@ var NativeMetricsAddon = class NativeMetricsAddon extends require_dist.BaseAddon
3481
3569
  //#endregion
3482
3570
  exports.NativeMetricsProvider = NativeMetricsProvider;
3483
3571
  exports.default = NativeMetricsAddon;
3572
+ exports.lifetimeCpuPercent = lifetimeCpuPercent;
3573
+ exports.nodeProcReader = nodeProcReader;
3574
+ exports.parseProcStat = parseProcStat;
3575
+ exports.parseProcStatusRss = parseProcStatusRss;
@@ -1,5 +1,4 @@
1
- import { Cn as resolveBucketMs, Ft as foldSnapshotByFunction, Or as createEvent, ai as EventCategory, bn as reducePoints, fr as errMsg, pr as BaseAddon, sn as metricsProviderCapability } from "../../dist-DwE9yHdk.mjs";
2
- import { a as parseProcStat, i as nodeProcReader, n as elapsedSecSince, o as parseProcStatusRss, r as lifetimeCpuPercent, t as commandFromCmdline } from "../../proc-stat-CbC55Kqi.mjs";
1
+ import { Mt as foldSnapshotByFunction, cr as BaseAddon, ei as EventCategory, hn as reducePoints, nn as metricsProviderCapability, sr as errMsg, vn as resolveBucketMs, wr as createEvent } from "../../dist-DlmdESNT.mjs";
3
2
  import { access, readFile, readdir } from "node:fs/promises";
4
3
  import * as os from "node:os";
5
4
  import { platform } from "node:os";
@@ -2121,7 +2120,7 @@ var NativeMetricsProvider = class {
2121
2120
  return getCpuTemperatureInternal();
2122
2121
  }
2123
2122
  async getProcessStats(input) {
2124
- const { getPidStats } = await import("../../resource-monitor-B2WZ8_q9.mjs").then((n) => n.r);
2123
+ const { getPidStats } = await import("../../resource-monitor-Di9daRwI.mjs").then((n) => n.r);
2125
2124
  const raw = await getPidStats(input.pids);
2126
2125
  const result = [];
2127
2126
  for (const [pid, s] of raw) result.push({
@@ -2457,6 +2456,95 @@ function execAsync(cmd, args, timeoutMs = 5e3) {
2457
2456
  });
2458
2457
  });
2459
2458
  }
2459
+ /**
2460
+ * Parse one `/proc/<pid>/stat` line. `null` for a line that does not parse —
2461
+ * a process that exited between the readdir and the read leaves a truncated
2462
+ * or empty file, and that is normal, not an error.
2463
+ */
2464
+ function parseProcStat(line) {
2465
+ const close = line.lastIndexOf(")");
2466
+ const open = line.indexOf("(");
2467
+ if (close < 0 || open < 0 || close < open) return null;
2468
+ const pid = Number(line.slice(0, open).trim());
2469
+ const comm = line.slice(open + 1, close);
2470
+ const rest = line.slice(close + 1).trim().split(/\s+/);
2471
+ const state = rest[0];
2472
+ const ppid = Number(rest[1]);
2473
+ const pgid = Number(rest[2]);
2474
+ const utime = Number(rest[11]);
2475
+ const stime = Number(rest[12]);
2476
+ const startTicks = Number(rest[19]);
2477
+ const rssPages = Number(rest[21]);
2478
+ if (state === void 0 || state === "") return null;
2479
+ if (![
2480
+ pid,
2481
+ ppid,
2482
+ pgid,
2483
+ utime,
2484
+ stime,
2485
+ startTicks,
2486
+ rssPages
2487
+ ].every(Number.isFinite)) return null;
2488
+ return {
2489
+ pid,
2490
+ comm,
2491
+ state,
2492
+ ppid,
2493
+ pgid,
2494
+ ticks: utime + stime,
2495
+ startTicks,
2496
+ rssPages
2497
+ };
2498
+ }
2499
+ function statusKb(status, key) {
2500
+ const match = status.match(new RegExp(`^${key}:\\s+(\\d+)`, "m"));
2501
+ return match ? parseInt(match[1], 10) * 1024 : void 0;
2502
+ }
2503
+ /** Read `VmRSS` / `RssAnon` / `RssFile` (kB in the file) out of `/proc/<pid>/status`. */
2504
+ function parseProcStatusRss(status) {
2505
+ return {
2506
+ rssBytes: statusKb(status, "VmRSS"),
2507
+ privateBytes: statusKb(status, "RssAnon"),
2508
+ sharedBytes: statusKb(status, "RssFile")
2509
+ };
2510
+ }
2511
+ /** Seconds the process has been alive — `ps etime`, whole seconds. */
2512
+ function elapsedSecSince(input) {
2513
+ return Math.max(0, Math.floor(input.uptimeSec - input.startTicks / 100));
2514
+ }
2515
+ /**
2516
+ * `ps pcpu`: CPU time over elapsed time, as a percentage with one decimal.
2517
+ *
2518
+ * This is deliberately the LIFETIME average `ps` prints, not an instantaneous
2519
+ * rate: the columns fed from it have always shown that quantity, and the
2520
+ * instantaneous split is a different number with a different owner
2521
+ * (`cpuMainPercent` / `cpuGcPercent` from `thread-cpu-sampler.ts`). A process
2522
+ * with no elapsed window yet reports 0, never a division by zero.
2523
+ */
2524
+ function lifetimeCpuPercent(input) {
2525
+ const elapsedSec = input.uptimeSec - input.startTicks / 100;
2526
+ if (!(elapsedSec > 0)) return 0;
2527
+ const cpuSec = input.ticks / 100;
2528
+ return Math.round(cpuSec / elapsedSec * 1e3) / 10;
2529
+ }
2530
+ var PID_RE = /^\d+$/;
2531
+ var nodeProcReader = {
2532
+ listPids: async () => (await readdir("/proc")).filter((entry) => PID_RE.test(entry)).map((entry) => Number(entry)),
2533
+ readStat: (pid) => readFile(`/proc/${pid}/stat`, "latin1"),
2534
+ readStatus: (pid) => readFile(`/proc/${pid}/status`, "latin1"),
2535
+ readCmdline: (pid) => readFile(`/proc/${pid}/cmdline`, "latin1"),
2536
+ readUptimeSec: async () => {
2537
+ const [first] = (await readFile("/proc/uptime", "latin1")).trim().split(/\s+/);
2538
+ const seconds = Number(first);
2539
+ if (!Number.isFinite(seconds)) throw new Error(`/proc/uptime unreadable: ${String(first)}`);
2540
+ return seconds;
2541
+ }
2542
+ };
2543
+ /** `ps command=`: argv joined by spaces, or `[comm]` when there is no argv. */
2544
+ function commandFromCmdline(cmdline, comm) {
2545
+ const joined = cmdline.split("\0").filter((part) => part.length > 0).join(" ");
2546
+ return joined.length > 0 ? joined : `[${comm}]`;
2547
+ }
2460
2548
  //#endregion
2461
2549
  //#region src/builtins/native-metrics/proc-process-table.ts
2462
2550
  /**
@@ -3474,4 +3562,4 @@ var NativeMetricsAddon = class NativeMetricsAddon extends BaseAddon {
3474
3562
  }
3475
3563
  };
3476
3564
  //#endregion
3477
- export { NativeMetricsAddon as default, NativeMetricsProvider as t };
3565
+ export { NativeMetricsProvider as a, NativeMetricsAddon as default, parseProcStatusRss as i, nodeProcReader as n, parseProcStat as r, lifetimeCpuPercent as t };
@@ -27,3 +27,9 @@ export interface AmdNpuContext {
27
27
  * generation so the UI and fleet census can show the hardware.
28
28
  */
29
29
  export declare function classifyAmdNpu(ctx: AmdNpuContext, fsx: AmdNpuFs): NpuInfo | null;
30
+ /**
31
+ * The NPU descriptor for an AMD PCI device id (`0x1502` or `1502`). Shared by
32
+ * the Linux sysfs probe and the Windows PnP probe so both name the same
33
+ * silicon the same way.
34
+ */
35
+ export declare function xdnaInfoForDevice(rawDeviceId: string): NpuInfo;
@@ -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_os = require("node:os");
8
8
  node_os = require_chunk.__toESM(node_os);
9
9
  let node_fs = require("node:fs");
@@ -59,7 +59,257 @@ function classifyCoralAccelerator(fsx) {
59
59
  return null;
60
60
  }
61
61
  //#endregion
62
+ //#region src/builtins/platform-probe/amd-npu.ts
63
+ var amd_npu_exports = /* @__PURE__ */ require_chunk.__exportAll({
64
+ classifyAmdNpu: () => classifyAmdNpu,
65
+ xdnaInfoForDevice: () => xdnaInfoForDevice
66
+ });
67
+ var ACCEL_CLASS = "/sys/class/accel";
68
+ var ACCEL_DEV = "/dev/accel";
69
+ var AMD_PCI_VENDOR = "0x1022";
70
+ /** Phoenix / Hawk Point XDNA1. */
71
+ var XDNA1_DEVICES = new Set(["0x1502"]);
72
+ /** Strix / Krackan XDNA2. */
73
+ var XDNA2_DEVICES = new Set(["0x17f0"]);
74
+ function normalizePciId(raw) {
75
+ const t = raw.trim().toLowerCase();
76
+ if (t.startsWith("0x")) return t;
77
+ if (t.length > 0 && [...t].every((c) => "0123456789abcdef".includes(c))) return "0x" + t;
78
+ return t;
79
+ }
80
+ function hasAccelCharDevice(fsx) {
81
+ if (fsx.listDir(ACCEL_DEV).some((n) => n.startsWith("accel"))) return true;
82
+ return fsx.exists("/dev/accel/accel0");
83
+ }
84
+ /**
85
+ * Detect an AMD XDNA NPU and report it as **present only**.
86
+ *
87
+ * Inference is NOT offered until P2 (Ryzen AI on Linux is Strix-first;
88
+ * Phoenix is not a production path today). The probe still names the
89
+ * generation so the UI and fleet census can show the hardware.
90
+ */
91
+ function classifyAmdNpu(ctx, fsx) {
92
+ if (ctx.platform !== "linux" || ctx.arch !== "x64" || !ctx.amdPresent) return null;
93
+ if (!hasAccelCharDevice(fsx)) return null;
94
+ for (const name of fsx.listDir(ACCEL_CLASS)) {
95
+ if (!name.startsWith("accel")) continue;
96
+ const vendor = normalizePciId(fsx.readFile("/sys/class/accel/" + name + "/device/vendor"));
97
+ const device = normalizePciId(fsx.readFile("/sys/class/accel/" + name + "/device/device"));
98
+ if (vendor !== AMD_PCI_VENDOR) continue;
99
+ return xdnaInfoForDevice(device);
100
+ }
101
+ return null;
102
+ }
103
+ /**
104
+ * The NPU descriptor for an AMD PCI device id (`0x1502` or `1502`). Shared by
105
+ * the Linux sysfs probe and the Windows PnP probe so both name the same
106
+ * silicon the same way.
107
+ */
108
+ function xdnaInfoForDevice(rawDeviceId) {
109
+ const device = normalizePciId(rawDeviceId);
110
+ if (XDNA1_DEVICES.has(device)) return {
111
+ type: "amd-xdna",
112
+ name: "AMD XDNA1 NPU",
113
+ generation: "xdna1"
114
+ };
115
+ if (XDNA2_DEVICES.has(device)) return {
116
+ type: "amd-xdna",
117
+ name: "AMD XDNA2 NPU",
118
+ generation: "xdna2"
119
+ };
120
+ return {
121
+ type: "amd-xdna",
122
+ name: "AMD XDNA NPU"
123
+ };
124
+ }
125
+ //#endregion
126
+ //#region src/builtins/platform-probe/windows-hardware.ts
127
+ var PCI_VENDOR_NVIDIA = "10DE";
128
+ var PCI_VENDOR_INTEL = "8086";
129
+ /** Radeon graphics are 1002; the XDNA NPU is a 1022 device. */
130
+ var PCI_VENDORS_AMD = new Set(["1002", "1022"]);
131
+ /** Adapters that are not hardware: RDP, hypervisor, capture and spoofing drivers. */
132
+ var VIRTUAL_ADAPTER = /basic display|basic render|remote display|hyper-v|vmware|virtualbox|parallels|citrix|parsec|indirect display|displaylink|mirror driver|virtual/i;
133
+ /** One PowerShell process answers both: video controllers and AMD PCI devices. */
134
+ var POWERSHELL_SCRIPT = [
135
+ "$ErrorActionPreference = 'SilentlyContinue'",
136
+ "$gpu = @(Get-CimInstance Win32_VideoController | Select-Object Name, PNPDeviceID)",
137
+ "$npu = @(Get-CimInstance Win32_PnPEntity | Where-Object { $_.PNPDeviceID -match 'VEN_1022&DEV_(1502|17F0)' } | Select-Object Name, PNPDeviceID)",
138
+ "@{ gpu = $gpu; npu = $npu } | ConvertTo-Json -Compress -Depth 3"
139
+ ].join("; ");
140
+ function powershellInvocation(systemRoot) {
141
+ return [`${systemRoot ?? "C:\\Windows"}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`, [
142
+ "-NoProfile",
143
+ "-NonInteractive",
144
+ "-ExecutionPolicy",
145
+ "Bypass",
146
+ "-Command",
147
+ POWERSHELL_SCRIPT
148
+ ]];
149
+ }
150
+ var WMIC_VIDEO_ARGS = [
151
+ "path",
152
+ "Win32_VideoController",
153
+ "get",
154
+ "Name,PNPDeviceID",
155
+ "/format:csv"
156
+ ];
157
+ var WMIC_AMD_PNP_ARGS = [
158
+ "path",
159
+ "Win32_PnPEntity",
160
+ "where",
161
+ "PNPDeviceID like 'PCI\\\\VEN_1022&DEV_%'",
162
+ "get",
163
+ "Name,PNPDeviceID",
164
+ "/format:csv"
165
+ ];
166
+ function asRecordList(value) {
167
+ if (Array.isArray(value)) return value.filter((v) => v !== null && typeof v === "object" && !Array.isArray(v));
168
+ return value !== null && typeof value === "object" ? [Object.fromEntries(Object.entries(value))] : [];
169
+ }
170
+ function str(value) {
171
+ return typeof value === "string" ? value : "";
172
+ }
173
+ /** PowerShell prepends a BOM on some hosts, which `JSON.parse` rejects. */
174
+ function parseJson(text) {
175
+ return JSON.parse(text.replace(/^\uFEFF/, "").trim());
176
+ }
177
+ /**
178
+ * `{"gpu":[...],"npu":[...]}` as the script emits it. A single result comes
179
+ * back as an object rather than a one-element array, and an empty one as
180
+ * `null` — all three are handled.
181
+ */
182
+ function parsePowershellOutput(text) {
183
+ const root = parseJson(text);
184
+ const gpu = root !== null && typeof root === "object" ? Reflect.get(root, "gpu") : void 0;
185
+ const npu = root !== null && typeof root === "object" ? Reflect.get(root, "npu") : void 0;
186
+ const toDevice = (r) => ({
187
+ name: str(r["Name"]),
188
+ pnpDeviceId: str(r["PNPDeviceID"])
189
+ });
190
+ return {
191
+ controllers: asRecordList(gpu).map(toDevice),
192
+ pnp: asRecordList(npu).map(toDevice)
193
+ };
194
+ }
195
+ /**
196
+ * `wmic ... /format:csv` — a blank line, then `Node,<cols alphabetical>`, then
197
+ * one row per object. The device name can contain commas, so only the FIRST
198
+ * column boundaries are trusted: columns after `Node` are `Name,PNPDeviceID`
199
+ * and the PNP id (no commas) is taken from the END of the row.
200
+ */
201
+ function parseWmicCsv(text) {
202
+ const lines = text.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0);
203
+ const headerIndex = lines.findIndex((l) => /^node,/i.test(l));
204
+ if (headerIndex < 0) return [];
205
+ const out = [];
206
+ for (const line of lines.slice(headerIndex + 1)) {
207
+ const parts = line.split(",");
208
+ if (parts.length < 3) continue;
209
+ const pnpDeviceId = (parts[parts.length - 1] ?? "").trim();
210
+ const name = parts.slice(1, -1).join(",").trim();
211
+ if (pnpDeviceId.length > 0) out.push({
212
+ name,
213
+ pnpDeviceId
214
+ });
215
+ }
216
+ return out;
217
+ }
218
+ /** The PCI vendor id (`10DE`) out of a PnP id like `PCI\VEN_10DE&DEV_2504&...`. */
219
+ function pciVendorOf(pnpDeviceId) {
220
+ const m = /VEN_([0-9A-F]{4})/i.exec(pnpDeviceId);
221
+ return m?.[1] ? m[1].toUpperCase() : null;
222
+ }
223
+ function pciDeviceOf(pnpDeviceId) {
224
+ const m = /DEV_([0-9A-F]{4})/i.exec(pnpDeviceId);
225
+ return m?.[1] ? m[1].toLowerCase() : null;
226
+ }
227
+ function gpuVendor(c) {
228
+ const vendor = pciVendorOf(c.pnpDeviceId);
229
+ if (vendor === PCI_VENDOR_NVIDIA) return "nvidia";
230
+ if (vendor === PCI_VENDOR_INTEL) return "intel";
231
+ if (vendor !== null && PCI_VENDORS_AMD.has(vendor)) return "amd";
232
+ if (/nvidia|geforce|quadro|rtx/i.test(c.name)) return "nvidia";
233
+ if (/intel/i.test(c.name)) return "intel";
234
+ if (/amd|radeon/i.test(c.name)) return "amd";
235
+ return null;
236
+ }
237
+ /**
238
+ * The accelerator the node should treat as its GPU. Same preference as the
239
+ * Linux probe — NVIDIA, then Intel, then AMD — so a laptop with an Intel iGPU
240
+ * and a discrete card is described the way the rest of the system already
241
+ * expects. Virtual adapters never count.
242
+ */
243
+ function classifyWindowsGpu(controllers) {
244
+ const real = controllers.filter((c) => c.name.length > 0 && !VIRTUAL_ADAPTER.test(c.name));
245
+ for (const wanted of [
246
+ "nvidia",
247
+ "intel",
248
+ "amd"
249
+ ]) {
250
+ const hit = real.find((c) => gpuVendor(c) === wanted);
251
+ if (hit) return {
252
+ type: wanted,
253
+ name: hit.name
254
+ };
255
+ }
256
+ return null;
257
+ }
258
+ /**
259
+ * An AMD XDNA NPU from PnP ids: `PCI\VEN_1022&DEV_1502` (Phoenix / Hawk Point)
260
+ * or `DEV_17F0` (Strix / Krackan). Present-only, exactly like the Linux probe.
261
+ */
262
+ function classifyWindowsAmdNpu(devices) {
263
+ for (const d of devices) {
264
+ if (pciVendorOf(d.pnpDeviceId) !== "1022") continue;
265
+ const device = pciDeviceOf(d.pnpDeviceId);
266
+ if (device === "1502" || device === "17f0") return xdnaInfoForDevice(device);
267
+ }
268
+ return null;
269
+ }
270
+ async function viaPowershell(run, systemRoot) {
271
+ const [file, args] = powershellInvocation(systemRoot);
272
+ const parsed = parsePowershellOutput(await run(file, args));
273
+ return {
274
+ gpu: classifyWindowsGpu(parsed.controllers),
275
+ npu: classifyWindowsAmdNpu(parsed.pnp),
276
+ source: "powershell"
277
+ };
278
+ }
279
+ async function viaWmic(run) {
280
+ const [video, amd] = await Promise.all([run("wmic", WMIC_VIDEO_ARGS), run("wmic", WMIC_AMD_PNP_ARGS).catch(() => "")]);
281
+ return {
282
+ gpu: classifyWindowsGpu(parseWmicCsv(video)),
283
+ npu: classifyWindowsAmdNpu(parseWmicCsv(amd)),
284
+ source: "wmic"
285
+ };
286
+ }
287
+ /**
288
+ * GPU + AMD NPU on a Windows host. NEVER throws: a probe that cannot run is
289
+ * `{ gpu: null, npu: null, source: 'none' }` and boot goes on — the node then
290
+ * scores as a CPU node, which is correct for hardware we could not see.
291
+ */
292
+ async function probeWindowsHardware(run, options = {}) {
293
+ try {
294
+ return await viaPowershell(run, options.systemRoot);
295
+ } catch (powershellError) {
296
+ options.onFallback?.(`PowerShell probe failed (${powershellError instanceof Error ? powershellError.message : String(powershellError)}); trying wmic`);
297
+ }
298
+ try {
299
+ return await viaWmic(run);
300
+ } catch (wmicError) {
301
+ options.onFallback?.(`wmic probe failed (${wmicError instanceof Error ? wmicError.message : String(wmicError)}); hardware unknown`);
302
+ return {
303
+ gpu: null,
304
+ npu: null,
305
+ source: "none"
306
+ };
307
+ }
308
+ }
309
+ //#endregion
62
310
  //#region src/builtins/platform-probe/platform-scorer.ts
311
+ /** WMI can be slow on a cold machine, but never worth stalling boot for. */
312
+ var WINDOWS_PROBE_TIMEOUT_MS = 15e3;
63
313
  /**
64
314
  * Promisified `execFile`. Used across the scorer so every subprocess
65
315
  * spawn yields the event loop — critical at boot because a single sync
@@ -237,24 +487,25 @@ var PlatformScorer = class {
237
487
  };
238
488
  npu = { type: "apple-ane" };
239
489
  }
490
+ if (platform === "win32") {
491
+ const nvidia = await this.probeNvidiaSmi();
492
+ const win = await this.probeWindowsHardwareSafely();
493
+ gpu = nvidia ?? win.gpu;
494
+ npu = win.npu;
495
+ if (gpu) this.logger.info("Windows GPU detected", { meta: {
496
+ type: gpu.type,
497
+ name: gpu.name
498
+ } });
499
+ if (npu && win.source !== "none") this.logger.info("AMD XDNA NPU detected (present only)", { meta: {
500
+ type: npu.type,
501
+ name: npu.name,
502
+ generation: npu.generation,
503
+ source: win.source
504
+ } });
505
+ }
240
506
  if (platform === "linux") {
241
- try {
242
- const { stdout } = await execFileAsync("nvidia-smi", ["--query-gpu=name,memory.total", "--format=csv,noheader"], {
243
- encoding: "utf8",
244
- timeout: 5e3
245
- });
246
- const output = stdout.trim();
247
- if (output) {
248
- const [name, mem] = output.split(",").map((s) => s.trim());
249
- gpu = {
250
- type: "nvidia",
251
- name: name ?? "NVIDIA GPU",
252
- memoryMB: parseInt(mem ?? "0")
253
- };
254
- }
255
- } catch (err) {
256
- this.logger.debug("NVIDIA GPU detection failed", { meta: { error: require_dist.errMsg(err) } });
257
- }
507
+ const nvidia = await this.probeNvidiaSmi();
508
+ if (nvidia) gpu = nvidia;
258
509
  const listRenderNodes = () => {
259
510
  try {
260
511
  return node_fs.readdirSync("/dev/dri").filter((n) => n.startsWith("renderD")).map((n) => `/dev/dri/${n}`);
@@ -313,7 +564,7 @@ var PlatformScorer = class {
313
564
  } });
314
565
  }
315
566
  if (!npu) {
316
- const { classifyAmdNpu } = await Promise.resolve().then(() => require("../../amd-npu-B-QyyMyF.js"));
567
+ const { classifyAmdNpu } = await Promise.resolve().then(() => amd_npu_exports);
317
568
  npu = classifyAmdNpu({
318
569
  platform,
319
570
  arch,
@@ -348,6 +599,53 @@ var PlatformScorer = class {
348
599
  coral
349
600
  };
350
601
  }
602
+ /** NVIDIA's own tool: exact model and VRAM. Null when absent or failing. */
603
+ async probeNvidiaSmi() {
604
+ try {
605
+ const { stdout } = await execFileAsync("nvidia-smi", ["--query-gpu=name,memory.total", "--format=csv,noheader"], {
606
+ encoding: "utf8",
607
+ timeout: 5e3,
608
+ windowsHide: true
609
+ });
610
+ const output = stdout.trim();
611
+ if (!output) return null;
612
+ const [name, mem] = output.split(",").map((s) => s.trim());
613
+ return {
614
+ type: "nvidia",
615
+ name: name ?? "NVIDIA GPU",
616
+ memoryMB: parseInt(mem ?? "0")
617
+ };
618
+ } catch (err) {
619
+ this.logger.debug("NVIDIA GPU detection failed", { meta: { error: require_dist.errMsg(err) } });
620
+ return null;
621
+ }
622
+ }
623
+ /** Windows WMI probe; bounded, and a failure is a log line, never a boot failure. */
624
+ async probeWindowsHardwareSafely() {
625
+ const run = async (file, args) => {
626
+ const { stdout } = await execFileAsync(file, [...args], {
627
+ encoding: "utf8",
628
+ timeout: WINDOWS_PROBE_TIMEOUT_MS,
629
+ windowsHide: true,
630
+ maxBuffer: 4 * 1024 * 1024
631
+ });
632
+ return stdout;
633
+ };
634
+ const systemRoot = process.env["SystemRoot"];
635
+ try {
636
+ return await probeWindowsHardware(run, {
637
+ ...systemRoot === void 0 ? {} : { systemRoot },
638
+ onFallback: (reason) => this.logger.warn("Windows hardware probe degraded", { meta: { reason } })
639
+ });
640
+ } catch (err) {
641
+ this.logger.warn("Windows hardware probe failed — scoring as a CPU node", { meta: { error: require_dist.errMsg(err) } });
642
+ return {
643
+ gpu: null,
644
+ npu: null,
645
+ source: "none"
646
+ };
647
+ }
648
+ }
351
649
  /**
352
650
  * Locates a Python interpreter without importing any module.
353
651
  *