Files
gpu-program-swapper/static/index.html

673 lines
40 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HYPERSWAP // Dual-Engine Model Orchestrator & Live Telemetry</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
<link rel="stylesheet" href="/static/styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
</head>
<body class="bg-slate-950 text-slate-100 min-h-screen font-sans antialiased selection:bg-cyan-500 selection:text-white">
<!-- TOP HEADER -->
<header class="border-b border-slate-800 bg-slate-900/80 backdrop-blur sticky top-0 z-50">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-3 flex flex-wrap items-center justify-between gap-4">
<div class="flex items-center space-x-3">
<div class="w-10 h-10 rounded-xl bg-gradient-to-tr from-cyan-500 via-indigo-500 to-purple-500 flex items-center justify-center shadow-lg shadow-cyan-500/20">
<i class="fa-solid fa-bolt-lightning text-white text-lg"></i>
</div>
<div>
<div class="flex items-center space-x-2">
<h1 class="text-xl font-bold tracking-tight bg-clip-text text-transparent bg-gradient-to-r from-cyan-400 via-sky-300 to-indigo-400">
HYPERSWAP
</h1>
<span class="text-xs uppercase tracking-widest px-2 py-0.5 rounded bg-cyan-950/80 text-cyan-400 border border-cyan-800 font-mono">
v1.0-DEPLOY
</span>
</div>
<p class="text-xs text-slate-400 font-mono">NVIDIA RTX 4080 SUPER 16GB // 64GB DDR5 RAM // Ubuntu Linux</p>
</div>
</div>
<div class="flex items-center space-x-3">
<!-- Service Status Indicators -->
<div class="flex items-center space-x-2 px-3 py-1.5 rounded-lg bg-slate-800/80 border border-slate-700/60 text-xs">
<span class="relative flex h-2.5 w-2.5">
<span id="ollama-pulse" class="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
<span id="ollama-dot" class="relative inline-flex rounded-full h-2.5 w-2.5 bg-emerald-500"></span>
</span>
<span class="font-medium text-slate-300">Ollama LLM:</span>
<span id="ollama-status-text" class="text-emerald-400 font-mono font-bold">ONLINE</span>
</div>
<div class="flex items-center space-x-2 px-3 py-1.5 rounded-lg bg-slate-800/80 border border-slate-700/60 text-xs">
<span class="relative flex h-2.5 w-2.5">
<span id="comfy-pulse" class="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
<span id="comfy-dot" class="relative inline-flex rounded-full h-2.5 w-2.5 bg-emerald-500"></span>
</span>
<span class="font-medium text-slate-300">ComfyUI:</span>
<span id="comfy-status-text" class="text-emerald-400 font-mono font-bold">ONLINE</span>
</div>
<div class="flex items-center space-x-1.5 px-3 py-1.5 rounded-lg bg-slate-800/80 border border-slate-700/60 text-xs text-slate-400 font-mono">
<i class="fa-solid fa-satellite-dish text-cyan-400 text-xs animate-pulse"></i>
<span id="sse-badge">SSE 1Hz</span>
</div>
</div>
</div>
</header>
<!-- MAIN CONTAINER -->
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6 space-y-6">
<!-- HERO MEMORY GAUGES -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- GPU VRAM ALLOCATION GAUGE -->
<div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-5 relative overflow-hidden backdrop-blur">
<div class="flex justify-between items-start mb-3">
<div>
<div class="flex items-center space-x-2">
<i class="fa-solid fa-microchip text-cyan-400"></i>
<h2 class="text-sm font-semibold text-slate-200 tracking-wide uppercase">GPU VRAM (16 GB Dedicated)</h2>
</div>
<p class="text-xs text-slate-400 mt-0.5">Real-time allocation breakdown on RTX 4080 SUPER</p>
</div>
<div class="text-right font-mono">
<span id="vram-total-used" class="text-2xl font-bold text-slate-100">0.0</span>
<span class="text-xs text-slate-400">/ 16.0 GB</span>
<div id="vram-used-pct" class="text-xs text-cyan-400 font-bold">0% USED</div>
</div>
</div>
<!-- Segmented Bar -->
<div class="h-6 w-full bg-slate-950 rounded-lg overflow-hidden flex border border-slate-800 p-0.5">
<div id="bar-ollama" class="bg-gradient-to-r from-purple-600 to-indigo-500 h-full rounded-l transition-all duration-500 relative group" style="width: 0%">
<div class="opacity-0 group-hover:opacity-100 absolute -top-8 left-1/2 -translate-x-1/2 bg-slate-800 text-[10px] text-white px-2 py-0.5 rounded border border-slate-700 whitespace-nowrap z-20">
Ollama: <span id="tooltip-ollama">0 GB</span>
</div>
</div>
<div id="bar-comfy" class="bg-gradient-to-r from-cyan-500 to-sky-400 h-full transition-all duration-500 relative group" style="width: 0%">
<div class="opacity-0 group-hover:opacity-100 absolute -top-8 left-1/2 -translate-x-1/2 bg-slate-800 text-[10px] text-white px-2 py-0.5 rounded border border-slate-700 whitespace-nowrap z-20">
ComfyUI: <span id="tooltip-comfy">0 GB</span>
</div>
</div>
<div id="bar-system" class="bg-slate-600 h-full transition-all duration-500 relative group" style="width: 0%">
<div class="opacity-0 group-hover:opacity-100 absolute -top-8 left-1/2 -translate-x-1/2 bg-slate-800 text-[10px] text-white px-2 py-0.5 rounded border border-slate-700 whitespace-nowrap z-20">
System: <span id="tooltip-system">0 GB</span>
</div>
</div>
<div id="bar-free" class="bg-slate-900 h-full rounded-r transition-all duration-500" style="width: 100%"></div>
</div>
<!-- Legend -->
<div class="grid grid-cols-4 gap-2 mt-3 text-xs font-mono">
<div class="flex items-center space-x-1.5">
<span class="w-2.5 h-2.5 rounded-full bg-purple-500"></span>
<span class="text-slate-400">Ollama:</span>
<span id="legend-ollama" class="text-slate-200 font-bold">0 GB</span>
</div>
<div class="flex items-center space-x-1.5">
<span class="w-2.5 h-2.5 rounded-full bg-cyan-400"></span>
<span class="text-slate-400">Comfy:</span>
<span id="legend-comfy" class="text-slate-200 font-bold">0 GB</span>
</div>
<div class="flex items-center space-x-1.5">
<span class="w-2.5 h-2.5 rounded-full bg-slate-500"></span>
<span class="text-slate-400">System:</span>
<span id="legend-system" class="text-slate-200 font-bold">0 GB</span>
</div>
<div class="flex items-center space-x-1.5">
<span class="w-2.5 h-2.5 rounded-full bg-slate-800 border border-slate-700"></span>
<span class="text-slate-400">Free:</span>
<span id="legend-free" class="text-emerald-400 font-bold">0 GB</span>
</div>
</div>
</div>
<!-- SYSTEM RAM & PAGE CACHE GAUGE -->
<div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-5 relative overflow-hidden backdrop-blur">
<div class="flex justify-between items-start mb-3">
<div>
<div class="flex items-center space-x-2">
<i class="fa-solid fa-memory text-amber-400"></i>
<h2 class="text-sm font-semibold text-slate-200 tracking-wide uppercase">Host RAM & Model Page Cache (64 GB)</h2>
</div>
<p class="text-xs text-slate-400 mt-0.5">Models stay resident in RAM for instant PCIe hot-swaps</p>
</div>
<div class="text-right font-mono">
<span id="ram-cached-gb" class="text-2xl font-bold text-amber-400">0.0</span>
<span class="text-xs text-slate-400">GB CACHED</span>
<div id="ram-total-text" class="text-xs text-slate-400">60.3 GB Total</div>
</div>
</div>
<!-- Segmented Bar -->
<div class="h-6 w-full bg-slate-950 rounded-lg overflow-hidden flex border border-slate-800 p-0.5">
<div id="bar-ram-used" class="bg-gradient-to-r from-rose-600 to-orange-500 h-full rounded-l transition-all duration-500" style="width: 10%"></div>
<div id="bar-ram-cache" class="bg-gradient-to-r from-amber-500 to-yellow-400 h-full transition-all duration-500" style="width: 50%"></div>
<div id="bar-ram-free" class="bg-slate-900 h-full rounded-r transition-all duration-500" style="width: 40%"></div>
</div>
<!-- Legend -->
<div class="grid grid-cols-3 gap-2 mt-3 text-xs font-mono">
<div class="flex items-center space-x-1.5">
<span class="w-2.5 h-2.5 rounded-full bg-rose-500"></span>
<span class="text-slate-400">Apps Used:</span>
<span id="legend-ram-used" class="text-slate-200 font-bold">0 GB</span>
</div>
<div class="flex items-center space-x-1.5">
<span class="w-2.5 h-2.5 rounded-full bg-amber-400"></span>
<span class="text-slate-400">Models in RAM:</span>
<span id="legend-ram-cached" class="text-amber-400 font-bold">0 GB</span>
</div>
<div class="flex items-center space-x-1.5">
<span class="w-2.5 h-2.5 rounded-full bg-slate-800 border border-slate-700"></span>
<span class="text-slate-400">Free RAM:</span>
<span id="legend-ram-free" class="text-emerald-400 font-bold">0 GB</span>
</div>
</div>
</div>
</div>
<!-- 4-CARD CONTROL & TELEMETRY GRID -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- CARD 1: OLLAMA LLM ENGINE -->
<div class="bg-slate-900/80 border border-slate-800 rounded-2xl p-5 flex flex-col justify-between space-y-4">
<div>
<div class="flex items-center justify-between pb-3 border-b border-slate-800">
<div class="flex items-center space-x-2">
<div class="p-2 rounded-lg bg-purple-950/80 border border-purple-800 text-purple-400">
<i class="fa-solid fa-brain text-sm"></i>
</div>
<div>
<h3 class="font-bold text-slate-100 text-sm">Ollama LLM Engine</h3>
<p class="text-xs text-slate-400">Port :11434 // FlashAttention + Q4 KV Cache</p>
</div>
</div>
<button onclick="freeOllamaVRAM()" class="px-2.5 py-1 text-xs font-semibold rounded-lg bg-rose-950/70 border border-rose-800 text-rose-300 hover:bg-rose-900 transition flex items-center space-x-1">
<i class="fa-solid fa-arrow-down-to-bracket"></i>
<span>Soft-Yield VRAM</span>
</button>
</div>
<!-- Active Model Box -->
<div class="mt-4 p-4 rounded-xl bg-slate-950 border border-slate-800/80 space-y-3">
<div class="flex justify-between items-center">
<span class="text-xs text-slate-400 uppercase font-mono">Active Model in VRAM</span>
<span id="ollama-vram-badge" class="px-2 py-0.5 text-[10px] font-mono rounded bg-purple-900/60 text-purple-300 border border-purple-700">
0.0 GB VRAM
</span>
</div>
<div class="flex items-center justify-between">
<div class="flex items-center space-x-2 overflow-hidden">
<i class="fa-solid fa-cube text-purple-400"></i>
<span id="ollama-active-model" class="text-base font-bold font-mono text-slate-100 truncate">None Loaded</span>
</div>
<span id="ollama-context" class="text-xs font-mono text-slate-400">0 ctx</span>
</div>
</div>
<!-- Quick Hot-Swap Control -->
<div class="mt-4 space-y-2">
<label class="text-xs font-semibold text-slate-300 flex items-center justify-between">
<span>Instant Model Hot-Swap:</span>
<span class="text-[10px] text-cyan-400 font-mono">RAM Cache Optimized</span>
</label>
<div class="flex space-x-2">
<select id="ollama-model-select" class="flex-1 bg-slate-950 border border-slate-700 rounded-lg px-3 py-2 text-xs font-mono text-slate-200 focus:outline-none focus:border-purple-500">
<option value="">Loading installed models...</option>
</select>
<button id="btn-switch-model" onclick="triggerModelSwitch()" class="px-4 py-2 bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-500 hover:to-indigo-500 text-white text-xs font-bold rounded-lg shadow-md transition flex items-center space-x-1.5">
<i class="fa-solid fa-shuffle"></i>
<span>Hot Swap</span>
</button>
</div>
</div>
</div>
<!-- Ollama Stats Footer -->
<div class="pt-3 border-t border-slate-800 grid grid-cols-3 gap-2 text-center font-mono text-xs">
<div class="p-2 rounded bg-slate-950 border border-slate-800">
<span class="text-[10px] text-slate-500 block">LAST SWAP TIME</span>
<span id="ollama-last-swap" class="text-cyan-400 font-bold">-- ms</span>
</div>
<div class="p-2 rounded bg-slate-950 border border-slate-800">
<span class="text-[10px] text-slate-500 block">RAM HIT STATUS</span>
<span id="ollama-cache-hit" class="text-emerald-400 font-bold">--</span>
</div>
<div class="p-2 rounded bg-slate-950 border border-slate-800">
<span class="text-[10px] text-slate-500 block">TOTAL MODELS</span>
<span id="ollama-total-models" class="text-slate-300 font-bold">0</span>
</div>
</div>
</div>
<!-- CARD 2: COMFYUI DIFFUSION PIPELINE -->
<div class="bg-slate-900/80 border border-slate-800 rounded-2xl p-5 flex flex-col justify-between space-y-4">
<div>
<div class="flex items-center justify-between pb-3 border-b border-slate-800">
<div class="flex items-center space-x-2">
<div class="p-2 rounded-lg bg-cyan-950/80 border border-cyan-800 text-cyan-400">
<i class="fa-solid fa-palette text-sm"></i>
</div>
<div>
<h3 class="font-bold text-slate-100 text-sm">ComfyUI Diffusion Engine</h3>
<p class="text-xs text-slate-400">Port :8188 // DynamicVRAM + Pinned Async Offload</p>
</div>
</div>
<button onclick="freeComfyVRAM()" class="px-2.5 py-1 text-xs font-semibold rounded-lg bg-rose-950/70 border border-rose-800 text-rose-300 hover:bg-rose-900 transition flex items-center space-x-1">
<i class="fa-solid fa-broom"></i>
<span>Purge VRAM</span>
</button>
</div>
<!-- Comfy Execution Box -->
<div class="mt-4 p-4 rounded-xl bg-slate-950 border border-slate-800/80 space-y-3">
<div class="flex justify-between items-center">
<span class="text-xs text-slate-400 uppercase font-mono">Pipeline Status</span>
<span id="comfy-exec-badge" class="px-2 py-0.5 text-[10px] font-mono rounded bg-emerald-950 text-emerald-300 border border-emerald-800">
IDLE / READY
</span>
</div>
<div class="flex items-center justify-between">
<div class="flex items-center space-x-2">
<i class="fa-solid fa-layer-group text-cyan-400"></i>
<span id="comfy-model-info" class="text-sm font-mono text-slate-200">Dynamic Model Offloader</span>
</div>
<div class="text-xs font-mono text-slate-400">
Queue: <span id="comfy-queue-count" class="text-cyan-400 font-bold">0</span>
</div>
</div>
</div>
<!-- Comfy Feature Checklist -->
<div class="mt-4 space-y-2 text-xs">
<div class="p-2.5 rounded-lg bg-slate-950 border border-slate-800 space-y-1.5">
<div class="flex items-center justify-between text-slate-300">
<span class="flex items-center space-x-1.5">
<i class="fa-solid fa-check text-emerald-400 text-xs"></i>
<span>Host Pinned Memory:</span>
</span>
<span class="font-mono font-bold text-emerald-400">53.6 GB Staging Buffer</span>
</div>
<div class="flex items-center justify-between text-slate-300">
<span class="flex items-center space-x-1.5">
<i class="fa-solid fa-check text-emerald-400 text-xs"></i>
<span>Async PCIe Offloading:</span>
</span>
<span class="font-mono font-bold text-cyan-400">Enabled (2 Streams)</span>
</div>
<div class="flex items-center justify-between text-slate-300">
<span class="flex items-center space-x-1.5">
<i class="fa-solid fa-check text-emerald-400 text-xs"></i>
<span>Fast Disk RAM Mmap:</span>
</span>
<span class="font-mono font-bold text-amber-400">Active</span>
</div>
</div>
</div>
</div>
<!-- Comfy Stats Footer -->
<div class="pt-3 border-t border-slate-800 grid grid-cols-2 gap-2 text-center font-mono text-xs">
<div class="p-2 rounded bg-slate-950 border border-slate-800">
<span class="text-[10px] text-slate-500 block">DISCOVERED MODELS</span>
<span id="comfy-discovered-count" class="text-cyan-400 font-bold">0 Files</span>
</div>
<div class="p-2 rounded bg-slate-950 border border-slate-800">
<span class="text-[10px] text-slate-500 block">VRAM AVAILABLE</span>
<span id="comfy-vram-avail" class="text-emerald-400 font-bold">15.9 GB</span>
</div>
</div>
</div>
<!-- CARD 3: GPU HARDWARE TELEMETRY -->
<div class="bg-slate-900/80 border border-slate-800 rounded-2xl p-5 space-y-4">
<div class="flex items-center justify-between pb-3 border-b border-slate-800">
<div class="flex items-center space-x-2">
<div class="p-2 rounded-lg bg-emerald-950/80 border border-emerald-800 text-emerald-400">
<i class="fa-solid fa-gauge-high text-sm"></i>
</div>
<div>
<h3 class="font-bold text-slate-100 text-sm">GPU Live Telemetry (NVML)</h3>
<p class="text-xs text-slate-400" id="gpu-chip-name">NVIDIA GeForce RTX 4080 SUPER</p>
</div>
</div>
</div>
<!-- Quick Gauges Grid -->
<div class="grid grid-cols-2 sm:grid-cols-4 gap-3 font-mono">
<div class="p-3 rounded-xl bg-slate-950 border border-slate-800 text-center">
<span class="text-[10px] text-slate-400 uppercase block">GPU Util</span>
<span id="gpu-util-val" class="text-xl font-bold text-cyan-400">0%</span>
</div>
<div class="p-3 rounded-xl bg-slate-950 border border-slate-800 text-center">
<span class="text-[10px] text-slate-400 uppercase block">Temperature</span>
<span id="gpu-temp-val" class="text-xl font-bold text-emerald-400">0°C</span>
</div>
<div class="p-3 rounded-xl bg-slate-950 border border-slate-800 text-center">
<span class="text-[10px] text-slate-400 uppercase block">Power Draw</span>
<span id="gpu-power-val" class="text-xl font-bold text-amber-400">0 W</span>
</div>
<div class="p-3 rounded-xl bg-slate-950 border border-slate-800 text-center relative overflow-hidden">
<span class="text-[10px] text-slate-400 uppercase block">Fan Speed</span>
<div class="flex items-center justify-center space-x-1.5">
<i id="gpu-fan-icon" class="fa-solid fa-fan text-emerald-400 text-sm"></i>
<span id="gpu-fan-val" class="text-xl font-bold text-emerald-400">0%</span>
</div>
<span id="gpu-fan-sub" class="text-[9px] font-mono text-slate-500 block truncate">Fan 0: --% | Fan 1: --%</span>
</div>
</div>
<!-- Process Table -->
<div class="space-y-2">
<span class="text-xs font-semibold text-slate-400 uppercase font-mono">Active Compute Processes</span>
<div class="rounded-xl bg-slate-950 border border-slate-800 p-2 max-h-36 overflow-y-auto font-mono text-xs">
<table class="w-full text-left">
<thead>
<tr class="text-slate-500 border-b border-slate-800/80 text-[10px]">
<th class="pb-1">PID</th>
<th class="pb-1">Process</th>
<th class="pb-1 text-right">VRAM</th>
</tr>
</thead>
<tbody id="gpu-proc-table" class="divide-y divide-slate-900">
<tr><td colspan="3" class="py-2 text-center text-slate-500">Scanning GPU processes...</td></tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- CARD 4: REAL-TIME SWITCH TIMELINE & OPTIMIZER -->
<div class="bg-slate-900/80 border border-slate-800 rounded-2xl p-5 flex flex-col justify-between space-y-4">
<div>
<div class="flex items-center justify-between pb-3 border-b border-slate-800">
<div class="flex items-center space-x-2">
<div class="p-2 rounded-lg bg-indigo-950/80 border border-indigo-800 text-indigo-400">
<i class="fa-solid fa-clock-rotate-left text-sm"></i>
</div>
<div>
<h3 class="font-bold text-slate-100 text-sm">Model Switch Timeline & Optimizer</h3>
<p class="text-xs text-slate-400">Real-time latency logger and memory warmer</p>
</div>
</div>
<button onclick="warmAllModels()" class="px-2.5 py-1 text-xs font-semibold rounded-lg bg-amber-950/70 border border-amber-800 text-amber-300 hover:bg-amber-900 transition flex items-center space-x-1">
<i class="fa-solid fa-fire text-amber-400"></i>
<span>Warm All to RAM</span>
</button>
</div>
<!-- Switch Events Log -->
<div class="mt-4 space-y-2">
<span class="text-xs font-semibold text-slate-400 uppercase font-mono">Recent Model Swaps</span>
<div id="switch-log-container" class="space-y-2 max-h-48 overflow-y-auto pr-1">
<div class="p-3 rounded-xl bg-slate-950 border border-slate-800 text-xs text-slate-400 text-center font-mono">
No recent model swaps recorded yet.
</div>
</div>
</div>
</div>
<!-- Optimizer Banner -->
<div class="p-3 rounded-xl bg-gradient-to-r from-cyan-950/50 via-slate-950 to-purple-950/50 border border-slate-800 text-xs flex items-center justify-between">
<div class="flex items-center space-x-2">
<i class="fa-solid fa-wand-magic-sparkles text-cyan-400"></i>
<span class="text-slate-300">64GB RAM Cache holds all models in memory</span>
</div>
<span class="font-mono text-cyan-400 font-bold">PCIe x16 (~31.5 GB/s)</span>
</div>
</div>
</div>
<!-- OVERCLOCK CONTROL PANEL -->
<div class="bg-slate-900/80 border border-fuchsia-900/50 rounded-2xl p-5 space-y-4 shadow-lg shadow-fuchsia-950/30">
<div class="flex flex-wrap items-center justify-between gap-3 pb-3 border-b border-slate-800">
<div class="flex items-center space-x-2">
<div class="p-2 rounded-lg bg-fuchsia-950/80 border border-fuchsia-800 text-fuchsia-400">
<i class="fa-solid fa-rocket text-sm"></i>
</div>
<div>
<h3 class="font-bold text-slate-100 text-sm">GPU Overclock Control</h3>
<p class="text-xs text-slate-400">Per-app profiles auto-switch with the VRAM arbitrator</p>
</div>
</div>
<div class="flex items-center space-x-2">
<span id="oc-active-badge" class="px-2.5 py-1 text-xs font-mono rounded-lg bg-slate-800 border border-slate-700 text-slate-300">Active: --</span>
<span id="oc-x-badge" class="px-2.5 py-1 text-xs font-mono rounded-lg bg-slate-800 border border-slate-700 text-slate-400">X: --</span>
</div>
</div>
<!-- Profile quick-select -->
<div class="grid grid-cols-3 gap-3">
<button id="oc-btn-ollama" onclick="applyOverclock('ollama')" class="py-2.5 rounded-xl border text-xs font-bold transition flex items-center justify-center space-x-2 bg-purple-950/60 border-purple-800 text-purple-300 hover:bg-purple-900/60">
<i class="fa-solid fa-brain"></i><span>Ollama</span>
</button>
<button id="oc-btn-comfy" onclick="applyOverclock('comfy')" class="py-2.5 rounded-xl border text-xs font-bold transition flex items-center justify-center space-x-2 bg-cyan-950/60 border-cyan-800 text-cyan-300 hover:bg-cyan-900/60">
<i class="fa-solid fa-palette"></i><span>ComfyUI</span>
</button>
<button id="oc-btn-balanced" onclick="applyOverclock('balanced')" class="py-2.5 rounded-xl border text-xs font-bold transition flex items-center justify-center space-x-2 bg-slate-800/60 border-slate-700 text-slate-300 hover:bg-slate-700/60">
<i class="fa-solid fa-scale-balanced"></i><span>Balanced</span>
</button>
</div>
<!-- Live status readback -->
<div class="grid grid-cols-2 sm:grid-cols-4 gap-3 font-mono text-center">
<div class="p-3 rounded-xl bg-slate-950 border border-slate-800">
<span class="text-[10px] text-slate-400 uppercase block">Power Limit</span>
<span id="oc-power-limit" class="text-lg font-bold text-amber-400">-- W</span>
</div>
<div class="p-3 rounded-xl bg-slate-950 border border-slate-800">
<span class="text-[10px] text-slate-400 uppercase block">Core Clock</span>
<span id="oc-core" class="text-lg font-bold text-cyan-400">--</span>
</div>
<div class="p-3 rounded-xl bg-slate-950 border border-slate-800">
<span class="text-[10px] text-slate-400 uppercase block">Mem Clock</span>
<span id="oc-mem" class="text-lg font-bold text-purple-400">--</span>
</div>
<div class="p-3 rounded-xl bg-slate-950 border border-slate-800">
<span class="text-[10px] text-slate-400 uppercase block">Temp / Draw</span>
<span id="oc-temp-draw" class="text-lg font-bold text-emerald-400">--</span>
</div>
</div>
<!-- GPU FAN COOLING CONTROL -->
<div class="p-4 rounded-xl bg-slate-950 border border-slate-800 space-y-4">
<div class="flex flex-wrap items-center justify-between gap-2">
<div class="flex items-center space-x-2">
<i id="oc-fan-card-icon" class="fa-solid fa-fan text-emerald-400 text-sm fan-spinning"></i>
<div>
<span class="text-xs font-semibold text-slate-200 uppercase font-mono block">GPU Fan Cooling Control</span>
<span class="text-[10px] text-slate-400 font-mono">Dual-fan PWM active speed regulation</span>
</div>
</div>
<span id="oc-fan-badge" class="px-2.5 py-1 text-xs font-mono rounded-lg bg-emerald-950/80 border border-emerald-700 text-emerald-300 font-bold">
AUTO (VBIOS)
</span>
</div>
<!-- Fan Presets -->
<div class="grid grid-cols-2 sm:grid-cols-5 gap-2">
<button onclick="setFanAuto()" class="py-1.5 px-2 rounded-lg bg-slate-900 hover:bg-slate-800 border border-slate-700 text-slate-300 text-xs font-mono font-semibold transition text-center flex items-center justify-center space-x-1">
<i class="fa-solid fa-wand-magic-sparkles text-cyan-400 text-[10px]"></i>
<span>Auto (VBIOS)</span>
</button>
<button onclick="setFanManual(50)" class="py-1.5 px-2 rounded-lg bg-slate-900 hover:bg-slate-800 border border-slate-700 text-slate-300 text-xs font-mono font-semibold transition text-center">
50% Quiet
</button>
<button onclick="setFanManual(65)" class="py-1.5 px-2 rounded-lg bg-slate-900 hover:bg-slate-800 border border-slate-700 text-slate-300 text-xs font-mono font-semibold transition text-center">
65% Balanced
</button>
<button onclick="setFanManual(80)" class="py-1.5 px-2 rounded-lg bg-slate-900 hover:bg-slate-800 border border-slate-700 text-slate-300 text-xs font-mono font-semibold transition text-center">
80% Heavy
</button>
<button onclick="setFanManual(100)" class="py-1.5 px-2 rounded-lg bg-rose-950/60 hover:bg-rose-900/80 border border-rose-800 text-rose-300 text-xs font-mono font-bold transition text-center flex items-center justify-center space-x-1">
<i class="fa-solid fa-gauge-max text-rose-400 text-[10px]"></i>
<span>100% Turbo</span>
</button>
</div>
<!-- Live Dual-Fan Meters -->
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3 p-3 rounded-lg bg-slate-900/60 border border-slate-800/80 text-xs font-mono">
<div class="space-y-1">
<div class="flex justify-between text-slate-400">
<span class="flex items-center space-x-1"><i class="fa-solid fa-fan text-[10px] text-cyan-400"></i><span>Fan 0 (Intake/Core):</span></span>
<span id="oc-fan0-val" class="font-bold text-slate-100">--%</span>
</div>
<div class="w-full bg-slate-950 rounded-full h-2 overflow-hidden border border-slate-800">
<div id="oc-fan0-bar" class="bg-gradient-to-r from-cyan-500 to-emerald-400 h-full rounded-full transition-all duration-300" style="width: 0%"></div>
</div>
</div>
<div class="space-y-1">
<div class="flex justify-between text-slate-400">
<span class="flex items-center space-x-1"><i class="fa-solid fa-fan text-[10px] text-purple-400"></i><span>Fan 1 (Exhaust/VRM):</span></span>
<span id="oc-fan1-val" class="font-bold text-slate-100">--%</span>
</div>
<div class="w-full bg-slate-950 rounded-full h-2 overflow-hidden border border-slate-800">
<div id="oc-fan1-bar" class="bg-gradient-to-r from-purple-500 to-emerald-400 h-full rounded-full transition-all duration-300" style="width: 0%"></div>
</div>
</div>
</div>
<!-- Custom Manual Slider -->
<div class="space-y-2">
<div class="flex justify-between items-center text-xs">
<span class="text-slate-400">Custom Manual Target:</span>
<span id="oc-fan-slider-label" class="font-mono text-emerald-400 font-bold">65%</span>
</div>
<div class="flex items-center space-x-3">
<input id="oc-fan-slider" type="range" min="30" max="100" step="1" value="65" oninput="document.getElementById('oc-fan-slider-label').textContent=this.value+'%'" class="flex-1 accent-emerald-500">
<button onclick="setFanManual(parseInt(document.getElementById('oc-fan-slider').value))" class="px-3.5 py-1.5 rounded-lg bg-gradient-to-r from-emerald-600 to-teal-600 hover:from-emerald-500 hover:to-teal-500 text-white text-xs font-bold font-mono shadow transition flex items-center space-x-1">
<i class="fa-solid fa-check"></i>
<span>Apply</span>
</button>
</div>
</div>
</div>
<!-- GPU SPECS STRIP -->
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-2 font-mono text-center">
<div class="p-2 rounded-lg bg-slate-950 border border-slate-800">
<span class="text-[9px] text-slate-500 uppercase block">GPU</span>
<span id="oc-spec-gpu" class="text-[11px] font-bold text-slate-200 block truncate">--</span>
</div>
<div class="p-2 rounded-lg bg-slate-950 border border-slate-800">
<span class="text-[9px] text-slate-500 uppercase block">Driver</span>
<span id="oc-spec-driver" class="text-[11px] font-bold text-cyan-400 block">--</span>
</div>
<div class="p-2 rounded-lg bg-slate-950 border border-slate-800">
<span class="text-[9px] text-slate-500 uppercase block">VRAM</span>
<span id="oc-spec-vram" class="text-[11px] font-bold text-purple-400 block">--</span>
</div>
<div class="p-2 rounded-lg bg-slate-950 border border-slate-800">
<span class="text-[9px] text-slate-500 uppercase block">Max Core</span>
<span id="oc-spec-maxcore" class="text-[11px] font-bold text-cyan-400 block">--</span>
</div>
<div class="p-2 rounded-lg bg-slate-950 border border-slate-800">
<span class="text-[9px] text-slate-500 uppercase block">Max Mem</span>
<span id="oc-spec-maxmem" class="text-[11px] font-bold text-purple-400 block">--</span>
</div>
<div class="p-2 rounded-lg bg-slate-950 border border-slate-800">
<span class="text-[9px] text-slate-500 uppercase block">Power</span>
<span id="oc-spec-power" class="text-[11px] font-bold text-amber-400 block">--</span>
</div>
</div>
<!-- LIVE TIME-SERIES GRAPH (clocks + temp + fan) -->
<div class="rounded-xl bg-slate-950 border border-slate-800 p-3">
<div class="flex items-center justify-between mb-2">
<span class="text-xs font-semibold text-slate-300 uppercase font-mono">
<i class="fa-solid fa-chart-line text-fuchsia-400 mr-1"></i>Live Tuning Graph
</span>
<div class="flex flex-wrap items-center gap-x-3 gap-y-1 text-[10px] font-mono">
<span class="flex items-center space-x-1"><span class="w-2 h-2 rounded-full bg-cyan-400 inline-block"></span>Core MHz</span>
<span class="flex items-center space-x-1"><span class="w-2 h-2 rounded-full bg-purple-400 inline-block"></span>Mem MHz</span>
<span class="flex items-center space-x-1"><span class="w-2 h-2 rounded-full bg-rose-400 inline-block"></span>Temp °C</span>
<span class="flex items-center space-x-1"><span class="w-2 h-2 rounded-full bg-amber-400 inline-block"></span>Power W</span>
<span class="flex items-center space-x-1"><span class="w-2 h-2 rounded-full bg-emerald-400 inline-block"></span>Fan %</span>
<span class="flex items-center space-x-1"><span class="w-2 h-2 rounded-full bg-indigo-400 inline-block"></span>VRAM GB</span>
<span class="flex items-center space-x-1"><span class="w-2 h-2 rounded-full bg-fuchsia-400 inline-block"></span>RAM Cache GB</span>
</div>
</div>
<div class="relative h-64">
<canvas id="oc-chart"></canvas>
</div>
</div>
<!-- Fine-tune sliders for the selected profile -->
<div class="p-4 rounded-xl bg-slate-950 border border-slate-800 space-y-4">
<div class="flex items-center justify-between">
<span class="text-xs font-semibold text-slate-300 uppercase font-mono">Fine-tune profile</span>
<select id="oc-edit-profile" onchange="loadOverclockForProfile(this.value)" class="bg-slate-900 border border-slate-700 rounded-lg px-2 py-1 text-xs font-mono text-slate-200 focus:outline-none focus:border-fuchsia-500">
<option value="ollama">ollama</option>
<option value="comfy">comfy</option>
<option value="balanced">balanced</option>
</select>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-5">
<div>
<label class="text-xs text-slate-400 flex justify-between"><span>Power Limit</span><span id="oc-val-power" class="font-mono text-amber-400">370 W</span></label>
<input id="oc-slider-power" type="range" min="150" max="370" step="5" value="370" oninput="document.getElementById('oc-val-power').textContent=this.value+' W'" class="w-full accent-amber-500">
</div>
<div>
<label class="text-xs text-slate-400 flex justify-between"><span>Core Offset</span><span id="oc-val-core" class="font-mono text-cyan-400">+100 MHz</span></label>
<input id="oc-slider-core" type="range" min="0" max="200" step="5" value="100" oninput="document.getElementById('oc-val-core').textContent='+'+this.value+' MHz'" class="w-full accent-cyan-500">
</div>
<div>
<label class="text-xs text-slate-400 flex justify-between"><span>Memory Offset</span><span id="oc-val-mem" class="font-mono text-purple-400">+500 MHz</span></label>
<input id="oc-slider-mem" type="range" min="0" max="1000" step="25" value="500" oninput="document.getElementById('oc-val-mem').textContent='+'+this.value+' MHz'" class="w-full accent-purple-500">
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-5">
<div>
<label class="text-xs text-slate-400 flex justify-between"><span>Core Clock Lock</span><span id="oc-val-lockcore" class="font-mono text-slate-400">Off</span></label>
<div class="flex items-center space-x-2">
<input id="oc-lockcore-toggle" type="checkbox" onchange="toggleCoreLock()" class="w-4 h-4 accent-cyan-500">
<span class="text-xs text-slate-500">Lock core to max boost (29003105 MHz)</span>
</div>
</div>
<div>
<label class="text-xs text-slate-400 flex justify-between"><span>Memory Clock Lock</span><span id="oc-val-lockmem" class="font-mono text-slate-400">Off</span></label>
<div class="flex items-center space-x-2">
<input id="oc-lockmem-toggle" type="checkbox" onchange="toggleMemLock()" class="w-4 h-4 accent-purple-500">
<span class="text-xs text-slate-500">Lock mem to max (11501 MHz)</span>
</div>
</div>
</div>
<!-- Per-Profile Fan Settings -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-5 pt-3 border-t border-slate-900">
<div>
<label class="text-xs text-slate-400 flex justify-between"><span>Profile Fan Mode</span><span id="oc-val-prof-fanmode" class="font-mono text-emerald-400">Auto</span></label>
<select id="oc-prof-fanmode" onchange="toggleProfileFanMode()" class="w-full bg-slate-900 border border-slate-700 rounded-lg px-3 py-2 text-xs font-mono text-slate-200 mt-1 focus:outline-none focus:border-emerald-500">
<option value="auto">Auto (VBIOS Dynamic Curve)</option>
<option value="manual">Manual (Locked Target %)</option>
</select>
</div>
<div id="oc-prof-fanspeed-container" class="opacity-50 pointer-events-none transition">
<label class="text-xs text-slate-400 flex justify-between"><span>Profile Fan Target</span><span id="oc-val-prof-fanspeed" class="font-mono text-emerald-400">70%</span></label>
<input id="oc-slider-prof-fanspeed" type="range" min="30" max="100" step="5" value="70" oninput="document.getElementById('oc-val-prof-fanspeed').textContent=this.value+'%'" class="w-full accent-emerald-500 mt-2">
</div>
</div>
<div class="flex items-center justify-between pt-2">
<span id="oc-offset-note" class="text-[11px] font-mono text-slate-500"></span>
<button onclick="saveOverclockProfile()" class="px-4 py-2 bg-gradient-to-r from-fuchsia-600 to-purple-600 hover:from-fuchsia-500 hover:to-purple-500 text-white text-xs font-bold rounded-lg shadow-md transition flex items-center space-x-1.5">
<i class="fa-solid fa-floppy-disk"></i><span>Save Profile</span>
</button>
</div>
</div>
</div>
</main>
<script src="/static/app.js"></script>
</body>
</html>