@infersec/conduit 1.90.1 → 1.90.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +172 -53
- package/dist/cli.sea.cjs +172 -53
- package/dist/utils/machineInfo.d.ts +7 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -20042,16 +20042,16 @@ const InferenceAgentMachineMetadataSchema = object$1({
|
|
|
20042
20042
|
model: string$1().nullable(),
|
|
20043
20043
|
physicalCores: number$1().int().positive().nullable()
|
|
20044
20044
|
}),
|
|
20045
|
-
exllamav3Version: string$1().nullable(),
|
|
20045
|
+
exllamav3Version: string$1().nullable().default(null),
|
|
20046
20046
|
gpus: array(InferenceAgentMachineGPUSchema),
|
|
20047
20047
|
hostname: string$1(),
|
|
20048
|
-
llamaCppVersion: string$1().nullable(),
|
|
20048
|
+
llamaCppVersion: string$1().nullable().default(null),
|
|
20049
20049
|
machineID: string$1(),
|
|
20050
20050
|
memory: object$1({
|
|
20051
20051
|
availableBytes: number$1().int().nonnegative().nullable(),
|
|
20052
20052
|
totalBytes: number$1().int().nonnegative().nullable()
|
|
20053
20053
|
}),
|
|
20054
|
-
mlxlmVersion: string$1().nullable(),
|
|
20054
|
+
mlxlmVersion: string$1().nullable().default(null),
|
|
20055
20055
|
os: object$1({
|
|
20056
20056
|
arch: string$1(),
|
|
20057
20057
|
platform: string$1(),
|
|
@@ -20059,9 +20059,9 @@ const InferenceAgentMachineMetadataSchema = object$1({
|
|
|
20059
20059
|
type: string$1().nullable(),
|
|
20060
20060
|
version: string$1().nullable()
|
|
20061
20061
|
}),
|
|
20062
|
-
sglangVersion: string$1().nullable(),
|
|
20063
|
-
tensorrtLlmVersion: string$1().nullable(),
|
|
20064
|
-
vllmVersion: string$1().nullable()
|
|
20062
|
+
sglangVersion: string$1().nullable().default(null),
|
|
20063
|
+
tensorrtLlmVersion: string$1().nullable().default(null),
|
|
20064
|
+
vllmVersion: string$1().nullable().default(null)
|
|
20065
20065
|
});
|
|
20066
20066
|
const InferenceAgentMachineReportPayloadSchema = object$1({
|
|
20067
20067
|
machine: InferenceAgentMachineMetadataSchema
|
|
@@ -135290,7 +135290,12 @@ function normalizeMegabytes(value) {
|
|
|
135290
135290
|
function normalizeBusAddress(bus) {
|
|
135291
135291
|
if (!bus)
|
|
135292
135292
|
return null;
|
|
135293
|
-
|
|
135293
|
+
// PCI addresses arrive with varying domain widths across tools:
|
|
135294
|
+
// nvidia-smi "00000000:09:00.0", lspci/sysfs "0000:09:00.0",
|
|
135295
|
+
// systeminformation "09:00.0". Reduce all to the trailing "bus:device.function"
|
|
135296
|
+
// so the same GPU matches across sources.
|
|
135297
|
+
const match = bus.toLowerCase().match(/([0-9a-f]{1,2}:[0-9a-f]{2}\.[0-9a-f])$/);
|
|
135298
|
+
return match ? match[1] : bus.toLowerCase();
|
|
135294
135299
|
}
|
|
135295
135300
|
function resolveCpuValue(value) {
|
|
135296
135301
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -135438,76 +135443,184 @@ async function detectVRAMViaRocmSmi() {
|
|
|
135438
135443
|
return [];
|
|
135439
135444
|
}
|
|
135440
135445
|
}
|
|
135441
|
-
|
|
135442
|
-
|
|
135443
|
-
|
|
135444
|
-
|
|
135445
|
-
|
|
135446
|
-
|
|
135447
|
-
|
|
135446
|
+
const NVIDIA_SMI_TIMEOUT_MS$1 = 10_000;
|
|
135447
|
+
function parseNvidiaSmiNumber(value) {
|
|
135448
|
+
if (!value)
|
|
135449
|
+
return null;
|
|
135450
|
+
// Unified-memory devices (e.g. NVIDIA GB10) report "[N/A]"; treat as unknown
|
|
135451
|
+
const parsed = parseInt(value, 10);
|
|
135452
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : null;
|
|
135453
|
+
}
|
|
135454
|
+
function parseNvidiaSmiMemoryBytes(value) {
|
|
135455
|
+
const mib = parseNvidiaSmiNumber(value);
|
|
135456
|
+
return mib !== null ? normalizeMegabytes(mib) : null;
|
|
135457
|
+
}
|
|
135458
|
+
async function readSystemMemoryBytes({ logger }) {
|
|
135459
|
+
try {
|
|
135460
|
+
const contents = await readFile("/proc/meminfo", "utf8");
|
|
135461
|
+
let availableBytes = null;
|
|
135462
|
+
let totalBytes = null;
|
|
135463
|
+
for (const line of contents.split("\n")) {
|
|
135464
|
+
const match = line.match(/^(MemTotal|MemAvailable):\s+(\d+)\s*kB/i);
|
|
135465
|
+
if (!match)
|
|
135466
|
+
continue;
|
|
135467
|
+
const bytes = parseInt(match[2], 10) * 1024;
|
|
135468
|
+
if (match[1].toLowerCase() === "memtotal") {
|
|
135469
|
+
totalBytes = bytes;
|
|
135470
|
+
}
|
|
135471
|
+
else {
|
|
135472
|
+
availableBytes = bytes;
|
|
135473
|
+
}
|
|
135474
|
+
}
|
|
135475
|
+
return { availableBytes, totalBytes };
|
|
135476
|
+
}
|
|
135477
|
+
catch (error) {
|
|
135478
|
+
logger.debug("Failed to read system memory", { error: asError(error) });
|
|
135479
|
+
return { availableBytes: null, totalBytes: null };
|
|
135480
|
+
}
|
|
135481
|
+
}
|
|
135482
|
+
async function detectGPUsViaNvidiaSmi({ logger }) {
|
|
135483
|
+
try {
|
|
135484
|
+
const { stdout } = await execa("nvidia-smi", [
|
|
135485
|
+
"--query-gpu=name,pci.bus_id,driver_version,memory.total,memory.used,memory.free,temperature.gpu",
|
|
135486
|
+
"--format=csv,noheader,nounits"
|
|
135487
|
+
], { timeout: NVIDIA_SMI_TIMEOUT_MS$1 });
|
|
135488
|
+
const lines = stdout.split("\n").filter(line => line.trim().length > 0);
|
|
135489
|
+
const gpus = [];
|
|
135490
|
+
for (const line of lines) {
|
|
135491
|
+
const [name, bus, driverVersion, memTotal, memUsed, memFree, temperature] = line
|
|
135492
|
+
.split(",")
|
|
135493
|
+
.map(part => part.trim());
|
|
135494
|
+
gpus.push({
|
|
135495
|
+
bus: normalizeBusAddress(bus),
|
|
135496
|
+
driverVersion: driverVersion || null,
|
|
135497
|
+
memoryFreeBytes: parseNvidiaSmiMemoryBytes(memFree),
|
|
135498
|
+
memoryTotalBytes: parseNvidiaSmiMemoryBytes(memTotal),
|
|
135499
|
+
memoryUsedBytes: parseNvidiaSmiMemoryBytes(memUsed),
|
|
135500
|
+
model: name || null,
|
|
135501
|
+
temperatureCelsius: parseNvidiaSmiNumber(temperature),
|
|
135502
|
+
vendor: "NVIDIA"
|
|
135503
|
+
});
|
|
135504
|
+
}
|
|
135505
|
+
// Unified-memory devices (e.g. NVIDIA GB10 on DGX Spark) report "[N/A]" for
|
|
135506
|
+
// memory. Their compute pool is system RAM, so fall back to /proc/meminfo.
|
|
135507
|
+
if (gpus.some(gpu => gpu.memoryTotalBytes === null)) {
|
|
135508
|
+
const systemMemory = await readSystemMemoryBytes({ logger });
|
|
135509
|
+
const total = systemMemory.totalBytes;
|
|
135510
|
+
if (total !== null) {
|
|
135511
|
+
const free = systemMemory.availableBytes;
|
|
135512
|
+
const used = free !== null ? total - free : null;
|
|
135513
|
+
for (const gpu of gpus) {
|
|
135514
|
+
if (gpu.memoryTotalBytes !== null)
|
|
135515
|
+
continue;
|
|
135516
|
+
gpu.memoryFreeBytes = free;
|
|
135517
|
+
gpu.memoryTotalBytes = total;
|
|
135518
|
+
gpu.memoryUsedBytes = used;
|
|
135519
|
+
}
|
|
135520
|
+
}
|
|
135521
|
+
}
|
|
135522
|
+
return gpus;
|
|
135448
135523
|
}
|
|
135524
|
+
catch (error) {
|
|
135525
|
+
logger.debug("nvidia-smi GPU query failed", { error: asError(error) });
|
|
135526
|
+
return [];
|
|
135527
|
+
}
|
|
135528
|
+
}
|
|
135529
|
+
function buildMergedGPUs(options) {
|
|
135530
|
+
const { lspciGPUs, nvidiaGPUs, rocmVRAM, siGPUs, sysfsVRAMMap } = options;
|
|
135449
135531
|
const rocmByBus = new Map();
|
|
135450
135532
|
for (const entry of rocmVRAM) {
|
|
135451
135533
|
const key = normalizeBusAddress(entry.bus);
|
|
135452
135534
|
if (key)
|
|
135453
135535
|
rocmByBus.set(key, entry);
|
|
135454
135536
|
}
|
|
135455
|
-
const
|
|
135456
|
-
|
|
135537
|
+
const byBus = new Map();
|
|
135538
|
+
// Priority 1 — nvidia-smi: authoritative for NVIDIA (name, driver, VRAM, temp, bus)
|
|
135539
|
+
for (const gpu of nvidiaGPUs) {
|
|
135540
|
+
const key = normalizeBusAddress(gpu.bus);
|
|
135541
|
+
if (key)
|
|
135542
|
+
byBus.set(key, gpu);
|
|
135543
|
+
}
|
|
135544
|
+
// Priority 2 — systeminformation: catches GPUs nvidia-smi doesn't see and
|
|
135545
|
+
// enriches existing entries with temperature
|
|
135546
|
+
for (const gpu of siGPUs) {
|
|
135547
|
+
const key = normalizeBusAddress(gpu.bus);
|
|
135548
|
+
if (!key)
|
|
135549
|
+
continue;
|
|
135550
|
+
const existing = byBus.get(key);
|
|
135551
|
+
if (existing) {
|
|
135552
|
+
if (existing.temperatureCelsius === null && gpu.temperatureCelsius !== null) {
|
|
135553
|
+
existing.temperatureCelsius = gpu.temperatureCelsius;
|
|
135554
|
+
}
|
|
135555
|
+
continue;
|
|
135556
|
+
}
|
|
135557
|
+
byBus.set(key, gpu);
|
|
135558
|
+
}
|
|
135559
|
+
// Priority 3 — lspci: enumerates AMD/other GPUs and supplies VRAM via sysfs/rocm-smi
|
|
135457
135560
|
for (const lspciGPU of lspciGPUs) {
|
|
135458
135561
|
const key = normalizeBusAddress(lspciGPU.bus);
|
|
135459
|
-
if (!key
|
|
135562
|
+
if (!key)
|
|
135460
135563
|
continue;
|
|
135461
|
-
|
|
135462
|
-
const existing = siByBus.get(key);
|
|
135564
|
+
const existing = byBus.get(key);
|
|
135463
135565
|
if (existing) {
|
|
135464
135566
|
if (existing.memoryTotalBytes === null) {
|
|
135465
|
-
|
|
135466
|
-
|
|
135467
|
-
|
|
135468
|
-
|
|
135469
|
-
|
|
135470
|
-
|
|
135471
|
-
existing.memoryTotalBytes = sysfsTotal;
|
|
135472
|
-
existing.memoryUsedBytes = validSysfsUsed ? sysfsUsed : null;
|
|
135473
|
-
existing.memoryFreeBytes =
|
|
135474
|
-
validSysfsUsed && sysfsUsed !== null ? sysfsTotal - sysfsUsed : null;
|
|
135475
|
-
}
|
|
135567
|
+
applySysfsOrRocmVRAM({
|
|
135568
|
+
gpu: existing,
|
|
135569
|
+
key,
|
|
135570
|
+
rocmByBus,
|
|
135571
|
+
sysfsVRAMMap
|
|
135572
|
+
});
|
|
135476
135573
|
}
|
|
135477
135574
|
continue;
|
|
135478
135575
|
}
|
|
135479
|
-
const
|
|
135480
|
-
|
|
135481
|
-
let usedBytes = sysfs?.memoryUsedBytes ?? null;
|
|
135482
|
-
if (totalBytes === null) {
|
|
135483
|
-
const rocm = rocmByBus.get(key);
|
|
135484
|
-
if (rocm) {
|
|
135485
|
-
totalBytes = rocm.memoryTotalBytes;
|
|
135486
|
-
usedBytes = rocm.memoryUsedBytes;
|
|
135487
|
-
}
|
|
135488
|
-
}
|
|
135489
|
-
merged.push({
|
|
135490
|
-
bus: lspciGPU.bus,
|
|
135576
|
+
const gpu = {
|
|
135577
|
+
bus: normalizeBusAddress(lspciGPU.bus),
|
|
135491
135578
|
driverVersion: null,
|
|
135492
|
-
memoryFreeBytes:
|
|
135493
|
-
|
|
135494
|
-
|
|
135495
|
-
memoryTotalBytes: totalBytes,
|
|
135496
|
-
memoryUsedBytes: usedBytes !== null && Number.isFinite(usedBytes) ? usedBytes : null,
|
|
135579
|
+
memoryFreeBytes: null,
|
|
135580
|
+
memoryTotalBytes: null,
|
|
135581
|
+
memoryUsedBytes: null,
|
|
135497
135582
|
model: lspciGPU.model,
|
|
135498
135583
|
temperatureCelsius: null,
|
|
135499
135584
|
vendor: lspciGPU.vendor
|
|
135585
|
+
};
|
|
135586
|
+
applySysfsOrRocmVRAM({
|
|
135587
|
+
gpu,
|
|
135588
|
+
key,
|
|
135589
|
+
rocmByBus,
|
|
135590
|
+
sysfsVRAMMap
|
|
135500
135591
|
});
|
|
135592
|
+
byBus.set(key, gpu);
|
|
135501
135593
|
}
|
|
135502
|
-
return
|
|
135594
|
+
return [...byBus.values()];
|
|
135503
135595
|
}
|
|
135504
|
-
|
|
135505
|
-
const
|
|
135596
|
+
function applySysfsOrRocmVRAM({ gpu, key, rocmByBus, sysfsVRAMMap }) {
|
|
135597
|
+
const sysfs = sysfsVRAMMap.get(key);
|
|
135598
|
+
let totalBytes = sysfs?.memoryTotalBytes ?? null;
|
|
135599
|
+
let usedBytes = sysfs?.memoryUsedBytes ?? null;
|
|
135600
|
+
if (totalBytes === null) {
|
|
135601
|
+
const rocm = rocmByBus.get(key);
|
|
135602
|
+
if (rocm) {
|
|
135603
|
+
totalBytes = rocm.memoryTotalBytes;
|
|
135604
|
+
usedBytes = rocm.memoryUsedBytes;
|
|
135605
|
+
}
|
|
135606
|
+
}
|
|
135607
|
+
if (totalBytes === null || !Number.isFinite(totalBytes))
|
|
135608
|
+
return;
|
|
135609
|
+
gpu.memoryTotalBytes = totalBytes;
|
|
135610
|
+
gpu.memoryUsedBytes = usedBytes !== null && Number.isFinite(usedBytes) ? usedBytes : null;
|
|
135611
|
+
gpu.memoryFreeBytes =
|
|
135612
|
+
usedBytes !== null && Number.isFinite(usedBytes)
|
|
135613
|
+
? Math.max(totalBytes - usedBytes, 0)
|
|
135614
|
+
: null;
|
|
135615
|
+
}
|
|
135616
|
+
async function collectMachineMetadata({ logger }) {
|
|
135617
|
+
const [cpuResult, memResult, osResult, graphicsResult, lspciGPUs, nvidiaGPUs, rocmVRAM] = await Promise.allSettled([
|
|
135506
135618
|
si.cpu(),
|
|
135507
135619
|
si.mem(),
|
|
135508
135620
|
si.osInfo(),
|
|
135509
135621
|
si.graphics(),
|
|
135510
135622
|
detectGPUsViaLspci(),
|
|
135623
|
+
detectGPUsViaNvidiaSmi({ logger }),
|
|
135511
135624
|
detectVRAMViaRocmSmi()
|
|
135512
135625
|
]);
|
|
135513
135626
|
const cpuInfo = cpuResult.status === "fulfilled" ? cpuResult.value : null;
|
|
@@ -135517,13 +135630,14 @@ async function collectMachineMetadata() {
|
|
|
135517
135630
|
? graphicsResult.value
|
|
135518
135631
|
: { controllers: [] };
|
|
135519
135632
|
const resolvedLspciGPUs = lspciGPUs.status === "fulfilled" ? lspciGPUs.value : [];
|
|
135633
|
+
const resolvedNvidiaGPUs = nvidiaGPUs.status === "fulfilled" ? nvidiaGPUs.value : [];
|
|
135520
135634
|
const resolvedRocmVRAM = rocmVRAM.status === "fulfilled" ? rocmVRAM.value : [];
|
|
135521
135635
|
const siGPUs = (graphicsInfo.controllers ?? []).map((controller) => {
|
|
135522
135636
|
const totalBytes = normalizeMegabytes(controller.memoryTotal ?? null);
|
|
135523
135637
|
const freeBytes = normalizeMegabytes(controller.memoryFree ?? null);
|
|
135524
135638
|
const usedBytes = totalBytes !== null && freeBytes !== null ? totalBytes - freeBytes : null;
|
|
135525
135639
|
return {
|
|
135526
|
-
bus: controller.bus ?? null,
|
|
135640
|
+
bus: normalizeBusAddress(controller.pciBus ?? controller.busAddress ?? controller.bus ?? null),
|
|
135527
135641
|
driverVersion: controller.driverVersion ?? null,
|
|
135528
135642
|
memoryFreeBytes: freeBytes,
|
|
135529
135643
|
memoryTotalBytes: totalBytes,
|
|
@@ -135537,6 +135651,10 @@ async function collectMachineMetadata() {
|
|
|
135537
135651
|
for (const lspciGPU of resolvedLspciGPUs) {
|
|
135538
135652
|
busSources.add(lspciGPU.bus);
|
|
135539
135653
|
}
|
|
135654
|
+
for (const nvidiaGPU of resolvedNvidiaGPUs) {
|
|
135655
|
+
if (nvidiaGPU.bus)
|
|
135656
|
+
busSources.add(nvidiaGPU.bus);
|
|
135657
|
+
}
|
|
135540
135658
|
for (const siGPU of siGPUs) {
|
|
135541
135659
|
if (siGPU.bus)
|
|
135542
135660
|
busSources.add(siGPU.bus);
|
|
@@ -135555,6 +135673,7 @@ async function collectMachineMetadata() {
|
|
|
135555
135673
|
}
|
|
135556
135674
|
const gpus = buildMergedGPUs({
|
|
135557
135675
|
lspciGPUs: resolvedLspciGPUs,
|
|
135676
|
+
nvidiaGPUs: resolvedNvidiaGPUs,
|
|
135558
135677
|
rocmVRAM: resolvedRocmVRAM,
|
|
135559
135678
|
siGPUs,
|
|
135560
135679
|
sysfsVRAMMap
|
|
@@ -135612,7 +135731,7 @@ async function createApplication({ abortController, apiClient, configuration, lo
|
|
|
135612
135731
|
});
|
|
135613
135732
|
let machine = null;
|
|
135614
135733
|
try {
|
|
135615
|
-
machine = await collectMachineMetadata();
|
|
135734
|
+
machine = await collectMachineMetadata({ logger });
|
|
135616
135735
|
logger.info("Detected machine hardware", {
|
|
135617
135736
|
gpuCount: machine.gpus.length
|
|
135618
135737
|
});
|
|
@@ -135645,7 +135764,7 @@ async function createApplication({ abortController, apiClient, configuration, lo
|
|
|
135645
135764
|
let modelManager = createModelManagerFromConfig(conduitConfiguration, configuration, logger);
|
|
135646
135765
|
const conduitStateReportManager = new ConduitStateReportManager({
|
|
135647
135766
|
apiClient,
|
|
135648
|
-
collectMachineMetadata: collectMachineMetadata,
|
|
135767
|
+
collectMachineMetadata: () => collectMachineMetadata({ logger }),
|
|
135649
135768
|
conduitStateManager,
|
|
135650
135769
|
downloadProgressReportIntervalMs: 5000,
|
|
135651
135770
|
logger,
|
package/dist/cli.sea.cjs
CHANGED
|
@@ -20056,16 +20056,16 @@ const InferenceAgentMachineMetadataSchema = object$1({
|
|
|
20056
20056
|
model: string$1().nullable(),
|
|
20057
20057
|
physicalCores: number$1().int().positive().nullable()
|
|
20058
20058
|
}),
|
|
20059
|
-
exllamav3Version: string$1().nullable(),
|
|
20059
|
+
exllamav3Version: string$1().nullable().default(null),
|
|
20060
20060
|
gpus: array(InferenceAgentMachineGPUSchema),
|
|
20061
20061
|
hostname: string$1(),
|
|
20062
|
-
llamaCppVersion: string$1().nullable(),
|
|
20062
|
+
llamaCppVersion: string$1().nullable().default(null),
|
|
20063
20063
|
machineID: string$1(),
|
|
20064
20064
|
memory: object$1({
|
|
20065
20065
|
availableBytes: number$1().int().nonnegative().nullable(),
|
|
20066
20066
|
totalBytes: number$1().int().nonnegative().nullable()
|
|
20067
20067
|
}),
|
|
20068
|
-
mlxlmVersion: string$1().nullable(),
|
|
20068
|
+
mlxlmVersion: string$1().nullable().default(null),
|
|
20069
20069
|
os: object$1({
|
|
20070
20070
|
arch: string$1(),
|
|
20071
20071
|
platform: string$1(),
|
|
@@ -20073,9 +20073,9 @@ const InferenceAgentMachineMetadataSchema = object$1({
|
|
|
20073
20073
|
type: string$1().nullable(),
|
|
20074
20074
|
version: string$1().nullable()
|
|
20075
20075
|
}),
|
|
20076
|
-
sglangVersion: string$1().nullable(),
|
|
20077
|
-
tensorrtLlmVersion: string$1().nullable(),
|
|
20078
|
-
vllmVersion: string$1().nullable()
|
|
20076
|
+
sglangVersion: string$1().nullable().default(null),
|
|
20077
|
+
tensorrtLlmVersion: string$1().nullable().default(null),
|
|
20078
|
+
vllmVersion: string$1().nullable().default(null)
|
|
20079
20079
|
});
|
|
20080
20080
|
const InferenceAgentMachineReportPayloadSchema = object$1({
|
|
20081
20081
|
machine: InferenceAgentMachineMetadataSchema
|
|
@@ -155519,7 +155519,12 @@ function normalizeMegabytes(value) {
|
|
|
155519
155519
|
function normalizeBusAddress(bus) {
|
|
155520
155520
|
if (!bus)
|
|
155521
155521
|
return null;
|
|
155522
|
-
|
|
155522
|
+
// PCI addresses arrive with varying domain widths across tools:
|
|
155523
|
+
// nvidia-smi "00000000:09:00.0", lspci/sysfs "0000:09:00.0",
|
|
155524
|
+
// systeminformation "09:00.0". Reduce all to the trailing "bus:device.function"
|
|
155525
|
+
// so the same GPU matches across sources.
|
|
155526
|
+
const match = bus.toLowerCase().match(/([0-9a-f]{1,2}:[0-9a-f]{2}\.[0-9a-f])$/);
|
|
155527
|
+
return match ? match[1] : bus.toLowerCase();
|
|
155523
155528
|
}
|
|
155524
155529
|
function resolveCpuValue(value) {
|
|
155525
155530
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -155667,76 +155672,184 @@ async function detectVRAMViaRocmSmi() {
|
|
|
155667
155672
|
return [];
|
|
155668
155673
|
}
|
|
155669
155674
|
}
|
|
155670
|
-
|
|
155671
|
-
|
|
155672
|
-
|
|
155673
|
-
|
|
155674
|
-
|
|
155675
|
-
|
|
155676
|
-
|
|
155675
|
+
const NVIDIA_SMI_TIMEOUT_MS$1 = 10_000;
|
|
155676
|
+
function parseNvidiaSmiNumber(value) {
|
|
155677
|
+
if (!value)
|
|
155678
|
+
return null;
|
|
155679
|
+
// Unified-memory devices (e.g. NVIDIA GB10) report "[N/A]"; treat as unknown
|
|
155680
|
+
const parsed = parseInt(value, 10);
|
|
155681
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : null;
|
|
155682
|
+
}
|
|
155683
|
+
function parseNvidiaSmiMemoryBytes(value) {
|
|
155684
|
+
const mib = parseNvidiaSmiNumber(value);
|
|
155685
|
+
return mib !== null ? normalizeMegabytes(mib) : null;
|
|
155686
|
+
}
|
|
155687
|
+
async function readSystemMemoryBytes({ logger }) {
|
|
155688
|
+
try {
|
|
155689
|
+
const contents = await require$$0$d.readFile("/proc/meminfo", "utf8");
|
|
155690
|
+
let availableBytes = null;
|
|
155691
|
+
let totalBytes = null;
|
|
155692
|
+
for (const line of contents.split("\n")) {
|
|
155693
|
+
const match = line.match(/^(MemTotal|MemAvailable):\s+(\d+)\s*kB/i);
|
|
155694
|
+
if (!match)
|
|
155695
|
+
continue;
|
|
155696
|
+
const bytes = parseInt(match[2], 10) * 1024;
|
|
155697
|
+
if (match[1].toLowerCase() === "memtotal") {
|
|
155698
|
+
totalBytes = bytes;
|
|
155699
|
+
}
|
|
155700
|
+
else {
|
|
155701
|
+
availableBytes = bytes;
|
|
155702
|
+
}
|
|
155703
|
+
}
|
|
155704
|
+
return { availableBytes, totalBytes };
|
|
155705
|
+
}
|
|
155706
|
+
catch (error) {
|
|
155707
|
+
logger.debug("Failed to read system memory", { error: asError(error) });
|
|
155708
|
+
return { availableBytes: null, totalBytes: null };
|
|
155709
|
+
}
|
|
155710
|
+
}
|
|
155711
|
+
async function detectGPUsViaNvidiaSmi({ logger }) {
|
|
155712
|
+
try {
|
|
155713
|
+
const { stdout } = await execa("nvidia-smi", [
|
|
155714
|
+
"--query-gpu=name,pci.bus_id,driver_version,memory.total,memory.used,memory.free,temperature.gpu",
|
|
155715
|
+
"--format=csv,noheader,nounits"
|
|
155716
|
+
], { timeout: NVIDIA_SMI_TIMEOUT_MS$1 });
|
|
155717
|
+
const lines = stdout.split("\n").filter(line => line.trim().length > 0);
|
|
155718
|
+
const gpus = [];
|
|
155719
|
+
for (const line of lines) {
|
|
155720
|
+
const [name, bus, driverVersion, memTotal, memUsed, memFree, temperature] = line
|
|
155721
|
+
.split(",")
|
|
155722
|
+
.map(part => part.trim());
|
|
155723
|
+
gpus.push({
|
|
155724
|
+
bus: normalizeBusAddress(bus),
|
|
155725
|
+
driverVersion: driverVersion || null,
|
|
155726
|
+
memoryFreeBytes: parseNvidiaSmiMemoryBytes(memFree),
|
|
155727
|
+
memoryTotalBytes: parseNvidiaSmiMemoryBytes(memTotal),
|
|
155728
|
+
memoryUsedBytes: parseNvidiaSmiMemoryBytes(memUsed),
|
|
155729
|
+
model: name || null,
|
|
155730
|
+
temperatureCelsius: parseNvidiaSmiNumber(temperature),
|
|
155731
|
+
vendor: "NVIDIA"
|
|
155732
|
+
});
|
|
155733
|
+
}
|
|
155734
|
+
// Unified-memory devices (e.g. NVIDIA GB10 on DGX Spark) report "[N/A]" for
|
|
155735
|
+
// memory. Their compute pool is system RAM, so fall back to /proc/meminfo.
|
|
155736
|
+
if (gpus.some(gpu => gpu.memoryTotalBytes === null)) {
|
|
155737
|
+
const systemMemory = await readSystemMemoryBytes({ logger });
|
|
155738
|
+
const total = systemMemory.totalBytes;
|
|
155739
|
+
if (total !== null) {
|
|
155740
|
+
const free = systemMemory.availableBytes;
|
|
155741
|
+
const used = free !== null ? total - free : null;
|
|
155742
|
+
for (const gpu of gpus) {
|
|
155743
|
+
if (gpu.memoryTotalBytes !== null)
|
|
155744
|
+
continue;
|
|
155745
|
+
gpu.memoryFreeBytes = free;
|
|
155746
|
+
gpu.memoryTotalBytes = total;
|
|
155747
|
+
gpu.memoryUsedBytes = used;
|
|
155748
|
+
}
|
|
155749
|
+
}
|
|
155750
|
+
}
|
|
155751
|
+
return gpus;
|
|
155677
155752
|
}
|
|
155753
|
+
catch (error) {
|
|
155754
|
+
logger.debug("nvidia-smi GPU query failed", { error: asError(error) });
|
|
155755
|
+
return [];
|
|
155756
|
+
}
|
|
155757
|
+
}
|
|
155758
|
+
function buildMergedGPUs(options) {
|
|
155759
|
+
const { lspciGPUs, nvidiaGPUs, rocmVRAM, siGPUs, sysfsVRAMMap } = options;
|
|
155678
155760
|
const rocmByBus = new Map();
|
|
155679
155761
|
for (const entry of rocmVRAM) {
|
|
155680
155762
|
const key = normalizeBusAddress(entry.bus);
|
|
155681
155763
|
if (key)
|
|
155682
155764
|
rocmByBus.set(key, entry);
|
|
155683
155765
|
}
|
|
155684
|
-
const
|
|
155685
|
-
|
|
155766
|
+
const byBus = new Map();
|
|
155767
|
+
// Priority 1 — nvidia-smi: authoritative for NVIDIA (name, driver, VRAM, temp, bus)
|
|
155768
|
+
for (const gpu of nvidiaGPUs) {
|
|
155769
|
+
const key = normalizeBusAddress(gpu.bus);
|
|
155770
|
+
if (key)
|
|
155771
|
+
byBus.set(key, gpu);
|
|
155772
|
+
}
|
|
155773
|
+
// Priority 2 — systeminformation: catches GPUs nvidia-smi doesn't see and
|
|
155774
|
+
// enriches existing entries with temperature
|
|
155775
|
+
for (const gpu of siGPUs) {
|
|
155776
|
+
const key = normalizeBusAddress(gpu.bus);
|
|
155777
|
+
if (!key)
|
|
155778
|
+
continue;
|
|
155779
|
+
const existing = byBus.get(key);
|
|
155780
|
+
if (existing) {
|
|
155781
|
+
if (existing.temperatureCelsius === null && gpu.temperatureCelsius !== null) {
|
|
155782
|
+
existing.temperatureCelsius = gpu.temperatureCelsius;
|
|
155783
|
+
}
|
|
155784
|
+
continue;
|
|
155785
|
+
}
|
|
155786
|
+
byBus.set(key, gpu);
|
|
155787
|
+
}
|
|
155788
|
+
// Priority 3 — lspci: enumerates AMD/other GPUs and supplies VRAM via sysfs/rocm-smi
|
|
155686
155789
|
for (const lspciGPU of lspciGPUs) {
|
|
155687
155790
|
const key = normalizeBusAddress(lspciGPU.bus);
|
|
155688
|
-
if (!key
|
|
155791
|
+
if (!key)
|
|
155689
155792
|
continue;
|
|
155690
|
-
|
|
155691
|
-
const existing = siByBus.get(key);
|
|
155793
|
+
const existing = byBus.get(key);
|
|
155692
155794
|
if (existing) {
|
|
155693
155795
|
if (existing.memoryTotalBytes === null) {
|
|
155694
|
-
|
|
155695
|
-
|
|
155696
|
-
|
|
155697
|
-
|
|
155698
|
-
|
|
155699
|
-
|
|
155700
|
-
existing.memoryTotalBytes = sysfsTotal;
|
|
155701
|
-
existing.memoryUsedBytes = validSysfsUsed ? sysfsUsed : null;
|
|
155702
|
-
existing.memoryFreeBytes =
|
|
155703
|
-
validSysfsUsed && sysfsUsed !== null ? sysfsTotal - sysfsUsed : null;
|
|
155704
|
-
}
|
|
155796
|
+
applySysfsOrRocmVRAM({
|
|
155797
|
+
gpu: existing,
|
|
155798
|
+
key,
|
|
155799
|
+
rocmByBus,
|
|
155800
|
+
sysfsVRAMMap
|
|
155801
|
+
});
|
|
155705
155802
|
}
|
|
155706
155803
|
continue;
|
|
155707
155804
|
}
|
|
155708
|
-
const
|
|
155709
|
-
|
|
155710
|
-
let usedBytes = sysfs?.memoryUsedBytes ?? null;
|
|
155711
|
-
if (totalBytes === null) {
|
|
155712
|
-
const rocm = rocmByBus.get(key);
|
|
155713
|
-
if (rocm) {
|
|
155714
|
-
totalBytes = rocm.memoryTotalBytes;
|
|
155715
|
-
usedBytes = rocm.memoryUsedBytes;
|
|
155716
|
-
}
|
|
155717
|
-
}
|
|
155718
|
-
merged.push({
|
|
155719
|
-
bus: lspciGPU.bus,
|
|
155805
|
+
const gpu = {
|
|
155806
|
+
bus: normalizeBusAddress(lspciGPU.bus),
|
|
155720
155807
|
driverVersion: null,
|
|
155721
|
-
memoryFreeBytes:
|
|
155722
|
-
|
|
155723
|
-
|
|
155724
|
-
memoryTotalBytes: totalBytes,
|
|
155725
|
-
memoryUsedBytes: usedBytes !== null && Number.isFinite(usedBytes) ? usedBytes : null,
|
|
155808
|
+
memoryFreeBytes: null,
|
|
155809
|
+
memoryTotalBytes: null,
|
|
155810
|
+
memoryUsedBytes: null,
|
|
155726
155811
|
model: lspciGPU.model,
|
|
155727
155812
|
temperatureCelsius: null,
|
|
155728
155813
|
vendor: lspciGPU.vendor
|
|
155814
|
+
};
|
|
155815
|
+
applySysfsOrRocmVRAM({
|
|
155816
|
+
gpu,
|
|
155817
|
+
key,
|
|
155818
|
+
rocmByBus,
|
|
155819
|
+
sysfsVRAMMap
|
|
155729
155820
|
});
|
|
155821
|
+
byBus.set(key, gpu);
|
|
155730
155822
|
}
|
|
155731
|
-
return
|
|
155823
|
+
return [...byBus.values()];
|
|
155732
155824
|
}
|
|
155733
|
-
|
|
155734
|
-
const
|
|
155825
|
+
function applySysfsOrRocmVRAM({ gpu, key, rocmByBus, sysfsVRAMMap }) {
|
|
155826
|
+
const sysfs = sysfsVRAMMap.get(key);
|
|
155827
|
+
let totalBytes = sysfs?.memoryTotalBytes ?? null;
|
|
155828
|
+
let usedBytes = sysfs?.memoryUsedBytes ?? null;
|
|
155829
|
+
if (totalBytes === null) {
|
|
155830
|
+
const rocm = rocmByBus.get(key);
|
|
155831
|
+
if (rocm) {
|
|
155832
|
+
totalBytes = rocm.memoryTotalBytes;
|
|
155833
|
+
usedBytes = rocm.memoryUsedBytes;
|
|
155834
|
+
}
|
|
155835
|
+
}
|
|
155836
|
+
if (totalBytes === null || !Number.isFinite(totalBytes))
|
|
155837
|
+
return;
|
|
155838
|
+
gpu.memoryTotalBytes = totalBytes;
|
|
155839
|
+
gpu.memoryUsedBytes = usedBytes !== null && Number.isFinite(usedBytes) ? usedBytes : null;
|
|
155840
|
+
gpu.memoryFreeBytes =
|
|
155841
|
+
usedBytes !== null && Number.isFinite(usedBytes)
|
|
155842
|
+
? Math.max(totalBytes - usedBytes, 0)
|
|
155843
|
+
: null;
|
|
155844
|
+
}
|
|
155845
|
+
async function collectMachineMetadata({ logger }) {
|
|
155846
|
+
const [cpuResult, memResult, osResult, graphicsResult, lspciGPUs, nvidiaGPUs, rocmVRAM] = await Promise.allSettled([
|
|
155735
155847
|
si.cpu(),
|
|
155736
155848
|
si.mem(),
|
|
155737
155849
|
si.osInfo(),
|
|
155738
155850
|
si.graphics(),
|
|
155739
155851
|
detectGPUsViaLspci(),
|
|
155852
|
+
detectGPUsViaNvidiaSmi({ logger }),
|
|
155740
155853
|
detectVRAMViaRocmSmi()
|
|
155741
155854
|
]);
|
|
155742
155855
|
const cpuInfo = cpuResult.status === "fulfilled" ? cpuResult.value : null;
|
|
@@ -155746,13 +155859,14 @@ async function collectMachineMetadata() {
|
|
|
155746
155859
|
? graphicsResult.value
|
|
155747
155860
|
: { controllers: [] };
|
|
155748
155861
|
const resolvedLspciGPUs = lspciGPUs.status === "fulfilled" ? lspciGPUs.value : [];
|
|
155862
|
+
const resolvedNvidiaGPUs = nvidiaGPUs.status === "fulfilled" ? nvidiaGPUs.value : [];
|
|
155749
155863
|
const resolvedRocmVRAM = rocmVRAM.status === "fulfilled" ? rocmVRAM.value : [];
|
|
155750
155864
|
const siGPUs = (graphicsInfo.controllers ?? []).map((controller) => {
|
|
155751
155865
|
const totalBytes = normalizeMegabytes(controller.memoryTotal ?? null);
|
|
155752
155866
|
const freeBytes = normalizeMegabytes(controller.memoryFree ?? null);
|
|
155753
155867
|
const usedBytes = totalBytes !== null && freeBytes !== null ? totalBytes - freeBytes : null;
|
|
155754
155868
|
return {
|
|
155755
|
-
bus: controller.bus ?? null,
|
|
155869
|
+
bus: normalizeBusAddress(controller.pciBus ?? controller.busAddress ?? controller.bus ?? null),
|
|
155756
155870
|
driverVersion: controller.driverVersion ?? null,
|
|
155757
155871
|
memoryFreeBytes: freeBytes,
|
|
155758
155872
|
memoryTotalBytes: totalBytes,
|
|
@@ -155766,6 +155880,10 @@ async function collectMachineMetadata() {
|
|
|
155766
155880
|
for (const lspciGPU of resolvedLspciGPUs) {
|
|
155767
155881
|
busSources.add(lspciGPU.bus);
|
|
155768
155882
|
}
|
|
155883
|
+
for (const nvidiaGPU of resolvedNvidiaGPUs) {
|
|
155884
|
+
if (nvidiaGPU.bus)
|
|
155885
|
+
busSources.add(nvidiaGPU.bus);
|
|
155886
|
+
}
|
|
155769
155887
|
for (const siGPU of siGPUs) {
|
|
155770
155888
|
if (siGPU.bus)
|
|
155771
155889
|
busSources.add(siGPU.bus);
|
|
@@ -155784,6 +155902,7 @@ async function collectMachineMetadata() {
|
|
|
155784
155902
|
}
|
|
155785
155903
|
const gpus = buildMergedGPUs({
|
|
155786
155904
|
lspciGPUs: resolvedLspciGPUs,
|
|
155905
|
+
nvidiaGPUs: resolvedNvidiaGPUs,
|
|
155787
155906
|
rocmVRAM: resolvedRocmVRAM,
|
|
155788
155907
|
siGPUs,
|
|
155789
155908
|
sysfsVRAMMap
|
|
@@ -155841,7 +155960,7 @@ async function createApplication({ abortController, apiClient, configuration, lo
|
|
|
155841
155960
|
});
|
|
155842
155961
|
let machine = null;
|
|
155843
155962
|
try {
|
|
155844
|
-
machine = await collectMachineMetadata();
|
|
155963
|
+
machine = await collectMachineMetadata({ logger });
|
|
155845
155964
|
logger.info("Detected machine hardware", {
|
|
155846
155965
|
gpuCount: machine.gpus.length
|
|
155847
155966
|
});
|
|
@@ -155874,7 +155993,7 @@ async function createApplication({ abortController, apiClient, configuration, lo
|
|
|
155874
155993
|
let modelManager = createModelManagerFromConfig(conduitConfiguration, configuration, logger);
|
|
155875
155994
|
const conduitStateReportManager = new ConduitStateReportManager({
|
|
155876
155995
|
apiClient,
|
|
155877
|
-
collectMachineMetadata: collectMachineMetadata,
|
|
155996
|
+
collectMachineMetadata: () => collectMachineMetadata({ logger }),
|
|
155878
155997
|
conduitStateManager,
|
|
155879
155998
|
downloadProgressReportIntervalMs: 5000,
|
|
155880
155999
|
logger,
|
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
import type { InferenceAgentMachineMetadata } from "@infersec/definitions";
|
|
2
|
-
|
|
2
|
+
import type { Logger } from "@infersec/logger";
|
|
3
|
+
export declare function normalizeBusAddress(bus: string | null | undefined): string | null;
|
|
4
|
+
export declare function parseNvidiaSmiNumber(value: string | undefined): number | null;
|
|
5
|
+
export declare function parseNvidiaSmiMemoryBytes(value: string | undefined): number | null;
|
|
6
|
+
export declare function collectMachineMetadata({ logger }: {
|
|
7
|
+
logger: Logger;
|
|
8
|
+
}): Promise<InferenceAgentMachineMetadata>;
|