From da507d55bb05df7a382cac713e4cf4455a403e9c Mon Sep 17 00:00:00 2001 From: ARIA Date: Wed, 2 Sep 2026 16:56:47 +0200 Subject: [PATCH] feat: add Dashboard tab with live GPU overview Add a new Dashboard tab as the default/first tab (Dashboard - Curve - Performance - Fans) showing a full GPU overview. Backend: - New hal/dashboard.py: one-shot static GPU info via NVML (VBIOS, CUDA cores, compute capability, bus width, BAR1/CPU-accessible VRAM, Resizable BAR, PCIe max, max clocks, power limits, temp thresholds, persistence mode, fan count, serial, board part number, UUID). ROP count and VRAM type are best-effort from a per-model table since NVML does not expose them. - New /api/dashboard endpoint. - MonitoringSample gains live throttle_reasons (+label), PCIe link width/generation (downclocks when idle, so read per poll), and VRAM temp (from the MEMORY thermal sensor, if exposed). Frontend: - New Dashboard component: critical top row (throttling, voltage, GPU/VRAM temps), full live-monitor grid with sparklines, and a static GPU-information grid. Unavailable fields are omitted. - useDashboard hook + DashboardInfo type + api.client dashboard(). Also: restrict CORS to localhost origins (end-anchored), make _int_key_deltas fail closed on bad keys, and clean up lint blockers in server.py/monitoring.py. --- frontend/src/App.tsx | 24 +- frontend/src/api/client.ts | 2 + .../src/components/Dashboard/Dashboard.tsx | 318 ++++++++++++++++++ frontend/src/hooks/useDashboard.ts | 47 +++ frontend/src/types.ts | 44 ++- frontend/src/utils/units.ts | 20 +- nvcurve/hal/__init__.py | 25 +- nvcurve/hal/dashboard.py | 285 ++++++++++++++++ nvcurve/hal/monitoring.py | 116 +++++-- nvcurve/nvapi/types.py | 16 +- nvcurve/server.py | 82 +++-- 11 files changed, 907 insertions(+), 72 deletions(-) create mode 100644 frontend/src/components/Dashboard/Dashboard.tsx create mode 100644 frontend/src/hooks/useDashboard.ts create mode 100644 nvcurve/hal/dashboard.py diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index ff00514..5d7c351 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,8 +1,10 @@ import { useGpu } from "./hooks/useGpu"; import { useCurve } from "./hooks/useCurve"; import { useMonitor } from "./hooks/useMonitor"; +import { useDashboard } from "./hooks/useDashboard"; import { StatusBar } from "./components/Monitor/StatusBar"; import { LiveMonitor } from "./components/Monitor/LiveMonitor"; +import { Dashboard } from "./components/Dashboard/Dashboard"; import { CurveEditor } from "./components/CurveEditor/CurveEditor"; import { PointTable } from "./components/PointTable/PointTable"; import { PerformancePanel } from "./components/Limits/PerformancePanel"; @@ -89,12 +91,13 @@ function MainApp({ const gpuInfo = useGpu(); const { curve, wsStatus: curveWsStatus } = useCurve(); const { monitor, monitorHistory, wsStatus: monitorWsStatus } = useMonitor(); + const { dashboard, loading: dashboardLoading } = useDashboard(); const { setCurve, activeProfile, setActiveProfile, selectedGpuIndex } = useCurveStore(); - const [activeTab, setActiveTab] = useState<"curve" | "performance" | "fans">( - "curve", - ); + const [activeTab, setActiveTab] = useState< + "dashboard" | "curve" | "performance" | "fans" + >("dashboard"); const [fanState, setFanState] = useState(null); const [activeDomain, setActiveDomain] = useState<"gpu" | "memory">("gpu"); const [isProfileOpen, setIsProfileOpen] = useState(false); @@ -168,6 +171,12 @@ function MainApp({ {/* Tab Header and Profile Selector */}
+