@infersec/conduit 1.90.2 → 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 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
- return bus.toLowerCase().replace(/^0000:/, "");
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
- function buildMergedGPUs(options) {
135442
- const { lspciGPUs, rocmVRAM, siGPUs, sysfsVRAMMap } = options;
135443
- const siByBus = new Map();
135444
- for (const gpu of siGPUs) {
135445
- const key = normalizeBusAddress(gpu.bus);
135446
- if (key)
135447
- siByBus.set(key, gpu);
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 seen = new Set();
135456
- const merged = [...siGPUs];
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 || seen.has(key))
135562
+ if (!key)
135460
135563
  continue;
135461
- seen.add(key);
135462
- const existing = siByBus.get(key);
135564
+ const existing = byBus.get(key);
135463
135565
  if (existing) {
135464
135566
  if (existing.memoryTotalBytes === null) {
135465
- const sysfs = sysfsVRAMMap.get(key);
135466
- const sysfsTotal = sysfs?.memoryTotalBytes ?? null;
135467
- const sysfsUsed = sysfs?.memoryUsedBytes ?? null;
135468
- const validSysfsTotal = sysfsTotal !== null && Number.isFinite(sysfsTotal);
135469
- const validSysfsUsed = sysfsUsed !== null && Number.isFinite(sysfsUsed);
135470
- if (validSysfsTotal) {
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 sysfs = sysfsVRAMMap.get(key);
135480
- let totalBytes = sysfs?.memoryTotalBytes ?? null;
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: totalBytes !== null && usedBytes !== null && Number.isFinite(usedBytes)
135493
- ? totalBytes - usedBytes
135494
- : null,
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 merged;
135594
+ return [...byBus.values()];
135503
135595
  }
135504
- async function collectMachineMetadata() {
135505
- const [cpuResult, memResult, osResult, graphicsResult, lspciGPUs, rocmVRAM] = await Promise.allSettled([
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
- return bus.toLowerCase().replace(/^0000:/, "");
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
- function buildMergedGPUs(options) {
155671
- const { lspciGPUs, rocmVRAM, siGPUs, sysfsVRAMMap } = options;
155672
- const siByBus = new Map();
155673
- for (const gpu of siGPUs) {
155674
- const key = normalizeBusAddress(gpu.bus);
155675
- if (key)
155676
- siByBus.set(key, gpu);
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 seen = new Set();
155685
- const merged = [...siGPUs];
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 || seen.has(key))
155791
+ if (!key)
155689
155792
  continue;
155690
- seen.add(key);
155691
- const existing = siByBus.get(key);
155793
+ const existing = byBus.get(key);
155692
155794
  if (existing) {
155693
155795
  if (existing.memoryTotalBytes === null) {
155694
- const sysfs = sysfsVRAMMap.get(key);
155695
- const sysfsTotal = sysfs?.memoryTotalBytes ?? null;
155696
- const sysfsUsed = sysfs?.memoryUsedBytes ?? null;
155697
- const validSysfsTotal = sysfsTotal !== null && Number.isFinite(sysfsTotal);
155698
- const validSysfsUsed = sysfsUsed !== null && Number.isFinite(sysfsUsed);
155699
- if (validSysfsTotal) {
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 sysfs = sysfsVRAMMap.get(key);
155709
- let totalBytes = sysfs?.memoryTotalBytes ?? null;
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: totalBytes !== null && usedBytes !== null && Number.isFinite(usedBytes)
155722
- ? totalBytes - usedBytes
155723
- : null,
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 merged;
155823
+ return [...byBus.values()];
155732
155824
  }
155733
- async function collectMachineMetadata() {
155734
- const [cpuResult, memResult, osResult, graphicsResult, lspciGPUs, rocmVRAM] = await Promise.allSettled([
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
- export declare function collectMachineMetadata(): Promise<InferenceAgentMachineMetadata>;
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>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@infersec/conduit",
3
3
  "description": "End user conduit agent for connecting local LLMs to the cloud.",
4
- "version": "1.90.2",
4
+ "version": "1.90.3",
5
5
  "bin": {
6
6
  "infersec-conduit": "./dist/cli.js"
7
7
  },