(function (global) { function fmtHz(value) { if (!Number.isFinite(value)) return 'n/a'; if (value >= 1e6) return `${(value / 1e6).toFixed(3)} MHz`; if (value >= 1e3) return `${(value / 1e3).toFixed(2)} kHz`; return `${Math.round(value)} Hz`; } function fmtAgeShort(ms) { if (!Number.isFinite(ms) || ms < 0) return '-'; if (ms < 1000) return `${Math.round(ms)} ms`; if (ms < 60000) return `${(ms / 1000).toFixed(1)} s`; return `${Math.round(ms / 60000)} min`; } function applyStatusClass(el, level) { if (!el) return; el.classList.remove('status-val--ok', 'status-val--warn', 'status-val--bad'); if (level === 'ok') el.classList.add('status-val--ok'); if (level === 'warn') el.classList.add('status-val--warn'); if (level === 'bad') el.classList.add('status-val--bad'); } function levelSummary(level) { if (!level || typeof level !== 'object') return 'n/a'; const bits = []; if (level.name) bits.push(level.name); if (Number.isFinite(level.fft_size) && level.fft_size > 0) bits.push(`${level.fft_size} bins`); if (Number.isFinite(level.span_hz) && level.span_hz > 0) bits.push(fmtHz(level.span_hz)); return bits.join(' · ') || 'n/a'; } function summarizeReason(reason) { if (!reason) return 'n/a'; const parts = String(reason).split(':').filter(Boolean); if (!parts.length) return 'n/a'; const tail = parts.slice(-3); const compact = tail.join(' › '); return compact.length > 64 ? compact.slice(0, 61) + '…' : compact; } function renderRefinementDetails(root, refinementInfo) { if (!root) return; const plan = refinementInfo?.plan || {}; const queue = refinementInfo?.arbitration?.queue || {}; const summary = refinementInfo?.arbitration?.decision_summary || {}; const reasons = summary?.reasons || {}; const topReason = Object.entries(reasons).sort((a, b) => Number(b[1]) - Number(a[1]))[0]; const primary = refinementInfo?.surveillance_level_set?.primary || refinementInfo?.surveillance_level; const display = refinementInfo?.surveillance_level_set?.presentation || refinementInfo?.display_level; const spans = refinementInfo?.window_summary?.refinement || refinementInfo?.window_stats || {}; const rows = [ `Budget: ${(plan.selected || []).length}/${plan.budget || 0}`, `Queue: rec ${queue.record_queued || 0} · dec ${queue.decode_queued || 0}`, `Drop: snr ${plan.dropped_by_snr || 0} · budget ${plan.dropped_by_budget || 0}`, `Reason: ${topReason ? `${summarizeReason(topReason[0])} (${topReason[1]})` : 'n/a'}`, `Primary: ${levelSummary(primary)}`, `Display: ${levelSummary(display)}`, `Windows: ${spans.count ? `${spans.count} · ${fmtHz(spans.min_span_hz || 0)}-${fmtHz(spans.max_span_hz || 0)}` : 'n/a'}` ]; root.innerHTML = rows.map((row) => `
${row}
`).join(''); } function renderTelemetryEvents(root, telemetryLive) { if (!root) return; const items = Array.isArray(telemetryLive?.recent_events) ? telemetryLive.recent_events.slice(0, 6) : []; if (!items.length) { root.innerHTML = '
No recent telemetry events.
'; return; } root.innerHTML = items.map((item) => { const ts = item?.timestamp ? new Date(item.timestamp).toLocaleTimeString() : '--:--:--'; const level = item?.level || 'info'; const name = item?.name || item?.metric || item?.category || 'event'; const detail = item?.message || item?.detail || item?.summary || ''; const shortDetail = detail ? String(detail).slice(0, 72) : ''; return `
${level}${ts}${name}${shortDetail ? ` · ${shortDetail}` : ''}
`; }).join(''); } function create(elements) { function updateStatus(data) { const { wsState, wsLastMessageTs, apiState, configStatusText, refinementInfo, telemetryLive, sourceAgeMs } = data; if (elements.healthWs) { const age = wsLastMessageTs > 0 ? fmtAgeShort(Date.now() - wsLastMessageTs) : '-'; elements.healthWs.textContent = `${wsState} · last ${age}`; applyStatusClass(elements.healthWs, wsState === 'live' ? 'ok' : (wsState === 'retrying' ? 'bad' : 'warn')); } if (elements.healthApi) { const latency = Number.isFinite(apiState?.latencyMs) ? `${apiState.latencyMs} ms` : 'n/a'; const isOk = !!apiState?.ok; elements.healthApi.textContent = isOk ? `ok · ${latency}` : `degraded · ${apiState?.lastError || 'n/a'}`; applyStatusClass(elements.healthApi, isOk ? 'ok' : 'bad'); } if (elements.healthConfig) { elements.healthConfig.textContent = configStatusText || '-'; applyStatusClass(elements.healthConfig, /failed|offline/i.test(configStatusText || '') ? 'bad' : 'ok'); } if (elements.healthRefine) { const plan = refinementInfo?.plan || {}; const queue = refinementInfo?.arbitration?.queue || {}; const budget = Number(plan?.budget || 0); const selected = Number((plan?.selected || []).length || 0); elements.healthRefine.textContent = `${selected}/${budget} · q ${queue.record_queued || 0}/${queue.decode_queued || 0}`; applyStatusClass(elements.healthRefine, budget > 0 && selected >= budget ? 'warn' : 'ok'); } if (elements.healthTelemetry) { if (!telemetryLive) { elements.healthTelemetry.textContent = 'unavailable'; applyStatusClass(elements.healthTelemetry, 'bad'); } else { const enabled = telemetryLive.enabled === false ? 'off' : 'on'; const collector = telemetryLive.collector || {}; const recent = Array.isArray(telemetryLive.recent_events) ? telemetryLive.recent_events.length : 0; const heavy = collector.heavy_enabled ? 'heavy' : 'light'; elements.healthTelemetry.textContent = `${enabled} · ${heavy} · events ${recent}`; applyStatusClass(elements.healthTelemetry, enabled === 'on' ? 'ok' : 'warn'); } } if (elements.healthSource) { const text = Number.isFinite(sourceAgeMs) && sourceAgeMs >= 0 ? `${sourceAgeMs} ms` : 'n/a'; elements.healthSource.textContent = text; applyStatusClass(elements.healthSource, Number.isFinite(sourceAgeMs) && sourceAgeMs < 1500 ? 'ok' : 'warn'); } renderRefinementDetails(elements.refineDetails, refinementInfo); renderTelemetryEvents(elements.telemetryEvents, telemetryLive); } return { updateStatus }; } global.OperatorPanel = { create }; })(window);