Files
mission-control-v2/frontend/src/components/dashboard/RolesCard.tsx
T
Hitonabi 45bede6579 Feat: reasoning-Rolle entfernt — Modell geloescht, UI bereinigt
- Nemotron-3-Nano-Omni-30B-A3B-Reasoning von der Box entfernt (25 GB freigegeben)
- llama-swap config: Modell-Eintrag und reasoning-Alias entfernt
- sources.py: reasoning-Kategorie aus CATEGORIES entfernt
- maintenance.py: reasoning->heavy Mapping aus ROLE_MAP entfernt
- llamaswap.py: reasoning aus ROLE_IDS entfernt
- Frontend: reasoning aus allen ROLES-Arrays entfernt (ModelBadges, RolesCard, Cockpit)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 00:11:15 +02:00

109 lines
5.3 KiB
TypeScript

import { Layers } from "lucide-react"
import { useModels } from "@/lib/queries"
import { cn } from "@/lib/utils"
const ROLES = ["fast", "heavy", "coder", "vision", "scout"]
export function RolesCard() {
const { data } = useModels(3_000)
const models = data?.models ?? []
const running = data?.running ?? []
return (
<div className="rounded-2xl border border-border/60 bg-card/45 backdrop-blur-md p-5 shadow-lg shadow-black/15 flex flex-col justify-between">
<div>
<div className="flex items-center gap-2 mb-4">
<Layers className="h-4.5 w-4.5 text-primary" />
<h2 className="text-sm font-semibold tracking-wide uppercase text-foreground">Rollen-Belegung</h2>
</div>
<div className="space-y-2 max-h-48 overflow-y-auto pr-1 scrollbar-thin">
{ROLES.map((role) => {
const m = models.find((x) => x.role === role)
const isRunning = m ? running.includes(m.name) : false
return (
<div
key={role}
className={cn(
"flex items-center justify-between p-2 rounded-xl border transition-all duration-300",
isRunning
? "border-emerald-500/30 bg-emerald-500/5 shadow-sm shadow-emerald-500/5"
: m
? "border-primary/20 bg-primary/5"
: "border-border/30 bg-background/10 opacity-60"
)}
>
<div className="min-w-0 flex-1 mr-2">
<div className="flex items-center gap-2 min-w-0">
<span className={cn("text-[9px] font-semibold uppercase px-1.5 py-0.5 rounded font-mono border tracking-wider shrink-0",
role === "fast" ? "bg-cyan-500/15 text-cyan-400 border-cyan-500/25" :
role === "heavy" ? "bg-amber-500/15 text-amber-400 border-amber-500/25" :
role === "coder" ? "bg-violet-500/15 text-violet-400 border-violet-500/25" :
role === "vision" ? "bg-pink-500/15 text-pink-400 border-pink-500/25" :
"bg-teal-500/15 text-teal-400 border-teal-500/25"
)}>
{role}
</span>
<div className="flex flex-col min-w-0">
<span className="text-xs font-semibold truncate font-mono text-foreground">
{m ? m.name.split("/").pop()?.replace(/\.gguf$/i, "") : "nicht zugewiesen"}
</span>
{m && (
<div className="flex gap-1 items-center mt-0.5 flex-wrap">
{m.prompt_cache && (
<span className="text-[7px] leading-none font-mono font-bold bg-cyan-500/10 text-cyan-400 border border-cyan-500/20 px-1 py-0.5 rounded" title="Prompt Caching aktiv">
PC
</span>
)}
{m.spec_draft_model && (
<span className="text-[7px] leading-none font-mono font-bold bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 px-1 py-0.5 rounded" title={`Speculative Decoding aktiv (Draft: ${m.spec_draft_model})`}>
SPEC
</span>
)}
{m.parallel_slots > 1 && (
<span className="text-[7px] leading-none font-mono font-bold bg-violet-500/10 text-violet-400 border border-violet-500/20 px-1 py-0.5 rounded" title={`${m.parallel_slots} parallele Slots aktiv`}>
SLOTS: {m.parallel_slots}
</span>
)}
{m.incomplete && (
<span className="text-[7px] leading-none font-mono font-bold bg-amber-500/10 text-amber-400 border border-amber-500/20 px-1 py-0.5 rounded" title="GGUF-Datei fehlt">
fehlt
</span>
)}
</div>
)}
</div>
</div>
</div>
<div className="flex items-center gap-1.5 shrink-0">
{m ? (
isRunning ? (
<span className="flex items-center gap-1 text-[8px] font-semibold text-emerald-400 uppercase tracking-wider font-mono">
<span className="h-1.5 w-1.5 rounded-full bg-emerald-500 animate-pulse" /> warm
</span>
) : (
<span className="text-[8px] font-semibold text-muted-foreground uppercase tracking-wider font-mono">
bereit
</span>
)
) : (
<span className="text-[8px] font-semibold text-muted-foreground/60 uppercase tracking-wider font-mono">
</span>
)}
</div>
</div>
)
})}
</div>
</div>
<div className="mt-4 text-[10px] text-muted-foreground/80 border-t border-border/30 pt-3">
Laden erfolgt automatisch per Auto-Swap.
</div>
</div>
)
}