/* Warm-up helper for the in-weights backend (Meta Muse Glimmer 30B + ViKernel, GPU unit). The backend sleeps when idle to save cost. While it wakes, every app shows "Loading the model n%" with the current start-up step instead of an error. Only apps that need the in-weights model call this (no polling otherwise). */ (() => { 'use strict'; const css = document.createElement('style'); css.textContent = `.vkwarm{border:1px solid var(--border);border-radius:10px;padding:8px 10px;background:var(--card);font:13px system-ui,'Segoe UI',sans-serif} .vkwarm .vkw-t{display:flex;justify-content:space-between;gap:8px;font-weight:700}.vkwarm .vkw-s{color:var(--muted);font-size:12px;margin-top:2px} .vkwarm .vkw-b{height:8px;border-radius:99px;background:var(--bg);overflow:hidden;margin-top:6px}.vkwarm .vkw-f{height:100%;width:0;background:linear-gradient(90deg,#6366F1,#0F766E);transition:width .8s ease} .vkwarm.ready .vkw-f{background:#16A34A}`; document.head.append(css); let last = null, maxPct = 0; async function health() { const ctl = new AbortController(); const to = setTimeout(() => ctl.abort(), 12000); try { const r = await fetch('api/agx/health', {cache:'no-store', signal:ctl.signal, headers:{'X-VK-Session':window.VK_SID || ''}}); if (!r.ok) return null; return await r.json(); } catch (e) { return null; } finally { clearTimeout(to); } } const ready = (h, needGpu) => !!(h && h.live && (!needGpu || (h.gpu_unit && h.gpu_unit.live))); function info(h, needGpu) { if (ready(h, needGpu)) { maxPct = 100; return {pct:100, label:'ready', eta:0}; } const L = (h && h.loading) || {pct:2, label:'waking the in-weights model'}; let pct = Math.min(99, L.pct || 0); if (h && h.live && needGpu && pct < 80) pct = 80; // chat is up, GPU unit still loading maxPct = Math.max(maxPct, pct); return {pct:maxPct, label:L.label || L.stage || 'loading', eta:L.eta_s}; } // a small progress card; call .set(info) to update function bar() { const d = document.createElement('div'); d.className = 'vkwarm'; d.innerHTML = '
Loading the model 0%
checking the in-weights backend...
'; d.set = i => { const q = k => d.querySelector(`[data-w="${k}"]`); d.classList.toggle('ready', i.pct >= 100); q('t').textContent = i.pct >= 100 ? 'Model ready' : `Loading the model ${i.pct}%`; q('s').textContent = i.pct >= 100 ? 'Meta Muse Glimmer 30B + ViKernel in-weights is live.' : i.label + '. The model sleeps when idle to save cost; the first wake takes about 4 minutes.'; q('e').textContent = i.pct >= 100 || i.eta == null ? '' : `about ${Math.max(1, Math.round(i.eta / 60))} min left`; q('f').style.width = i.pct + '%'; }; return d; } // resolves true when ready; onProgress(info) on every poll. alive() false stops polling (window closed). async function wait({needGpu = true, onProgress = () => {}, alive = () => true, maxMs = 600000} = {}) { const t0 = Date.now(); while (Date.now() - t0 < maxMs && alive()) { const h = await health(); last = h; const i = info(h, needGpu); onProgress(i, h); if (i.pct >= 100) return true; await new Promise(r => setTimeout(r, 5000)); } return false; } window.VK_WARM = {health, wait, bar, ready, info, last:() => last}; })();