import { c, table, formatBytes, formatNumber } from '../ansi';import type { AppState } from '../types'; function gpuColor(util: number): (s: string) => string { if (util >= 80) return c.red; if (util >= 50) return c.yellow; return c.green;} export function renderDashboard(state: AppState): string { const lines: string[] = []; lines.push(c.bold('═══ GPUs ═══')); if (state.gpus.length === 0) { lines.push(c.dim(' No GPUs detected')); } else { const headers = ['ID', 'Name', 'VRAM', 'Util', 'Temp', 'Power']; const widths = [2, 18, 15, 5, 5, 6]; const rows = state.gpus.map(gpu => { const vram = `${formatBytes(gpu.memory_used)}/${formatBytes(gpu.memory_total)}`; const util = gpuColor(gpu.utilization)(`${gpu.utilization}%`); const temp = gpu.temperature >= 80 ? c.red(`${gpu.temperature}°C`) : `${gpu.temperature}°C`; return [ gpu.index.toString(), gpu.name.slice(0, 20), vram, util, temp, `${Math.round(gpu.power_draw)}W`, ]; }); lines.push(table(headers, rows, widths)); } lines.push(''); lines.push(c.bold('═══ Lifetime Metrics ═══')); const { total_tokens, total_requests, total_energy_kwh } = state.lifetime; lines.push( ` Tokens: ${c.cyan(formatNumber(total_tokens))} ` + `Requests: ${c.cyan(formatNumber(total_requests))} ` + `Energy: ${c.cyan(total_energy_kwh.toFixed(2) + ' kWh')}` ); lines.push(''); const st = state.status; const statusText = st.launching ? 'launching' : st.running ? 'running' : 'idle'; const statusColor = st.launching ? c.yellow : st.running ? c.green : c.dim; lines.push(` Status: ${statusColor(statusText)}` + (st.model ? ` (${c.cyan(st.model)})` : '')); return lines.join('\n');}
import { c, table, formatBytes, formatNumber } from '../ansi';
import type { AppState } from '../types';
function gpuColor(util: number): (s: string) => string {
if (util >= 80) return c.red;
if (util >= 50) return c.yellow;
return c.green;
}
export function renderDashboard(state: AppState): string {
const lines: string[] = [];
lines.push(c.bold('═══ GPUs ═══'));
if (state.gpus.length === 0) {
lines.push(c.dim(' No GPUs detected'));
} else {
const headers = ['ID', 'Name', 'VRAM', 'Util', 'Temp', 'Power'];
const widths = [2, 18, 15, 5, 5, 6];
const rows = state.gpus.map(gpu => {
const vram = `${formatBytes(gpu.memory_used)}/${formatBytes(gpu.memory_total)}`;
const util = gpuColor(gpu.utilization)(`${gpu.utilization}%`);
const temp = gpu.temperature >= 80
? c.red(`${gpu.temperature}°C`)
: `${gpu.temperature}°C`;
return [
gpu.index.toString(),
gpu.name.slice(0, 20),
vram,
util,
temp,
`${Math.round(gpu.power_draw)}W`,
];
});
lines.push(table(headers, rows, widths));
}
lines.push('');
lines.push(c.bold('═══ Lifetime Metrics ═══'));
const { total_tokens, total_requests, total_energy_kwh } = state.lifetime;
lines.push(
` Tokens: ${c.cyan(formatNumber(total_tokens))} ` +
`Requests: ${c.cyan(formatNumber(total_requests))} ` +
`Energy: ${c.cyan(total_energy_kwh.toFixed(2) + ' kWh')}`
);
lines.push('');
const st = state.status;
const statusText = st.launching ? 'launching' : st.running ? 'running' : 'idle';
const statusColor = st.launching ? c.yellow : st.running ? c.green : c.dim;
lines.push(` Status: ${statusColor(statusText)}` +
(st.model ? ` (${c.cyan(st.model)})` : ''));
return lines.join('\n');
}