diff --git a/src/unified-dashboard.ts b/src/unified-dashboard.ts index 3f581f2..e9c0280 100644 --- a/src/unified-dashboard.ts +++ b/src/unified-dashboard.ts @@ -617,6 +617,39 @@ async function buildUsageContent(): Promise { /* ignore */ } + // GPU (optional — only shown when an NVIDIA GPU + nvidia-smi is present). + let gpuLine: string | null = null; + let vramLine: string | null = null; + try { + const out = execSync( + 'nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total --format=csv,noheader,nounits', + { encoding: 'utf-8', timeout: 5000 }, + ).trim(); + const first = out.split('\n')[0]?.trim(); + if (first) { + const [utilStr, usedStr, totalStr] = first + .split(',') + .map((s) => s.trim()); + const gpuPct = parseInt(utilStr, 10); + const vramUsed = parseInt(usedStr, 10); + const vramTotal = parseInt(totalStr, 10); + if ( + Number.isFinite(gpuPct) && + Number.isFinite(vramUsed) && + Number.isFinite(vramTotal) && + vramTotal > 0 + ) { + const vramPct = Math.round((vramUsed / vramTotal) * 100); + const vramUsedGB = (vramUsed / 1024).toFixed(1); + const vramTotalGB = (vramTotal / 1024).toFixed(1); + gpuLine = `${'GPU'.padEnd(8)}${bar(gpuPct)} ${String(gpuPct).padStart(3)}%`; + vramLine = `${'VRAM'.padEnd(8)}${bar(vramPct)} ${String(vramPct).padStart(3)}% ${vramUsedGB}/${vramTotalGB}GB`; + } + } + } catch { + /* no GPU or nvidia-smi unavailable */ + } + lines.push('```'); lines.push(`${'CPU'.padEnd(8)}${bar(cpuPct)} ${String(cpuPct).padStart(3)}%`); lines.push( @@ -625,6 +658,8 @@ async function buildUsageContent(): Promise { lines.push( `${'Disk'.padEnd(8)}${bar(diskPct)} ${String(diskPct).padStart(3)}% ${diskUsedGB}/${diskTotalGB}GB`, ); + if (gpuLine) lines.push(gpuLine); + if (vramLine) lines.push(vramLine); lines.push(`${'Uptime'.padEnd(8)}${formatElapsed(os.uptime() * 1000)}`); lines.push('```');