Feat: Pool-Auslastungs-Mini-Bar in der Dashboard-Modelle-Karte
Schlanke Glance-Anzeige der echten Speicher-Pool-Belegung (gtt_used/gtt_total inkl. KV aus sysStatus.gpu) oben in der Modelle-Karte — teal/amber/rot ab 70/88 %. Keine Karten-Doppelung: die volle interaktive VRAM-Bar + „Alle entladen" bleibt im Modell-Manager. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+1
-1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+86
-86
File diff suppressed because one or more lines are too long
-1
File diff suppressed because one or more lines are too long
Vendored
+2
-2
@@ -7,8 +7,8 @@
|
||||
<link rel="manifest" href="/manifest.webmanifest" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<title>Mission Control 2.0</title>
|
||||
<script type="module" crossorigin src="/assets/index-DSZM1C9y.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-UDlAwulM.css">
|
||||
<script type="module" crossorigin src="/assets/index-PXdvVWCT.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-B_KoUJpZ.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useRef, useState } from "react"
|
||||
import { Boxes, Zap, Moon } from "lucide-react"
|
||||
import { useModels, useTokenStats } from "@/lib/queries"
|
||||
import { fmtSize } from "@/lib/format"
|
||||
import { useModels, useTokenStats, useSystemStatus } from "@/lib/queries"
|
||||
import { fmtSize, gb } from "@/lib/format"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { ROLES, roleTone } from "@/components/models/ModelBadges"
|
||||
|
||||
@@ -10,9 +10,18 @@ import { ROLES, roleTone } from "@/components/models/ModelBadges"
|
||||
export function ModelsCard() {
|
||||
const { data } = useModels(2_000)
|
||||
const { data: stats } = useTokenStats(2_000)
|
||||
const { data: sysStatus } = useSystemStatus()
|
||||
const models = data?.models ?? []
|
||||
const running = data?.running ?? []
|
||||
|
||||
// Echte Pool-Belegung (Unified-RAM inkl. KV) — schlanke Glance-Bar. Die volle
|
||||
// Segment-Bar + „Alle entladen" bleibt im Modell-Manager.
|
||||
const gttTotal = sysStatus?.gpu?.gtt_total || sysStatus?.gpu?.vram_total || 0
|
||||
const gttUsed = sysStatus?.gpu?.gtt_used || 0
|
||||
const poolPct = gttTotal > 0 ? Math.min(100, (gttUsed / gttTotal) * 100) : 0
|
||||
const poolBar = poolPct >= 88 ? "bg-red-500" : poolPct >= 70 ? "bg-amber-500" : "bg-teal-500"
|
||||
const poolText = poolPct >= 88 ? "text-red-400" : poolPct >= 70 ? "text-amber-400" : "text-foreground"
|
||||
|
||||
// „Inferenz aktiv": total_tokens seit letztem Poll gestiegen → es wird generiert.
|
||||
const prev = useRef<number | null>(null)
|
||||
const [generating, setGenerating] = useState(false)
|
||||
@@ -46,6 +55,18 @@ export function ModelsCard() {
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{gttTotal > 0 && (
|
||||
<div className="mb-4">
|
||||
<div className="flex items-center justify-between text-[10px] font-mono text-muted-foreground/80 mb-1">
|
||||
<span className="uppercase tracking-wider font-semibold">Speicher-Pool</span>
|
||||
<span><span className={cn("font-bold", poolText)}>{gb(gttUsed)}</span> / {gb(gttTotal)} GB belegt</span>
|
||||
</div>
|
||||
<div className="h-1.5 w-full rounded-full bg-background/50 border border-border/30 overflow-hidden">
|
||||
<div className={cn("h-full rounded-full transition-all duration-500", poolBar)} style={{ width: `${poolPct}%` }} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="space-y-2 flex-1">
|
||||
{ROLES.map((role) => {
|
||||
const m = models.find((x) => x.role === role)
|
||||
|
||||
Reference in New Issue
Block a user