import { HardDrive } from "lucide-react" import type { ModelInfo } from "@/lib/api" import { fmtSize, gb } from "@/lib/format" import { roleMeta } from "@/lib/roleMeta" import { cn } from "@/lib/utils" import { roleBarColor } from "./roleColors" const B = 1024 ** 3 const short = (name: string) => name.split("/").pop()?.replace(/\.gguf$/i, "") ?? name // Maschinenraum-Speicherleiste — das Signatur-Element. EIN großer Balken „Arbeitsspeicher // · 124 GB", farbig aufgeteilt nach geladenem Modell (nach Rolle eingefärbt) + freier Rest. // Man sieht LIVE, wohin die GB gehen. Ein Klick auf ein Segment wählt das Modell rechts. export function MaschinenraumBar({ running, capacityBytes, realUsedBytes, selected, onSelect, }: { running: ModelInfo[] capacityBytes: number realUsedBytes: number selected?: string | null onSelect?: (name: string) => void }) { const capacity = capacityBytes > 2 * B ? capacityBytes : 124 * B const weights = running.reduce((a, m) => a + (m.size_bytes || 0), 0) const freeBytes = Math.max(0, capacity - weights) const freePct = (freeBytes / capacity) * 100 return (
Arbeitsspeicher
{gb(capacity)} GB gesamt
{gb(weights)} GB Modelle geladen
{realUsedBytes > 0 &&
{gb(realUsedBytes)} GB real belegt (inkl. KV-Cache)
}
{gb(freeBytes)} GB frei
{/* Der Balken */}
{running.length === 0 ? (
Kein Modell geladen — Auto-Swap holt bei Anfrage automatisch das passende.
) : ( <> {running.map((m) => { const pct = ((m.size_bytes || 0) / capacity) * 100 const c = roleBarColor(m.role) const isSel = selected === m.name return ( ) })} {freePct > 1.5 && (
frei
)} )}
{/* Legende */} {running.length > 0 && (
{running.map((m) => { const c = roleBarColor(m.role) return ( ) })} frei · {gb(freeBytes)} GB
)}
) }