async function refreshInternals() {
let d;
try {
const r = await fetch('/api/internals');
d = await r.json();
} catch(e) { return; }
setRows('tb-int-health', (d.st_health||[]).map(r => {
const dot = r.is_populated
? '●'
: '○';
const ts = r.last_refresh ? new Date(r.last_refresh).toLocaleTimeString() : '—';
const dur = r.duration_ms != null ? r.duration_ms + ' ms' : '—';
const rows = r.rows_affected != null ? fmt(r.rows_affected) : '—';
return `
| ${esc(r.name)} |
${esc(r.refresh_mode)} |
${esc(r.schedule||'calc')} |
${dot} |
${ts} |
${dur} |
${rows} |
${esc(r.status)} |
`;
}).join(''));
document.getElementById('pre-dep-tree').textContent =
(d.dep_tree||[]).join('\n') || '(no dependency data)';
setRows('tb-int-history', (d.refresh_history||[]).map(r => {
const fallback = r.was_full_fallback
? ' ▲' : '';
const statusCol = r.status === 'FAILED' ? 'color:var(--red)' : 'color:var(--muted)';
const ts = r.start_time ? new Date(r.start_time).toLocaleTimeString() : '—';
return `
| ${esc(r.name)} |
${esc(r.refresh_mode)}${fallback} |
${ts} |
${r.duration_ms != null ? r.duration_ms : '—'} |
${r.rows_affected != null ? fmt(r.rows_affected) : '—'} |
${esc(r.status)} |
`;
}).join(''));
setRows('tb-int-eff', (d.efficiency||[]).map(r =>
`
| ${esc(r.name)} |
${fmt(r.total_refreshes)} |
${fmt(r.diff_count)} |
${fmt(r.full_count)} |
${r.avg_diff_ms != null ? Number(r.avg_diff_ms).toFixed(1) : '—'} |
${r.avg_full_ms != null ? Number(r.avg_full_ms).toFixed(1) : '—'} |
${esc(r.diff_speedup||'—')} |
${r.avg_change_ratio != null ? Number(r.avg_change_ratio).toFixed(3) : '—'} |
`).join(''));
setRows('tb-int-advisor', (d.opt_hints||[]).map(r => {
const keep = r.recommended_mode === 'KEEP';
const recHtml = keep
? `✓ KEEP ${esc(r.current_mode)}`
: `→ SWITCH TO ${esc(r.recommended_mode)}`;
const confClass = r.confidence === 'high' ? 'conf-high'
: r.confidence === 'medium' ? 'conf-medium' : 'conf-low';
return `
| ${esc(r.name)} |
${esc(r.current_mode)} |
${esc(r.effective_mode||'—')} |
${recHtml} |
${esc(r.confidence||'—')} |
${esc(r.reason||'')} |
`;
}).join(''));
}
document.getElementById('tab-internals-btn')
.addEventListener('shown.bs.tab', refreshInternals);
document.getElementById('tab-internals-btn')
.addEventListener('shown.bs.tab', refreshInternals);
setInterval(refreshInternals, 5000);