woz-vault / app.js
SNAPKITTYWEST's picture
push from SNAPKITTYWEST/woz-vault
8fa497d verified
Raw
History Blame Contribute Delete
13.1 kB
"use strict";
(() => {
const config = window.__WOZ_CONFIG__ || {};
const API_BASE = String(config.OS_URL || "").replace(/\/$/, "");
const state = {
health: null,
knownEntries: new Set(),
entrySeq: 0,
soundEnabled: false,
audioContext: null,
};
const $ = (id) => document.getElementById(id);
const el = {
agentOrb: $("agent-orb"),
agentName: $("agent-name"),
agentState: $("agent-state"),
agentUptime: $("agent-uptime"),
agentLatency: $("agent-latency"),
agentNode: $("agent-node"),
agentVersion: $("agent-version"),
agentIntegrity: $("agent-integrity"),
chainTerminal: $("chain-terminal"),
chainStatus: $("chain-status"),
chainTip: $("chain-tip"),
streamDot: $("stream-dot"),
immutableState: $("immutable-state"),
entryCount: $("entry-count"),
raceList: $("race-list"),
raceSource: $("race-source"),
vectorHealth: $("vector-health"),
vectorRate: $("vector-rate"),
vectorLastSeal: $("vector-last-seal"),
vectorApi: $("vector-api"),
soundToggle: $("sound-toggle"),
cmdHistory: $("command-history"),
magmaInput: $("magma-input"),
footerSession: $("footer-session"),
utcDate: $("utc-date"),
utcClock: $("utc-clock"),
};
function api(path) { return `${API_BASE}${path}`; }
async function request(path, options = {}, timeout = 8000) {
const ctrl = new AbortController();
const timer = setTimeout(() => ctrl.abort(), timeout);
try {
const res = await fetch(api(path), {
...options,
signal: ctrl.signal,
headers: {
Accept: "application/json",
...(options.body ? { "Content-Type": "application/json" } : {}),
...options.headers,
},
});
const body = await res.json().catch(() => ({}));
if (!res.ok) throw new Error(body.message || body.error || `HTTP ${res.status}`);
return body;
} finally { clearTimeout(timer); }
}
function pick(obj, paths, fallback) {
for (const p of paths) {
const v = p.split(".").reduce((o, k) => o?.[k], obj);
if (v !== undefined && v !== null) return v;
}
return fallback;
}
function formatUptime(v) {
if (typeof v === "string") return v;
const s = Math.max(0, v > 1_000_000 ? Math.floor(v / 1000) : Math.floor(Number(v || 0)));
const h = String(Math.floor(s / 3600)).padStart(2, "0");
const m = String(Math.floor((s % 3600) / 60)).padStart(2, "0");
const r = String(s % 60).padStart(2, "0");
return `${h}:${m}:${r}`;
}
function normalizeHealth(payload, latency) {
const src = payload.data || payload;
const status = String(pick(src, ["status", "health", "state"], "online")).toLowerCase();
const online = !["offline", "down", "error", "failed", "unhealthy"].includes(status);
return {
online,
status: online ? status.toUpperCase() : "OFFLINE",
name: String(pick(src, ["agent.name", "agentName", "name"], "CIPHER")),
uptime: formatUptime(pick(src, ["uptime", "system.uptime", "agent.uptime"], 0)),
latency,
node: String(pick(src, ["node", "nodeId", "instance", "agent.node"], "OS-01")),
version: String(pick(src, ["version", "build.version", "agent.version"], "v2.2.0")),
integrity: String(pick(src, ["integrity", "worm.integrity", "chain.integrity"], online ? "VERIFIED" : "UNVERIFIED")),
agents: normalizeAgents(pick(src, ["agents", "race", "agentRace", "metrics.agents"], [])),
};
}
function normalizeAgents(raw) {
if (!Array.isArray(raw) || raw.length === 0) return [];
return raw.map(a => ({
name: String(a.name || a.agent || a.key || "AGENT").toUpperCase(),
score: Math.min(100, Math.max(0, Number(a.score ?? a.value ?? a.decisions ?? 0))),
}));
}
// ── Clock ──────────────────────────────────────────────────────────────────
function tickClock() {
const now = new Date();
if (el.utcDate) el.utcDate.textContent = now.toISOString().slice(0, 10);
if (el.utcClock) el.utcClock.textContent = now.toUTCString().slice(17, 25) + " UTC";
}
tickClock();
setInterval(tickClock, 1000);
// ── Health polling ─────────────────────────────────────────────────────────
async function pollHealth() {
const t0 = performance.now();
try {
const raw = await request("/api/health");
const latency = Math.round(performance.now() - t0);
const h = normalizeHealth(raw, latency);
applyHealth(h);
} catch {
applyHealth({ online: false, status: "OFFLINE", latency: "β€”", uptime: "--:--:--",
node: "β€”", version: "β€”", integrity: "UNREACHABLE", agents: [] });
}
}
function applyHealth(h) {
state.health = h;
if (el.agentOrb) {
el.agentOrb.className = `agent-orb ${h.online ? "online" : "offline"}`;
}
if (el.agentName) el.agentName.textContent = h.name;
if (el.agentState) {
el.agentState.textContent = h.status;
el.agentState.className = `state ${h.online ? "online" : "offline"}`;
}
if (el.agentUptime) el.agentUptime.textContent = h.uptime;
if (el.agentLatency) el.agentLatency.textContent = typeof h.latency === "number" ? `${h.latency} MS` : String(h.latency);
if (el.agentNode) el.agentNode.textContent = h.node;
if (el.agentVersion) el.agentVersion.textContent = h.version;
if (el.agentIntegrity) el.agentIntegrity.textContent = h.integrity;
// System vector
if (el.vectorHealth) el.vectorHealth.textContent = h.online ? "NOMINAL" : "DEGRADED";
if (el.vectorApi) el.vectorApi.textContent = h.online ? "ONLINE" : "OFFLINE";
// Agent race
if (h.agents.length > 0) renderRace(h.agents);
}
pollHealth();
setInterval(pollHealth, 3000);
// ── WORM chain polling ─────────────────────────────────────────────────────
let chainPollRate = 0;
async function pollChain() {
const candidates = ["/api/worm/entries", "/api/agents/history", "/api/worm/tail"];
let data = null;
for (const path of candidates) {
try { data = await request(path, {}, 5000); if (data) break; } catch {}
}
if (!data) return;
const entries = Array.isArray(data) ? data : (data.entries ?? data.results ?? []);
chainPollRate++;
if (el.streamDot) el.streamDot.className = "stream-dot live";
if (el.chainStatus) el.chainStatus.textContent = "STREAMING";
let added = 0;
for (const entry of entries.slice(-20)) {
const id = entry.id ?? entry.worm_entry_id ?? entry.decision_seal ?? JSON.stringify(entry).slice(0, 32);
if (state.knownEntries.has(id)) continue;
state.knownEntries.add(id);
state.entrySeq++;
appendChainLine(entry, id);
added++;
}
if (added > 0) {
beep(880, 0.05);
const tip = entries.at(-1);
const hash = tip?.seal ?? tip?.decision_seal ?? tip?.worm_entry_id ?? "β€”";
if (el.chainTip) el.chainTip.textContent = String(hash).slice(0, 16);
if (el.entryCount) el.entryCount.textContent = String(state.knownEntries.size);
if (el.immutableState) el.immutableState.textContent = "CONFIRMED";
if (el.vectorLastSeal) el.vectorLastSeal.textContent = String(hash).slice(0, 12) + "…";
}
const evPerMin = Math.round(chainPollRate * 2);
if (el.vectorRate) el.vectorRate.textContent = `${evPerMin}/MIN`;
}
function appendChainLine(entry, id) {
const seq = String(state.entrySeq).padStart(4, "0");
const ts = (entry.created_at ?? entry.timestamp ?? entry.ts ?? new Date().toISOString()).slice(11, 23);
const actor = entry.agent ?? entry.actor ?? entry.source ?? "SYSTEM";
const evt = entry.event_type ?? entry.decision ?? entry.type ?? "SEAL";
const hash = (entry.seal ?? entry.decision_seal ?? id ?? "").slice(0, 12);
const line = document.createElement("div");
line.className = "chain-line new-entry";
line.innerHTML = `
<span class="seq">${seq}</span>
<span class="ts">${ts}</span>
<span class="event">${actor}Β·${evt}</span>
<span class="hash">${hash}…</span>
`;
if (el.chainTerminal) {
const boot = el.chainTerminal.querySelector(".boot-line");
if (boot) boot.remove();
el.chainTerminal.appendChild(line);
el.chainTerminal.scrollTop = el.chainTerminal.scrollHeight;
}
if (state.soundEnabled) beep(440 + (state.entrySeq % 8) * 55, 0.04);
}
pollChain();
setInterval(pollChain, 5000);
// ── Agent race ─────────────────────────────────────────────────────────────
const STATIC_AGENTS = ["CIPHER","VAULT","SENTINEL","ATLAS","ORACLE","FORGE","NOVA","LOC"];
function renderRace(agents) {
if (!el.raceList) return;
const list = agents.length > 0 ? agents : STATIC_AGENTS.map((n, i) => ({ name: n, score: Math.floor(Math.random() * 60 + 20) }));
el.raceList.innerHTML = list.map(a => `
<div class="race-row">
<span class="race-name">${a.name}</span>
<div class="race-track"><div class="race-fill" style="width:${a.score}%"></div></div>
<span class="race-score">${a.score}</span>
</div>
`).join("");
if (el.raceSource) el.raceSource.textContent = agents.length > 0 ? "SOURCE: HEALTH API" : "SOURCE: STATIC";
}
renderRace([]);
// ── Sound ──────────────────────────────────────────────────────────────────
function beep(freq = 440, gain = 0.1) {
if (!state.soundEnabled) return;
try {
state.audioContext = state.audioContext ?? new AudioContext();
const o = state.audioContext.createOscillator();
const g = state.audioContext.createGain();
o.type = "square";
o.frequency.value = freq;
g.gain.value = gain;
o.connect(g);
g.connect(state.audioContext.destination);
o.start();
g.gain.exponentialRampToValueAtTime(0.001, state.audioContext.currentTime + 0.08);
o.stop(state.audioContext.currentTime + 0.08);
} catch {}
}
if (el.soundToggle) {
el.soundToggle.addEventListener("click", () => {
state.soundEnabled = !state.soundEnabled;
el.soundToggle.textContent = `[ SOUND: ${state.soundEnabled ? "ON " : "OFF"} ]`;
el.soundToggle.ariaPressed = String(state.soundEnabled);
if (state.soundEnabled) beep(660, 0.15);
});
}
// ── Magma command line ─────────────────────────────────────────────────────
function appendHistory(line, cls = "muted") {
if (!el.cmdHistory) return;
const span = document.createElement("div");
span.style.color = cls === "ok" ? "var(--green)" : cls === "err" ? "var(--danger)" : "var(--muted)";
span.textContent = line;
el.cmdHistory.appendChild(span);
el.cmdHistory.scrollTop = el.cmdHistory.scrollHeight;
}
async function sendMagma() {
if (!el.magmaInput) return;
const cmd = el.magmaInput.value.trim();
if (!cmd) return;
el.magmaInput.value = "";
appendHistory(`> ${cmd}`);
try {
const res = await request("/api/agents/ask", {
method: "POST",
body: JSON.stringify({ message: cmd, agent: "forge" }),
}, 15000);
const reply = res.reply ?? res.message ?? res.text ?? JSON.stringify(res);
appendHistory(reply, "ok");
beep(660, 0.1);
} catch (err) {
appendHistory(`ERR: ${err.message}`, "err");
}
}
window.__wozSend = sendMagma;
if (el.magmaInput) {
el.magmaInput.addEventListener("keydown", e => {
if (e.key === "Enter") { e.preventDefault(); sendMagma(); }
});
}
// ── Footer session ─────────────────────────────────────────────────────────
if (el.footerSession) {
const id = Math.random().toString(36).slice(2, 10).toUpperCase();
el.footerSession.textContent = `SESSION: ${id}`;
}
})();