feat: settings model selector for news summarizer

This commit is contained in:
Sirius DevOps 2026-08-27 23:29:35 -04:00
parent d93ad88956
commit 610666ef6a

View file

@ -979,6 +979,30 @@
</div>
<div class="set-saved" id="mkt-saved"></div>
</div>
<div class="panel">
<h3>News Summarizer</h3>
<p class="set-note" style="margin-bottom:0.9rem">Takes effect on the next hourly run (:05). No container restart.</p>
<div class="set-row">
<label>Provider</label>
<span>Nous Portal (inference-api.nousresearch.com)</span>
</div>
<div class="set-row">
<label>API key</label>
<span>set in API Keys as NOUS_API_KEY (never shown here)</span>
</div>
<div class="set-row">
<label for="set-summary-model">Model</label>
<select id="set-summary-model"></select>
</div>
<div class="set-row">
<label>Current</label>
<span id="set-summary-model-now"></span>
</div>
<div class="set-actions">
<button class="btn" onclick="saveSummaryModel()">Save model</button>
</div>
<div class="set-saved" id="sum-saved"></div>
</div>
<div class="panel">
<h3>Map Defaults</h3>
<p class="set-note" style="margin-bottom:0.9rem">Applied to the live map on load.</p>
@ -1025,7 +1049,7 @@
<div class="sys-row"><span class="k">Active sources</span><span class="v" id="sys-sources"></span></div>
<div class="sys-row"><span class="k">Open alerts</span><span class="v" id="sys-alerts"></span></div>
<div class="sys-row"><span class="k">Tracked entities</span><span class="v" id="sys-entities"></span></div>
<div class="sys-row"><span class="k">News cycle</span><span class="v">15 min</span></div>
<div class="sys-row"><span class="k">News cycle</span><span class="v">hourly :05</span></div>
<div class="sys-row"><span class="k">Market feed</span><span class="v" id="sys-market">STANDBY</span></div>
</div>
<div class="set-actions">
@ -1051,7 +1075,7 @@
<div class="tick-wrap">
<div class="tick-track" id="nt-track"></div>
</div>
<div class="tick-tag" id="nt-tag">15-MIN CYCLE</div>
<div class="tick-tag" id="nt-tag">HOURLY</div>
</div>
</footer>
@ -1181,7 +1205,7 @@ function showView(name) {
}
if (name === 'news') loadNews(false);
if (name === 'events') { loadSummary(); loadEvents(); }
if (name === 'settings') { loadSummary(); renderSysInfo(); }
if (name === 'settings') { loadSummary(); renderSysInfo(); loadSettings(); }
window.scrollTo(0, 0);
}
@ -1657,6 +1681,55 @@ function initSettings() {
}
} catch (e) {}
}
async function loadSettings() {
const sel = document.getElementById('set-summary-model');
const now = document.getElementById('set-summary-model-now');
try {
const [setR, modR] = await Promise.all([
fetch(`${API}/api/settings`),
fetch(`${API}/api/news/models`),
]);
const settings = setR.ok ? await setR.json() : {};
const catalog = modR.ok ? await modR.json() : {models: []};
const saved = (settings.summary_model || '').trim();
const ids = (catalog.models || []).map(m => m && m.id).filter(Boolean);
if (saved && ids.indexOf(saved) === -1) ids.unshift(saved);
if (sel) {
sel.innerHTML = ids.map(id => `<option value="${esc(id)}">${esc(id)}</option>`).join('');
if (saved) sel.value = saved;
}
if (now) now.textContent = saved || '—';
} catch (e) {
console.error('Settings load failed', e);
}
}
async function saveSummaryModel() {
const sel = document.getElementById('set-summary-model');
const flash = document.getElementById('sum-saved');
const now = document.getElementById('set-summary-model-now');
const summary_model = ((sel && sel.value) || '').trim();
if (!summary_model) {
if (flash) flash.textContent = 'Choose a model to save.';
return;
}
try {
const r = await fetch(`${API}/api/settings`, {
method: 'PUT',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({summary_model}),
});
const d = await r.json().catch(() => ({}));
if (!r.ok) {
if (flash) flash.textContent = (typeof d.detail === 'string' ? d.detail : 'Save failed');
return;
}
if (now) now.textContent = d.summary_model || summary_model;
if (sel && d.summary_model) sel.value = d.summary_model;
if (flash) flash.textContent = 'Model saved.';
} catch (e) {
if (flash) flash.textContent = 'Network error.';
}
}
/* ═══════════════ MAP (NASA GIBS basemap + FIRMS + cameras + blips) ═══════
The satellite map core is production-proven — preserved verbatim. */