(() => { const state = { last: { codex: null, devin: null }, refresh: 10, countdowns: new Map() }; const byId = (id) => document.getElementById(id); const text = (node, value) => { node.textContent = value; return node; }; const fmt = (value) => Number.isInteger(value) ? String(value) : Number(value).toFixed(1).replace(/\.0$/, ''); const clockValue = (date) => date.toLocaleTimeString([], { hour12: false }); const remainingClass = (value) => value < 20 ? 'red' : value <= 50 ? 'amber' : ''; const amount = (limit) => { if (limit.used != null && limit.limit != null) return `${fmt(limit.used)} / ${fmt(limit.limit)} ${limit.unit || ''}`.trim(); if (limit.used != null) return `${fmt(limit.used)} ${limit.unit || ''}`.trim(); if (limit.remaining != null) return `${fmt(limit.remaining)} ${limit.unit || ''}`.trim(); return ''; }; const countdown = (date) => { const delta = new Date(date).getTime() - Date.now(); if (!Number.isFinite(delta) || delta <= 0) return 'Reset due'; let seconds = Math.floor(delta / 1000); const days = Math.floor(seconds / 86400); seconds %= 86400; const hours = Math.floor(seconds / 3600); seconds %= 3600; const minutes = Math.floor(seconds / 60); seconds %= 60; if (days) return `Reset in ${days}d ${String(hours).padStart(2, '0')}h ${String(minutes).padStart(2, '0')}m`; return `Reset in ${String(hours).padStart(2, '0')}h ${String(minutes).padStart(2, '0')}m ${String(seconds).padStart(2, '0')}s`; }; const updateClock = () => text(byId('clock'), clockValue(new Date())); const updateCountdowns = () => state.countdowns.forEach((date, node) => text(node, countdown(date))); const renderLimit = (limit, prior) => { const item = document.createElement('section'); item.className = 'limit'; const top = document.createElement('div'); top.className = 'limit-top'; const name = document.createElement('span'); name.className = 'limit-name'; text(name, limit.name || 'Usage limit'); top.append(name); if (limit.remaining_percent != null) { const remaining = document.createElement('strong'); remaining.className = `remaining ${remainingClass(limit.remaining_percent)}`; text(remaining, `${fmt(limit.remaining_percent)}%`); top.append(remaining); } item.append(top); if (limit.remaining_percent != null) { const target = Math.max(0, Math.min(100, limit.remaining_percent)); const bar = document.createElement('div'); bar.className = 'bar'; bar.setAttribute('role', 'progressbar'); bar.setAttribute('aria-valuemin', '0'); bar.setAttribute('aria-valuemax', '100'); bar.setAttribute('aria-valuenow', String(limit.remaining_percent)); const fill = document.createElement('div'); fill.className = `bar-fill ${remainingClass(limit.remaining_percent)}`; if (prior && Number.isFinite(prior.remaining_percent) && prior.remaining_percent !== limit.remaining_percent) { fill.style.width = `${Math.max(0, Math.min(100, prior.remaining_percent))}%`; requestAnimationFrame(() => { fill.style.width = `${target}%`; }); } else { fill.style.width = `${target}%`; } bar.append(fill); item.append(bar); } const meta = document.createElement('div'); meta.className = 'meta'; if (limit.remaining_percent == null && limit.used_percent == null) meta.classList.add('standalone'); if (limit.used_percent != null) { const used = document.createElement('span'); text(used, `${fmt(limit.used_percent)}% used`); meta.append(used); } const value = amount(limit); if (value) { const numeric = document.createElement('span'); numeric.className = 'amount'; text(numeric, value); meta.append(numeric); } if (meta.childNodes.length) item.append(meta); if (limit.reset_at) { const reset = document.createElement('div'); reset.className = 'reset'; text(reset, countdown(limit.reset_at)); state.countdowns.set(reset, limit.reset_at); item.append(reset); } return item; }; const clearContent = (content) => { while (content.firstChild) content.removeChild(content.firstChild); }; const renderProvider = (name, provider) => { const content = byId(`${name}-content`); const status = byId(`${name}-status`); status.className = `status-pill ${provider.status}`; text(status, provider.status === 'ok' ? 'LIVE' : provider.status === 'disabled' ? 'DISABLED' : 'ERROR'); if (provider.status === 'ok') { const prior = state.last[name]; state.last[name] = provider; state.countdowns.forEach((_, node) => { if (content.contains(node)) state.countdowns.delete(node); }); clearContent(content); provider.limits.forEach((limit) => { const priorLimit = prior && prior.limits.find((entry) => entry.id === limit.id); content.append(renderLimit(limit, priorLimit)); }); return; } if (provider.status === 'error' && state.last[name]) { if (!content.querySelector('.overlay')) { const overlay = document.createElement('div'); overlay.className = 'overlay'; const strong = document.createElement('strong'); text(strong, 'Data currently unavailable'); overlay.append(strong); const small = document.createElement('small'); const lastUpdate = provider.last_successful_update || state.last[name].last_successful_update; text(small, lastUpdate ? `Last successful update: ${clockValue(new Date(lastUpdate))}` : 'No successful update yet'); overlay.append(small); content.append(overlay); } return; } state.countdowns.forEach((_, node) => { if (content.contains(node)) state.countdowns.delete(node); }); clearContent(content); const notice = document.createElement('div'); notice.className = 'notice'; const strong = document.createElement('strong'); text(strong, provider.status === 'disabled' ? 'Provider disabled' : 'Data currently unavailable'); notice.append(strong); const detail = document.createElement('span'); text(detail, provider.status === 'disabled' ? 'Enable this provider in configuration to view usage.' : 'Waiting for a successful update.'); notice.append(detail); content.append(notice); }; const setConnection = (online) => { text(byId('connection-state'), online ? 'LIVE' : 'Connection error'); byId('connection-dot').classList.toggle('offline', !online); }; const fetchUsage = async () => { try { const response = await fetch('/api/usage', { cache: 'no-store' }); if (!response.ok) throw new Error('request failed'); const data = await response.json(); renderProvider('codex', data.codex); renderProvider('devin', data.devin); state.refresh = Math.max(1, Number(data.refresh_interval) || 10); byId('demo-badge').hidden = !data.demo_mode; setConnection(true); text(byId('last-update'), `Last update: ${clockValue(new Date(data.server_time))}`); window.clearInterval(state.networkTimer); state.networkTimer = window.setInterval(fetchUsage, state.refresh * 1000); } catch (_) { setConnection(false); window.clearInterval(state.networkTimer); state.networkTimer = window.setInterval(fetchUsage, state.refresh * 1000); } }; state.networkTimer = null; updateClock(); setInterval(() => { updateClock(); updateCountdowns(); }, 1000); fetchUsage(); })();