NishithP2004's picture
Upload folder using huggingface_hub
33dd31d verified
/**
* NeuroCaster web UI — telemetry polling, fixed-size Chart.js panels, training + chat.
* Chart height is locked in CSS (.chart-surface); options use maintainAspectRatio: false.
*/
const CONFIG = {
telemetryUrl: "/api/telemetry?n=100",
trainStatusUrl: "/api/train/status",
trainStreamUrl: "/api/training/stream",
maxSeriesPoints: 60,
maxLogLines: 500,
pollFastMs: 2000,
pollIdleMs: 8000,
pollBackgroundMs: 20000,
};
const el = {
tabTraining: document.querySelector("#tab-training"),
tabStageTester: document.querySelector("#tab-stage-tester"),
workspaceTraining: document.querySelector("#workspace-training"),
workspaceStageTester: document.querySelector("#workspace-stage-tester"),
trainForm: document.querySelector("#train-form"),
trainButton: document.querySelector("#start-training"),
trainStatus: document.querySelector("#train-status"),
modelName: document.querySelector("#model-name"),
maxEpisodes: document.querySelector("#max-episodes"),
metricEpisode: document.querySelector("#metric-episode"),
metricReward: document.querySelector("#metric-reward"),
metricCognitiveLoad: document.querySelector("#metric-cognitive-load"),
brainSts: document.querySelector("#brain-sts"),
brainTpj: document.querySelector("#brain-tpj"),
brainBroca: document.querySelector("#brain-broca"),
meterSts: document.querySelector("#meter-sts"),
meterTpj: document.querySelector("#meter-tpj"),
meterBroca: document.querySelector("#meter-broca"),
chatForm: document.querySelector("#chat-form"),
chatInput: document.querySelector("#chat-input"),
chatScore: document.querySelector("#chat-score"),
chatResponse: document.querySelector("#chat-response"),
trainLog: document.querySelector("#train-log"),
testerReset: document.querySelector("#tester-reset"),
testerRunAuto: document.querySelector("#tester-run-auto"),
testerDownloadTrace: document.querySelector("#tester-download-trace"),
testerForm: document.querySelector("#tester-form"),
testerStage: document.querySelector("#tester-stage"),
testerActionJson: document.querySelector("#tester-action-json"),
testerLoadTemplate: document.querySelector("#tester-load-template"),
testerAutoPrompt: document.querySelector("#tester-auto-prompt"),
testerSummary: document.querySelector("#tester-summary"),
testerResponse: document.querySelector("#tester-response"),
};
const pointLabelEls = document.querySelectorAll("[data-chart-points]");
function setChartPointLabels() {
const n = String(CONFIG.maxSeriesPoints);
pointLabelEls.forEach((node) => {
node.textContent = n;
});
}
Chart.defaults.color = "rgba(248, 251, 255, 0.78)";
Chart.defaults.borderColor = "rgba(255, 255, 255, 0.09)";
Chart.defaults.font.family = "Inter, system-ui, sans-serif";
function baseChartOptions(yTitle) {
return {
responsive: true,
maintainAspectRatio: false,
animation: false,
interaction: { intersect: false, mode: "index" },
resizeDelay: 0,
layout: {
padding: { top: 6, right: 8, bottom: 4, left: 4 },
},
elements: {
point: { radius: 0, hoverRadius: 4 },
line: { borderWidth: 2, tension: 0.25 },
},
plugins: {
legend: {
display: true,
position: "top",
align: "end",
labels: { boxWidth: 10, usePointStyle: true, padding: 8, font: { size: 10 } },
},
tooltip: {
enabled: true,
intersect: false,
},
},
scales: {
x: {
display: true,
title: { display: true, text: "Episode", font: { size: 11 } },
grid: { color: "rgba(255, 255, 255, 0.04)" },
ticks: { maxRotation: 0, autoSkip: true, maxTicksLimit: 8, font: { size: 10 } },
},
y: {
display: true,
title: { display: true, text: yTitle, font: { size: 11 } },
grid: { color: "rgba(255, 255, 255, 0.04)" },
ticks: { font: { size: 10 } },
},
},
};
}
function datasetLine(label, color, fill) {
return {
label,
data: [],
borderColor: color,
backgroundColor: fill ? `${color}22` : "transparent",
fill: Boolean(fill),
pointRadius: 0,
};
}
const rewardChart = new Chart(document.getElementById("reward-chart"), {
type: "line",
data: {
labels: [],
datasets: [datasetLine("Total reward", "#12c2e9", true)],
},
options: baseChartOptions("Reward"),
});
const brainChart = new Chart(document.getElementById("brain-chart"), {
type: "line",
data: {
labels: [],
datasets: [
datasetLine("STS", "#12c2e9", false),
datasetLine("TPJ", "#c471ed", false),
datasetLine("Broca", "#f64f59", false),
],
},
options: baseChartOptions("Z-score"),
});
function formatNumber(value) {
const n = Number(value);
return Number.isFinite(n) ? n.toFixed(3) : "0.000";
}
function metric(row, ...keys) {
for (const key of keys) {
const v = row?.[key];
if (v !== undefined && v !== null && v !== "") {
const n = Number(v);
return Number.isFinite(n) ? n : 0;
}
}
return 0;
}
function updateMeter(node, value) {
const n = Math.max(0, Math.min(100, 50 + Number(value || 0) * 18));
node.style.width = `${n}%`;
}
const series = {
lastEpisode: 0,
labels: [],
rewards: [],
sts: [],
tpj: [],
broca: [],
};
let lastHash = "";
let pollTimer = null;
let pollIntervalMs = CONFIG.pollIdleMs;
let fetchLock = false;
let trainingRunning = false;
let trainingStream = null;
const logLines = [];
let testerLastReset = null;
let testerTrace = [];
function appendTrainingLog(line) {
const text = String(line || "").trim();
if (!text) {
return;
}
logLines.push(text);
while (logLines.length > CONFIG.maxLogLines) {
logLines.shift();
}
if (el.trainLog) {
el.trainLog.textContent = logLines.join("\n");
el.trainLog.scrollTop = el.trainLog.scrollHeight;
}
}
function disconnectTrainingStream() {
if (trainingStream) {
trainingStream.close();
trainingStream = null;
}
}
function connectTrainingStream(force = false) {
if (!window.EventSource) {
return;
}
if (trainingStream && !force) {
return;
}
disconnectTrainingStream();
try {
trainingStream = new EventSource(CONFIG.trainStreamUrl);
} catch (_) {
trainingStream = null;
return;
}
trainingStream.addEventListener("log", (event) => {
try {
const payload = JSON.parse(event.data || "{}");
appendTrainingLog(payload.line || "");
} catch (_) {
appendTrainingLog(event.data || "");
}
});
trainingStream.addEventListener("status", (event) => {
try {
const payload = JSON.parse(event.data || "{}");
const was = trainingRunning;
trainingRunning = Boolean(payload.running);
if (was && !trainingRunning) {
if (payload.status === "failed") {
el.trainStatus.textContent = `Training failed (exit ${payload.exit_code ?? "?"}). Live logs shown below.`;
} else {
el.trainStatus.textContent = "Training finished. You can use the playground.";
}
}
} catch (_) {
// no-op
}
});
trainingStream.addEventListener("end", (event) => {
try {
const payload = JSON.parse(event.data || "{}");
if (payload.status === "failed") {
el.trainStatus.textContent = `Training failed (exit ${payload.exit_code ?? "?"}). Live logs shown below.`;
}
} catch (_) {
// no-op
}
disconnectTrainingStream();
});
trainingStream.onerror = () => {
// Stream may be disabled by config or temporarily unavailable.
disconnectTrainingStream();
};
}
function setupTabs() {
if (!el.tabTraining || !el.tabStageTester) {
return;
}
const activate = (target) => {
const trainingActive = target === "training";
el.tabTraining.classList.toggle("is-active", trainingActive);
el.tabStageTester.classList.toggle("is-active", !trainingActive);
el.tabTraining.setAttribute("aria-selected", trainingActive ? "true" : "false");
el.tabStageTester.setAttribute("aria-selected", !trainingActive ? "true" : "false");
if (el.workspaceTraining) {
el.workspaceTraining.hidden = !trainingActive;
}
if (el.workspaceStageTester) {
el.workspaceStageTester.hidden = trainingActive;
}
};
el.tabTraining.addEventListener("click", () => activate("training"));
el.tabStageTester.addEventListener("click", () => activate("stage_tester"));
activate("training");
}
function prettyJson(value) {
return JSON.stringify(value, null, 2);
}
function stageTemplate(stage) {
if (stage === "investigator") {
return {
metadata: { done_investigating: true },
};
}
if (stage === "drafter") {
const audioAnchor =
testerLastReset?.observation?.task?.audio_anchor ||
"/app/shared_data/audio/voices/reference.wav";
return {
slide_markdown: `---
title: Stage Tester
audio: ${audioAnchor}
---
# Architecture Snapshot
<!-- narration: This stage tester slide checks verifier and TRIBE paths. -->
\`\`\`mermaid
flowchart TD
user[User] --> service[Service]
\`\`\`
`,
};
}
return {};
}
async function testerResetEpisode() {
const response = await fetch("/reset", { method: "POST" });
const payload = await response.json();
testerTrace = [];
testerTrace.push({
timestamp: new Date().toISOString(),
step: "reset",
payload,
});
testerLastReset = payload;
if (el.testerSummary) {
const obs = payload?.observation || {};
el.testerSummary.textContent = `Reset ok. Next stage: ${obs.stage || "unknown"}, task: ${obs.task?.task_id || "n/a"}`;
}
if (el.testerResponse) {
el.testerResponse.textContent = prettyJson(payload);
}
return payload;
}
async function testerRunStep(stage, actionBody) {
const response = await fetch("/step", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ stage, ...actionBody }),
});
const payload = await response.json();
if (el.testerSummary) {
const obs = payload?.observation || {};
el.testerSummary.textContent =
`Step ${stage} => next ${obs.stage || "unknown"}, reward ${Number(payload?.reward ?? 0).toFixed(3)}, done ${Boolean(payload?.done)}`;
}
if (el.testerResponse) {
el.testerResponse.textContent = prettyJson(payload);
}
testerTrace.push({
timestamp: new Date().toISOString(),
step: stage,
action: { stage, ...actionBody },
payload,
});
return payload;
}
function setTesterSummary(message) {
if (el.testerSummary) {
el.testerSummary.textContent = message;
}
}
function setTesterResponseSections(sections) {
if (!el.testerResponse) {
return;
}
const text = sections
.map((section) => `=== ${section.title} ===\n${prettyJson(section.payload)}`)
.join("\n\n");
el.testerResponse.textContent = text;
}
async function generateAutomatedDraft(prompt) {
const response = await fetch("/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ prompt }),
});
const payload = await response.json();
if (!response.ok) {
throw new Error(payload.detail || "Automated draft generation failed");
}
testerTrace.push({
timestamp: new Date().toISOString(),
step: "llm_draft_generation",
request: { prompt },
payload,
});
return payload;
}
async function runAutomatedEpisode() {
const sections = [];
setTesterSummary("Automated episode: reset...");
const resetPayload = await testerResetEpisode();
sections.push({ title: "reset", payload: resetPayload });
const task = resetPayload?.observation?.task || {};
setTesterSummary("Automated episode: investigator...");
const investigatorPayload = await testerRunStep("investigator", {
repo_path: task.repo_path || "",
query: task.query || "",
metadata: { done_investigating: true },
});
sections.push({ title: "investigator", payload: investigatorPayload });
const promptOverride = (el.testerAutoPrompt?.value || "").trim();
const llmPrompt = promptOverride || String(task.query || "Explain this repository architecture.");
setTesterSummary("Automated episode: generating drafter markdown with model...");
const draftGeneration = await generateAutomatedDraft(llmPrompt);
sections.push({ title: "llm_draft_generation", payload: draftGeneration });
setTesterSummary("Automated episode: drafter...");
const drafterPayload = await testerRunStep("drafter", {
slide_markdown: String(draftGeneration.markdown || ""),
});
sections.push({ title: "drafter", payload: drafterPayload });
setTesterSummary("Automated episode: verifier_bio...");
const verifierPayload = await testerRunStep("verifier_bio", {});
sections.push({ title: "verifier_bio", payload: verifierPayload });
const finalDone = Boolean(verifierPayload?.done);
const finalReward = Number(verifierPayload?.reward ?? 0).toFixed(3);
setTesterSummary(`Automated episode complete: done=${finalDone}, reward=${finalReward}`);
setTesterResponseSections(sections);
}
function setupStageTester() {
if (!el.testerReset || !el.testerForm || !el.testerStage || !el.testerActionJson) {
return;
}
el.testerReset.addEventListener("click", async () => {
el.testerReset.disabled = true;
try {
await testerResetEpisode();
} catch (error) {
if (el.testerSummary) {
el.testerSummary.textContent = `Reset failed: ${error.message}`;
}
} finally {
el.testerReset.disabled = false;
}
});
el.testerLoadTemplate?.addEventListener("click", () => {
const stage = el.testerStage.value;
el.testerActionJson.value = prettyJson(stageTemplate(stage));
});
el.testerForm.addEventListener("submit", async (event) => {
event.preventDefault();
const stage = el.testerStage.value;
let parsed = {};
try {
parsed = JSON.parse(el.testerActionJson.value || "{}");
} catch (error) {
if (el.testerSummary) {
el.testerSummary.textContent = `Invalid JSON: ${error.message}`;
}
return;
}
const runButton = el.testerForm.querySelector("button[type='submit']");
if (runButton) {
runButton.disabled = true;
}
try {
await testerRunStep(stage, parsed);
} catch (error) {
if (el.testerSummary) {
el.testerSummary.textContent = `Step failed: ${error.message}`;
}
} finally {
if (runButton) {
runButton.disabled = false;
}
}
});
el.testerRunAuto?.addEventListener("click", async () => {
const autoBtn = el.testerRunAuto;
autoBtn.disabled = true;
try {
await runAutomatedEpisode();
} catch (error) {
setTesterSummary(`Automated run failed: ${error.message}`);
} finally {
autoBtn.disabled = false;
}
});
el.testerDownloadTrace?.addEventListener("click", () => {
if (!testerTrace.length) {
setTesterSummary("No trace available yet. Run reset/steps first.");
return;
}
const episodeId = testerTrace[0]?.payload?.observation?.episode_id || `episode-${Date.now()}`;
const filename = `${String(episodeId).replace(/[^a-zA-Z0-9-_]/g, "_")}-trace.json`;
const blob = new Blob([prettyJson(testerTrace)], { type: "application/json" });
const url = URL.createObjectURL(blob);
const anchor = document.createElement("a");
anchor.href = url;
anchor.download = filename;
document.body.appendChild(anchor);
anchor.click();
anchor.remove();
URL.revokeObjectURL(url);
setTesterSummary(`Trace exported: ${filename}`);
});
}
function resetSeries() {
series.lastEpisode = 0;
series.labels.length = 0;
series.rewards.length = 0;
series.sts.length = 0;
series.tpj.length = 0;
series.broca.length = 0;
}
function trimSeries() {
while (series.labels.length > CONFIG.maxSeriesPoints) {
series.labels.shift();
series.rewards.shift();
series.sts.shift();
series.tpj.shift();
series.broca.shift();
}
}
function applySeriesToCharts() {
const r = rewardChart;
const b = brainChart;
r.data.labels = series.labels;
r.data.datasets[0].data = series.rewards;
b.data.labels = series.labels;
b.data.datasets[0].data = series.sts;
b.data.datasets[1].data = series.tpj;
b.data.datasets[2].data = series.broca;
r.update("none");
b.update("none");
}
function ingestRows(rows) {
const cap = CONFIG.maxSeriesPoints;
const slice = rows.length > cap ? rows.slice(-cap) : rows;
const latest = slice.at(-1);
if (!latest) {
return;
}
const latestEp = Number(latest.episode || 0);
if (latestEp > 0 && latestEp < series.lastEpisode) {
resetSeries();
}
const reward = metric(latest, "total_reward", "cumulative_reward", "reward");
const h = `${latestEp}-${reward}`;
if (h === lastHash) {
return;
}
lastHash = h;
for (const row of slice) {
let ep = Number(row.episode || 0);
if (!Number.isFinite(ep) || ep <= 0) {
ep = series.lastEpisode + 1;
}
if (ep <= series.lastEpisode) {
continue;
}
series.lastEpisode = ep;
series.labels.push(ep);
series.rewards.push(metric(row, "total_reward", "cumulative_reward", "reward"));
series.sts.push(metric(row, "STS_Z_Score", "Z_STS"));
series.tpj.push(metric(row, "TPJ_Z_Score", "Z_TPJ"));
series.broca.push(metric(row, "Broca_Z_Score", "Z_Broca", "cognitive_load"));
}
trimSeries();
applySeriesToCharts();
const s = metric(latest, "STS_Z_Score", "Z_STS");
const t = metric(latest, "TPJ_Z_Score", "Z_TPJ");
const b = metric(latest, "Broca_Z_Score", "Z_Broca", "cognitive_load");
el.metricEpisode.textContent = String(latest.episode ?? rows.length);
el.metricReward.textContent = formatNumber(reward);
el.metricCognitiveLoad.textContent = formatNumber(b);
el.brainSts.textContent = formatNumber(s);
el.brainTpj.textContent = formatNumber(t);
el.brainBroca.textContent = formatNumber(b);
updateMeter(el.meterSts, s);
updateMeter(el.meterTpj, t);
updateMeter(el.meterBroca, b);
}
async function getTelemetry() {
const res = await fetch(CONFIG.telemetryUrl, { cache: "no-store" });
if (!res.ok) {
throw new Error(`HTTP ${res.status}`);
}
const data = await res.json();
if (!Array.isArray(data)) {
return;
}
ingestRows(data);
}
async function getTrainStatus() {
const res = await fetch(CONFIG.trainStatusUrl, { cache: "no-store" });
if (!res.ok) {
return;
}
const json = await res.json();
const was = trainingRunning;
trainingRunning = Boolean(json.running);
if (was && !trainingRunning) {
if (json.status === "failed") {
el.trainStatus.textContent = `Training failed (exit ${json.exit_code ?? "?"}). Live logs shown below.`;
} else {
el.trainStatus.textContent = "Training finished. You can use the playground.";
}
} else if (!was && trainingRunning) {
el.trainStatus.textContent = `Training (pid ${json.pid}) — streaming telemetry.`;
}
}
function clearPoll() {
if (pollTimer !== null) {
clearTimeout(pollTimer);
pollTimer = null;
}
}
function schedulePoll(ms) {
clearPoll();
pollTimer = window.setTimeout(tick, ms);
}
async function tick() {
if (fetchLock) {
schedulePoll(pollIntervalMs);
return;
}
fetchLock = true;
try {
await getTrainStatus();
await getTelemetry();
} catch (e) {
el.trainStatus.textContent = `Telemetry error: ${e.message}`;
} finally {
fetchLock = false;
if (document.hidden) {
pollIntervalMs = CONFIG.pollBackgroundMs;
} else {
pollIntervalMs = trainingRunning ? CONFIG.pollFastMs : CONFIG.pollIdleMs;
}
schedulePoll(pollIntervalMs);
}
}
el.trainForm.addEventListener("submit", async (e) => {
e.preventDefault();
el.trainButton.disabled = true;
el.trainStatus.textContent = "Starting training…";
try {
const res = await fetch("/api/train", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model_name: el.modelName.value.trim(),
max_episodes: Number(el.maxEpisodes.value || 1),
}),
});
const json = await res.json();
if (!res.ok || json.ok === false) {
throw new Error(json.detail || json.status || "Could not start training");
}
el.trainStatus.textContent = `Started (pid ${json.pid}).`;
trainingRunning = true;
logLines.length = 0;
appendTrainingLog(`[neurocaster] training started (pid ${json.pid})`);
connectTrainingStream(true);
pollIntervalMs = CONFIG.pollFastMs;
await getTelemetry();
schedulePoll(0);
} catch (err) {
el.trainStatus.textContent = `Error: ${err.message}`;
} finally {
el.trainButton.disabled = false;
}
});
el.chatForm.addEventListener("submit", async (e) => {
e.preventDefault();
const prompt = el.chatInput.value.trim();
if (!prompt) {
return;
}
const btn = el.chatForm.querySelector("button");
btn.disabled = true;
el.chatScore.textContent = "Generating…";
el.chatResponse.innerHTML = "";
try {
const res = await fetch("/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ prompt }),
});
const json = await res.json();
if (!res.ok) {
throw new Error(json.detail || "Request failed");
}
const md = json.markdown || "";
if (window.marked && typeof window.marked.parse === "function") {
el.chatResponse.innerHTML = window.marked.parse(md);
} else {
el.chatResponse.textContent = md;
}
const m = json.metrics || {};
el.chatScore.textContent =
`TRIBE-v2: ${formatNumber(json.biological_reward)} ` +
`(STS ${formatNumber(m.STS_Z_Score)}, TPJ ${formatNumber(m.TPJ_Z_Score)}, Broca ${formatNumber(m.Broca_Z_Score)})`;
} catch (err) {
el.chatScore.textContent = `Error: ${err.message}`;
} finally {
btn.disabled = false;
}
});
document.addEventListener("visibilitychange", () => {
pollIntervalMs = document.hidden
? CONFIG.pollBackgroundMs
: trainingRunning
? CONFIG.pollFastMs
: CONFIG.pollIdleMs;
schedulePoll(0);
});
/* One layout sync after fonts — avoids a single mis-sized first frame */
window.addEventListener("load", () => {
rewardChart.resize();
brainChart.resize();
});
window.addEventListener("beforeunload", () => {
clearPoll();
disconnectTrainingStream();
rewardChart.destroy();
brainChart.destroy();
});
setChartPointLabels();
setupTabs();
setupStageTester();
connectTrainingStream();
schedulePoll(0);