feat: overhaul Duriin autonomy console

This commit is contained in:
ImBenji
2026-08-04 21:05:47 +01:00
parent 0724f5dc36
commit 5037e1e192
10 changed files with 793 additions and 374 deletions
+67
View File
@@ -34,6 +34,72 @@ function escapeHtml(s) {
}
function formatNumber(value, compact = false) {
const number = Number(value || 0);
return new Intl.NumberFormat("en-GB", compact ? { notation: "compact", maximumFractionDigits: 1 } : {}).format(number);
}
function formatPercent(value, digits = 1) {
if (value == null || !Number.isFinite(Number(value))) return "—";
return `${(Number(value) * 100).toFixed(digits)}%`;
}
function formatRelative(value) {
if (!value) return "—";
const timestamp = new Date(value.endsWith && value.endsWith("Z") ? value : `${value}Z`).getTime();
if (!Number.isFinite(timestamp)) return value;
const seconds = Math.round((timestamp - Date.now()) / 1000);
const units = [[86400, "day"], [3600, "hour"], [60, "minute"]];
const formatter = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
for (const [size, name] of units) {
if (Math.abs(seconds) >= size) return formatter.format(Math.round(seconds / size), name);
}
return "just now";
}
function installChrome() {
const header = document.querySelector("header.app-header");
if (!header) return;
const title = header.querySelector("h1");
if (title) title.innerHTML = `<span class="brand-mark">D</span><span class="brand-copy">Duriin<span>Autonomous intelligence</span></span>`;
const nav = header.querySelector(".tabs");
if (nav && !nav.querySelector('[href="/admin/autonomy"]')) {
nav.insertAdjacentHTML("afterbegin", '<a href="/admin/autonomy">Autonomy</a>');
}
if (nav) {
const path = location.pathname;
nav.querySelectorAll("a").forEach(link => {
const href = link.getAttribute("href");
const active = href === "/admin/autonomy"
? path === href
: href === "/admin/ingest"
? path.startsWith("/admin/ingest")
: href === "/admin/intelligence"
? path.startsWith("/admin/intelligence")
: path === href;
link.classList.toggle("active", active);
});
}
const status = document.createElement("div");
status.className = "rail-status";
status.innerHTML = `<div class="rail-status-label"><span class="rail-status-dot"></span><span id="rail-mode">Connecting</span></div><div class="rail-status-meta" id="rail-meta">Runtime status</div>`;
header.appendChild(status);
api("/admin/api/autonomy/overview").then(data => {
const mode = String(data.mode || "offline").toUpperCase();
document.getElementById("rail-mode").textContent = data.enabled ? `${mode} runtime` : "Runtime unavailable";
document.getElementById("rail-meta").textContent = data.broker?.configured ? `${data.broker.name} · connected` : "Broker not configured";
document.querySelector(".rail-status-dot")?.classList.toggle("live", data.enabled);
}).catch(() => {
document.getElementById("rail-mode").textContent = "Runtime unavailable";
});
}
// ── url query-param helpers ────────────────────────────────────────────────
//
// filters and sort state live in the url so reloads and shared links keep
@@ -106,6 +172,7 @@ function wireOverlays() {
document.addEventListener("DOMContentLoaded", () => {
installChrome();
wireOverlays();
loadGlobalStats();
});