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="manifest" href="/manifest.webmanifest" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<title>Mission Control 2.0</title>
|
<title>Mission Control 2.0</title>
|
||||||
<script type="module" crossorigin src="/assets/index-DSZM1C9y.js"></script>
|
<script type="module" crossorigin src="/assets/index-PXdvVWCT.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-UDlAwulM.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-B_KoUJpZ.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useEffect, useRef, useState } from "react"
|
import { useEffect, useRef, useState } from "react"
|
||||||
import { Boxes, Zap, Moon } from "lucide-react"
|
import { Boxes, Zap, Moon } from "lucide-react"
|
||||||
import { useModels, useTokenStats } from "@/lib/queries"
|
import { useModels, useTokenStats, useSystemStatus } from "@/lib/queries"
|
||||||
import { fmtSize } from "@/lib/format"
|
import { fmtSize, gb } from "@/lib/format"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { ROLES, roleTone } from "@/components/models/ModelBadges"
|
import { ROLES, roleTone } from "@/components/models/ModelBadges"
|
||||||
|
|
||||||
@@ -10,9 +10,18 @@ import { ROLES, roleTone } from "@/components/models/ModelBadges"
|
|||||||
export function ModelsCard() {
|
export function ModelsCard() {
|
||||||
const { data } = useModels(2_000)
|
const { data } = useModels(2_000)
|
||||||
const { data: stats } = useTokenStats(2_000)
|
const { data: stats } = useTokenStats(2_000)
|
||||||
|
const { data: sysStatus } = useSystemStatus()
|
||||||
const models = data?.models ?? []
|
const models = data?.models ?? []
|
||||||
const running = data?.running ?? []
|
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.
|
// „Inferenz aktiv": total_tokens seit letztem Poll gestiegen → es wird generiert.
|
||||||
const prev = useRef<number | null>(null)
|
const prev = useRef<number | null>(null)
|
||||||
const [generating, setGenerating] = useState(false)
|
const [generating, setGenerating] = useState(false)
|
||||||
@@ -46,6 +55,18 @@ export function ModelsCard() {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</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">
|
<div className="space-y-2 flex-1">
|
||||||
{ROLES.map((role) => {
|
{ROLES.map((role) => {
|
||||||
const m = models.find((x) => x.role === role)
|
const m = models.find((x) => x.role === role)
|
||||||
|
|||||||
Reference in New Issue
Block a user