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
)}
)
}