Open raw ↗/* Reference client — plain JS, no frameworks, no secrets ever present here.
The API key lives only in the server's environment (GOV-B7.3). */
"use strict";
const $ = (id) => document.getElementById(id);
async function api(path, body) {
const res = await fetch(path, {
method: body === undefined ? "GET" : "POST",
headers: body === undefined ? {} : {"Content-Type": "application/json"},
body: body === undefined ? undefined : JSON.stringify(body),
credentials: "same-origin",
});
const data = await res.json().catch(() => ({}));
return {ok: res.ok, status: res.status, data};
}
function show(view) {
$("login-view").hidden = view !== "login";
$("chat-view").hidden = view !== "chat";
}
function bubble(kind, text) {
const li = document.createElement("li");
li.className = kind;
li.textContent = text; // textContent: engine output is data, never HTML (INV-6 spirit)
$("thread").appendChild(li);
$("thread").scrollTop = $("thread").scrollHeight;
}
async function boot() {
const {data} = await api("/api/whoami");
if (data && data.user) {
if (data.engine) $("engine-badge").textContent = "engine: " + data.engine;
show("chat");
} else {
show("login");
}
}
$("login-form").addEventListener("submit", async (ev) => {
ev.preventDefault();
$("login-error").hidden = true;
const {ok, data} = await api("/api/login", {
username: $("username").value.trim(),
password: $("password").value,
});
if (ok) { location.reload(); }
else { $("login-error").textContent = "Sign-in failed."; $("login-error").hidden = false; }
});
$("logout").addEventListener("click", async () => { await api("/api/logout", {}); location.reload(); });
$("chat-form").addEventListener("submit", async (ev) => {
ev.preventDefault();
const text = $("message").value.trim();
if (!text) return;
$("chat-error").hidden = true;
bubble("me", text);
$("message").value = "";
const {ok, data} = await api("/api/chat", {message: text});
if (ok) bubble("engine", data.reply || "(empty reply)");
else { $("chat-error").textContent = "Engine error — see the server console."; $("chat-error").hidden = false; }
});
boot();