54 lines · 1.8 KB · TypeScript
RawDownload
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');}