(function () { 'use strict'; const d = window.DBN_DASHBOARD || {}; const apiBase = (d.apiBase || '/api/dashboard') + '/engines.php'; const $context = document.getElementById('engContext'); const $tier = document.getElementById('engTierPanel'); const $persona = document.getElementById('engPersonaPanel'); const $refresh = document.getElementById('engRefresh'); const safe = s => String(s == null ? '' : s).replace(/[&<>"]/g, c => ({ '&':'&','<':'<','>':'>','"':'"' }[c])); let tierEngines = []; let reviewerModels = []; function optionsHtml(list, selected) { return list.map(o => '' ).join(''); } function toolLabel(row) { if (row.tool_slug === '*') { return row.scope.indexOf('persona') === 0 ? 'All personas' : 'All tier tools'; } return row.tool_slug; } function rowHtml(row, list) { const list2 = list; const sel = row.override || row.code_default; const badge = row.override ? 'override' : 'default'; const meta = row.override && row.updated_by ? '
by ' + safe(row.updated_by) + (row.updated_at ? ' · ' + safe(row.updated_at) : '') + '
' : ''; return '
' + '
' + safe(toolLabel(row)) + '' + '
default: ' + safe(row.code_default || '—') + '
' + meta + '
' + '
' + safe(row.scope) + '
' + '
' + '
' + badge + (row.override ? '' : '') + '
' + '
'; } function headHtml() { return '
Tool
Scope
Engine
'; } function render(data) { tierEngines = data.tier_engines || []; reviewerModels = data.reviewer_models || []; const ctx = data.context || {}; $context.innerHTML = 'Bedrock: ' + (ctx.bedrock_enabled ? 'ON' : 'OFF') + ' — ' + safe(ctx.note || ''); const rows = data.rows || []; const tierRows = rows.filter(r => r.scope.indexOf('persona') !== 0); const personaRows = rows.filter(r => r.scope.indexOf('persona') === 0); $tier.innerHTML = headHtml() + tierRows.map(r => rowHtml(r, tierEngines)).join(''); $persona.innerHTML = headHtml() + personaRows.map(r => rowHtml(r, reviewerModels)).join(''); bind($tier); bind($persona); } function bind(panel) { panel.querySelectorAll('.eng-row').forEach(rowEl => { const tool = rowEl.getAttribute('data-tool'); const scope = rowEl.getAttribute('data-scope'); const select = rowEl.querySelector('.eng-select'); const clearBtn = rowEl.querySelector('.eng-clear'); if (select) { select.addEventListener('change', () => save(tool, scope, select.value, rowEl)); } if (clearBtn) { clearBtn.addEventListener('click', () => clear(tool, scope, rowEl)); } }); } function setBusy(rowEl, busy) { rowEl.querySelectorAll('select, button').forEach(el => { el.disabled = busy; }); } async function post(action, body) { const r = await fetch(apiBase + '?action=' + action, { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }); const data = await r.json(); if (!data.ok) throw new Error(data.message || 'Request failed'); return data; } async function save(tool, scope, engine, rowEl) { setBusy(rowEl, true); try { await post('set', { tool_slug: tool, scope: scope, engine: engine }); await load(); } catch (e) { alert('Could not save: ' + e.message); setBusy(rowEl, false); } } async function clear(tool, scope, rowEl) { setBusy(rowEl, true); try { await post('clear', { tool_slug: tool, scope: scope }); await load(); } catch (e) { alert('Could not clear: ' + e.message); setBusy(rowEl, false); } } async function load() { $tier.innerHTML = '
'; $persona.innerHTML = '
'; try { const r = await fetch(apiBase, { credentials: 'same-origin' }); const data = await r.json(); if (!data.ok) throw new Error(data.message || 'Could not load engine map'); render(data); } catch (e) { $context.textContent = 'Could not load: ' + e.message; $tier.innerHTML = ''; $persona.innerHTML = ''; } } if ($refresh) $refresh.addEventListener('click', load); load(); })();