feat: surface VIBEPOD_DEVICE (CPU/CUDA) in the frontend header

This commit is contained in:
2026-04-29 08:43:07 +01:00
parent b8f59875d9
commit 68174b9d67
2 changed files with 44 additions and 18 deletions
+1
View File
@@ -23,6 +23,7 @@ export async function GET() {
return NextResponse.json(
{
status,
device: data.device ?? null,
message: data.message,
progress: data.progress ?? null,
voices: data.voices ?? [],
+26 -1
View File
@@ -3,6 +3,7 @@
import { useEffect, useRef, useState } from "react";
type ServerStatus = "checking" | "downloading" | "loading" | "online" | "error" | "offline";
type Device = "cpu" | "cuda" | null;
// Polling intervals: poll quickly until the server is online, then slow down.
const FAST_INTERVAL_MS = 3000; // while checking / loading
@@ -10,6 +11,7 @@ const SLOW_INTERVAL_MS = 30000; // once online
export default function Header() {
const [status, setStatus] = useState<ServerStatus>("checking");
const [device, setDevice] = useState<Device>(null);
const [message, setMessage] = useState<string | undefined>();
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
@@ -20,6 +22,7 @@ export default function Header() {
const data = await res.json();
const newStatus: ServerStatus = (data.status as ServerStatus) ?? "offline";
setStatus(newStatus);
setDevice((data.device as Device) ?? null);
setMessage(data.message);
// Switch to slow polling once we know the server is online
@@ -34,6 +37,7 @@ export default function Header() {
}
} catch {
setStatus("offline");
setDevice(null);
setMessage(undefined);
}
};
@@ -90,6 +94,25 @@ export default function Header() {
const cfg = statusConfig[status];
// Device badge — only shown once the server is online and device is known
const deviceBadge = status === "online" && device ? (
<span
className="px-2 py-0.5 rounded-full text-xs font-semibold tracking-wide uppercase"
style={{
background: device === "cuda"
? "var(--accent-violet-dim)"
: "var(--accent-teal-dim)",
color: device === "cuda"
? "var(--accent-violet)"
: "var(--accent-teal)",
border: `1px solid ${device === "cuda" ? "var(--accent-violet-dim)" : "var(--accent-teal-dim)"}`,
}}
title={device === "cuda" ? "Running on NVIDIA GPU" : "Running on CPU"}
>
{device.toUpperCase()}
</span>
) : null;
return (
<header
className="border-b px-6 py-4 flex items-center justify-between"
@@ -128,6 +151,8 @@ export default function Header() {
</div>
</div>
<div className="flex items-center gap-2">
{deviceBadge}
<div
className={`flex items-center gap-2 px-3 py-1.5 rounded-full text-xs font-medium border ${cfg.ring}`}
style={{
@@ -148,7 +173,7 @@ export default function Header() {
</span>
<span style={{ color: "var(--foreground)" }}>{cfg.label}</span>
</div>
</div>
</header>
);
}