feat(dashboard): add GPU/VRAM usage to status channel server section

Show NVIDIA GPU utilization and VRAM used/total in the 서버 status block,
matching the existing CPU/Memory/Disk bar format. Gracefully omitted when
nvidia-smi is unavailable.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Codex
2026-06-12 19:14:36 +09:00
parent 73fd71b39a
commit ee4c5559b1

View File

@@ -617,6 +617,39 @@ async function buildUsageContent(): Promise<string> {
/* 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<string> {
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('```');