@camstack/system 1.2.417 → 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.
- package/dist/addon-utils.js +1 -1
- package/dist/addon-utils.mjs +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
- package/dist/builtins/calendars/calendars.addon.js +1 -1
- package/dist/builtins/calendars/calendars.addon.mjs +1 -1
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/composer/composer.addon.js +2 -2
- package/dist/builtins/composer/composer.addon.mjs +2 -2
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
- package/dist/builtins/device-manager/device-manager.addon.js +2 -2
- package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/keychain/index.js +7 -9
- package/dist/builtins/keychain/index.mjs +7 -9
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +2 -2
- package/dist/builtins/local-auth/local-auth.addon.mjs +2 -2
- package/dist/builtins/local-network/local-network.addon.js +2 -2
- package/dist/builtins/local-network/local-network.addon.mjs +2 -2
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/amd-npu.d.ts +6 -0
- package/dist/builtins/platform-probe/index.js +317 -19
- package/dist/builtins/platform-probe/index.mjs +318 -20
- package/dist/builtins/platform-probe/platform-scorer.d.ts +4 -0
- package/dist/builtins/platform-probe/windows-hardware.d.ts +77 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-config/system-config.addon.js +2 -2
- package/dist/builtins/system-config/system-config.addon.mjs +2 -2
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{composition-sources-CndJVssc.mjs → composition-sources-0cPw9E0M.mjs} +1 -1
- package/dist/{composition-sources-ChAX2Kdo.js → composition-sources-BVjuMvpb.js} +1 -1
- package/dist/{constants-VXvZkGgw.js → constants-Aj0OBqlt.js} +1 -1
- package/dist/{constants-BzxwnfDc.mjs → constants-C8T7u1_Z.mjs} +1 -1
- package/dist/{custom-action-registry-DHv0kYcT.mjs → custom-action-registry-BQnbN0DP.mjs} +1 -2
- package/dist/{custom-action-registry-Bb28ibZV.js → custom-action-registry-Bf_YnagS.js} +3 -4
- package/dist/{dist-BMOD9OyH.js → dist-DVUg8e1T.js} +56 -72
- package/dist/{dist-H_RapIeM.mjs → dist-DlmdESNT.mjs} +57 -55
- package/dist/index.js +38 -10
- package/dist/index.mjs +38 -10
- package/dist/{jwt-signing-key-xQxqpwMC.mjs → jwt-signing-key-CGg61A5v.mjs} +1 -1
- package/dist/{jwt-signing-key-BiKHENST.js → jwt-signing-key-Jyu81jZR.js} +1 -1
- package/dist/{restore-archive-BobsETEp.js → restore-archive-Bq5PpQ-H.js} +1 -1
- package/dist/{restore-archive-CCAQicV-.mjs → restore-archive-DVo5ooBt.mjs} +1 -1
- package/dist/{retired-settings-keys-BMq2u4Wv.js → retired-settings-keys-CihMX6h9.js} +1 -1
- package/dist/{retired-settings-keys-CwL4zHLg.mjs → retired-settings-keys-k_XuC-Mt.mjs} +1 -1
- package/dist/{tls-C0TRPfqc.js → tls-BgImdxCO.js} +4 -11
- package/dist/{tls-D-2dPY-5.mjs → tls-CaOLZ09W.mjs} +5 -12
- package/package.json +1 -1
- package/dist/amd-npu-B-QyyMyF.js +0 -53
- package/dist/amd-npu-Db_SoSuL.mjs +0 -52
|
@@ -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-
|
|
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
|
-
|
|
242
|
-
|
|
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(() =>
|
|
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
|
*
|