const DEBOUNCE_MS = 420;
const SILENCE_MS = 500;
const SILENCE_TOKEN = "<|silence|>";
const BOUNDARY_PATTERN = /[\s.,!?;:)\]}"]$/;
const MODE_BASELINE = "baseline";
const MODE_INTERACTIVE_BASE = "interactive-base";
const MODE_INTERACTIVE_RL = "interactive-rl";
const MODES = [MODE_BASELINE, MODE_INTERACTIVE_BASE, MODE_INTERACTIVE_RL];
const authView = document.querySelector("#authView");
const appView = document.querySelector("#appView");
const authForm = document.querySelector("#authForm");
const authError = document.querySelector("#authError");
const accessCode = document.querySelector("#accessCode");
const modeButtons = Array.from(document.querySelectorAll("[data-mode]"));
const historyView = document.querySelector("#history");
const composer = document.querySelector("#composer");
const typedText = document.querySelector("#typedText");
const predictedText = document.querySelector("#predictedText");
const thinking = document.querySelector("#thinking");
const assistantResponse = document.querySelector("#assistantResponse");
const latencyAverage = document.querySelector("#latencyAverage");
const accuracyAverage = document.querySelector("#accuracyAverage");
const callList = document.querySelector("#callList");
const clearCalls = document.querySelector("#clearCalls");
const pageTabs = Array.from(document.querySelectorAll("[data-tab]"));
const tabPanels = Array.from(document.querySelectorAll("[data-panel]"));
const state = {
mode: MODE_INTERACTIVE_RL,
activeTab: "overview",
history: [],
typed: "",
predictionAnchor: null,
predictionModelUserText: "",
predictedUserCompletion: "",
remainingUserCompletion: "",
assistantText: "",
errorText: "",
hasPrediction: false,
predictionComplete: false,
predictionTurnDone: false,
inFlight: false,
controller: null,
requestSeq: 0,
debounceTimer: null,
silenceTimer: null,
silenceAnchor: "",
silenceTokenCount: 0,
silenceStartedAt: null,
activeCallNode: null,
locked: false,
lockedSeq: null,
pendingCommitSeq: null,
pendingCommitText: "",
pendingCommitModelText: "",
pendingLatency: null,
latencyMeasurements: [],
measuredLatencySeqs: new Set(),
interactiveInferenceCount: 0,
predictionAccuracies: [],
};
async function boot() {
const response = await fetch("/api/session", { credentials: "same-origin" });
const session = await response.json();
if (session.authenticated) {
showApp();
} else {
authView.classList.remove("hidden");
}
}
authForm.addEventListener("submit", async (event) => {
event.preventDefault();
authError.textContent = "";
const response = await fetch("/api/auth", {
method: "POST",
credentials: "same-origin",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ code: accessCode.value }),
});
const payload = await response.json();
if (!response.ok) {
authError.textContent = payload.error || "Could not sign in.";
return;
}
accessCode.value = "";
showApp();
});
composer.addEventListener("keydown", (event) => {
if (event.key !== "Enter" || event.isComposing) {
return;
}
event.preventDefault();
void commitCurrentTurn("enter");
});
for (const button of modeButtons) {
button.addEventListener("click", () => {
setMode(button.dataset.mode);
});
}
for (const tab of pageTabs) {
tab.addEventListener("click", () => {
setActiveTab(tab.dataset.tab);
});
}
composer.addEventListener("input", () => {
if (state.locked) {
composer.value = state.typed;
return;
}
state.typed = composer.value;
resizeComposer();
if (state.mode === MODE_BASELINE) {
clearTimeout(state.debounceTimer);
state.debounceTimer = null;
stopSilenceLoop();
clearPredictionState();
render();
return;
}
const contradictedTurnDone =
state.hasPrediction &&
state.predictionAnchor !== null &&
normalizeInline(state.predictedUserCompletion) === "" &&
state.typed.startsWith(state.predictionAnchor) &&
state.typed.length > state.predictionAnchor.length;
if (reconcilePrediction()) {
if (state.predictionTurnDone) {
queueCommitFromPrediction("accepted", performance.now());
}
render();
return;
}
invalidatePrediction();
if (!state.typed.trim()) {
resetCurrentInteractiveMetrics();
stopSilenceLoop();
render();
return;
}
const immediate = contradictedTurnDone || BOUNDARY_PATTERN.test(state.typed);
if (immediate) {
startSilenceLoop(state.typed);
} else {
stopSilenceLoop();
}
scheduleInference(
contradictedTurnDone ? "continued" : immediate ? "boundary" : "pause",
immediate ? 0 : DEBOUNCE_MS,
);
render();
});
clearCalls.addEventListener("click", () => {
callList.replaceChildren();
});
function showApp() {
authView.classList.add("hidden");
appView.classList.remove("hidden");
setActiveTab(state.activeTab);
render();
}
function setActiveTab(tabName) {
if (!tabPanels.some((panel) => panel.dataset.panel === tabName)) {
return;
}
state.activeTab = tabName;
for (const tab of pageTabs) {
const active = tab.dataset.tab === tabName;
tab.classList.toggle("active", active);
tab.setAttribute("aria-selected", String(active));
}
for (const panel of tabPanels) {
panel.classList.toggle("hidden", panel.dataset.panel !== tabName);
}
if (tabName !== "demo") {
stopSilenceLoop();
}
if (tabName === "demo") {
composer.focus();
}
}
function setMode(mode) {
if (
state.locked ||
!MODES.includes(mode) ||
mode === state.mode
) {
return;
}
invalidatePrediction();
resetCurrentInteractiveMetrics();
stopSilenceLoop();
state.mode = mode;
state.typed = composer.value;
state.assistantText = "";
state.errorText = "";
render();
composer.focus();
if (isInteractiveMode(state.mode) && state.typed.trim()) {
if (BOUNDARY_PATTERN.test(state.typed)) {
startSilenceLoop(state.typed);
}
scheduleInference("mode", 0);
}
}
function reconcilePrediction() {
if (state.predictionAnchor === null || !state.hasPrediction) {
return false;
}
if (state.typed === state.predictionAnchor) {
state.remainingUserCompletion = state.predictedUserCompletion;
state.predictionTurnDone = normalizeInline(state.remainingUserCompletion) === "";
return true;
}
if (!state.typed.startsWith(state.predictionAnchor)) {
return false;
}
const consumed = state.typed.slice(state.predictionAnchor.length);
if (!state.predictedUserCompletion.startsWith(consumed)) {
return false;
}
state.remainingUserCompletion = state.predictedUserCompletion.slice(consumed.length);
state.predictionTurnDone = normalizeInline(state.remainingUserCompletion) === "";
return true;
}
function invalidatePrediction() {
state.requestSeq += 1;
if (state.controller) {
state.controller.abort();
markCall(state.activeCallNode, "canceled", "canceled");
}
clearTimeout(state.debounceTimer);
state.debounceTimer = null;
stopSilenceLoop();
state.inFlight = false;
state.controller = null;
state.activeCallNode = null;
state.predictionAnchor = null;
state.predictionModelUserText = "";
state.predictedUserCompletion = "";
state.remainingUserCompletion = "";
state.assistantText = "";
state.errorText = "";
state.hasPrediction = false;
state.predictionComplete = false;
state.predictionTurnDone = false;
state.pendingCommitSeq = null;
state.pendingCommitText = "";
state.pendingCommitModelText = "";
}
function scheduleInference(reason, delayMs) {
clearTimeout(state.debounceTimer);
state.debounceTimer = window.setTimeout(() => {
void runInference(reason);
}, delayMs);
}
function startSilenceLoop(anchorText, delayMs = SILENCE_MS) {
if (!isInteractiveMode(state.mode) || !anchorText.trim()) {
stopSilenceLoop();
return;
}
if (!BOUNDARY_PATTERN.test(anchorText)) {
stopSilenceLoop();
return;
}
if (state.silenceAnchor !== anchorText) {
state.silenceAnchor = anchorText;
state.silenceTokenCount = 0;
state.silenceStartedAt = performance.now();
}
clearTimeout(state.silenceTimer);
state.silenceTimer = window.setTimeout(() => {
if (
state.locked ||
!isInteractiveMode(state.mode) ||
composer.value !== state.silenceAnchor ||
!BOUNDARY_PATTERN.test(composer.value)
) {
stopSilenceLoop();
return;
}
if (state.inFlight) {
startSilenceLoop(state.silenceAnchor, 100);
return;
}
const elapsedSilenceMs = performance.now() - (state.silenceStartedAt ?? performance.now());
state.silenceTokenCount = Math.max(
state.silenceTokenCount + 1,
Math.floor(elapsedSilenceMs / SILENCE_MS),
);
void runInference(`silence x${state.silenceTokenCount}`, {
userText: state.silenceAnchor,
requestText: withSilenceTokens(
state.silenceAnchor,
state.silenceTokenCount,
),
});
startSilenceLoop(state.silenceAnchor);
}, delayMs);
}
function stopSilenceLoop() {
clearTimeout(state.silenceTimer);
state.silenceTimer = null;
state.silenceAnchor = "";
state.silenceTokenCount = 0;
state.silenceStartedAt = null;
}
function withSilenceTokens(text, count) {
if (count <= 0) {
return text;
}
return `${text}${" "}${Array(count).fill(SILENCE_TOKEN).join(" ")}`;
}
async function runInference(reason, options = {}) {
const mode = options.mode ?? state.mode;
const userText = options.userText ?? composer.value;
const requestText = options.requestText ?? userText;
const commitAfterResult = Boolean(options.commitAfterResult);
const lockDuringRequest = Boolean(options.lockDuringRequest);
const turnComplete = Boolean(options.turnComplete);
const latencyStartedAt = options.latencyStartedAt;
const latencySource = options.latencySource ?? reason;
if (!requestText.trim()) {
return null;
}
state.requestSeq += 1;
const seq = state.requestSeq;
if (state.controller) {
state.controller.abort();
markCall(state.activeCallNode, "canceled", "canceled");
}
const controller = new AbortController();
state.controller = controller;
state.inFlight = true;
if (isInteractiveMode(mode)) {
state.interactiveInferenceCount += 1;
}
state.activeCallNode = addCall({
seq,
reason: interactiveCallReason(mode, reason),
text: userText,
});
if (typeof latencyStartedAt === "number") {
beginLatencyMeasurement(seq, latencySource, latencyStartedAt);
}
if (lockDuringRequest) {
lockComposer(seq);
}
render();
let finalPrediction = null;
let committed = false;
try {
const response = await fetch("/api/predict", {
method: "POST",
credentials: "same-origin",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
typed: requestText,
history: state.history,
turn_complete: turnComplete,
model_variant: predictionVariantForMode(mode),
}),
signal: controller.signal,
});
if (response.status === 401) {
authView.classList.remove("hidden");
appView.classList.add("hidden");
return null;
}
if (!response.ok || !response.body) {
throw new Error(`Prediction failed with HTTP ${response.status}`);
}
await readEventStream(response.body, (event, data) => {
if (seq !== state.requestSeq) {
return;
}
if (event === "meta") {
updateCallMeta(state.activeCallNode, data);
}
if (event === "parsed" || event === "result") {
const eventTime = performance.now();
const applied = applyPrediction(userText, data, requestText);
if (event === "result") {
finalPrediction = data;
}
if (
applied &&
!commitAfterResult &&
data.user_completion_closed &&
state.predictionTurnDone
) {
queuePendingCommit(
seq,
composer.value,
"predicted",
eventTime,
requestText,
);
}
observeAssistantFirstToken(seq, eventTime);
}
if (event === "error") {
throw new Error(data.error || "Prediction failed.");
}
});
if (seq === state.requestSeq) {
markCall(state.activeCallNode, "done", "done");
}
if (seq === state.requestSeq && finalPrediction) {
const pendingText =
state.pendingCommitSeq === seq ? state.pendingCommitText : "";
const pendingModelText =
state.pendingCommitSeq === seq ? state.pendingCommitModelText : "";
const shouldCommit = commitAfterResult || Boolean(pendingText);
if (shouldCommit) {
committed = commitPrediction(
pendingText || userText,
finalPrediction,
pendingModelText || requestText,
);
}
}
return finalPrediction;
} catch (error) {
if (error.name === "AbortError") {
return null;
}
markCall(state.activeCallNode, "error", "error");
state.errorText = error.message || "Prediction failed.";
clearPendingLatency(seq);
return null;
} finally {
if (seq === state.requestSeq) {
state.inFlight = false;
state.controller = null;
state.activeCallNode = null;
if (!committed && state.lockedSeq === seq) {
unlockComposer(seq);
}
render();
}
}
}
function applyPrediction(anchor, parsed, modelUserText = anchor) {
const currentText = composer.value;
const predictedCompletion = removeEchoedUserPrefix(
currentText,
parsed.user_completion || "",
);
let remainingCompletion = predictedCompletion;
const isSilenceRefresh =
modelUserText.includes(SILENCE_TOKEN) &&
state.hasPrediction &&
state.predictionAnchor === anchor;
if (currentText !== anchor) {
if (!currentText.startsWith(anchor)) {
return false;
}
const consumedCompletion = currentText.slice(anchor.length);
if (!predictedCompletion.startsWith(consumedCompletion)) {
return false;
}
remainingCompletion = predictedCompletion.slice(consumedCompletion.length);
}
if (
isSilenceRefresh &&
!parsed.complete &&
isRegressiveRefresh(
state.remainingUserCompletion,
remainingCompletion,
state.assistantText,
parsed.assistant_response || "",
)
) {
return false;
}
state.predictionAnchor = anchor;
state.predictionModelUserText = modelUserText;
state.predictedUserCompletion = predictedCompletion;
state.remainingUserCompletion = remainingCompletion;
state.assistantText = parsed.assistant_response || "";
state.errorText = "";
state.hasPrediction =
Boolean(parsed.has_user_completion_tag) ||
Boolean(parsed.has_assistant_response_tag);
state.predictionComplete = Boolean(parsed.complete);
state.predictionTurnDone =
Boolean(parsed.user_completion_closed) &&
normalizeInline(state.remainingUserCompletion) === "";
render();
return true;
}
function removeEchoedUserPrefix(userText, predictedCompletion) {
const normalizedUser = normalizeInline(stripSilenceTokens(userText)).toLowerCase();
if (!normalizedUser || !predictedCompletion.trim()) {
return predictedCompletion;
}
let bestEnd = 0;
for (let end = 1; end <= predictedCompletion.length; end += 1) {
const prefix = normalizeInline(predictedCompletion.slice(0, end)).toLowerCase();
if (prefix && normalizedUser.endsWith(prefix)) {
bestEnd = end;
}
}
return bestEnd ? predictedCompletion.slice(bestEnd).trimStart() : predictedCompletion;
}
function isRegressiveRefresh(
previousUserCompletion,
nextUserCompletion,
previousAssistant,
nextAssistant,
) {
return (
isRegressiveText(previousUserCompletion, nextUserCompletion) ||
isRegressiveText(previousAssistant, nextAssistant)
);
}
function isRegressiveText(previous, next) {
if (!previous) {
return false;
}
return previous.startsWith(next) && previous !== next;
}
async function commitCurrentTurn(reason) {
if (state.locked) {
return;
}
const userText = composer.value;
if (!userText.trim()) {
return;
}
const turnStoppedAt = performance.now();
state.typed = userText;
clearTimeout(state.debounceTimer);
state.debounceTimer = null;
if (state.mode === MODE_BASELINE) {
await commitBaselineTurn(userText, turnStoppedAt);
return;
}
reconcilePrediction();
if (
state.hasPrediction &&
state.predictionTurnDone &&
state.inFlight
) {
queuePendingCommit(state.requestSeq, userText, reason, turnStoppedAt);
return;
}
if (
state.hasPrediction &&
state.predictionTurnDone &&
state.assistantText.trim()
) {
beginLatencyMeasurement(state.requestSeq, reason, turnStoppedAt);
observeAssistantFirstToken(state.requestSeq, turnStoppedAt);
if (state.controller) {
state.controller.abort();
markCall(state.activeCallNode, "canceled", "canceled");
}
state.requestSeq += 1;
commitPrediction(
userText,
{ assistant_response: state.assistantText },
state.predictionModelUserText || userText,
);
render();
return;
}
invalidatePrediction();
state.typed = userText;
composer.value = userText;
resizeComposer();
await runInference(reason, {
userText,
requestText: userText,
commitAfterResult: true,
lockDuringRequest: true,
turnComplete: true,
latencyStartedAt: turnStoppedAt,
latencySource: reason,
});
}
async function commitBaselineTurn(userText, turnStoppedAt) {
invalidatePrediction();
state.typed = userText;
composer.value = userText;
resizeComposer();
await runBaselineResponse(userText, turnStoppedAt);
}
async function runBaselineResponse(userText, latencyStartedAt) {
state.requestSeq += 1;
const seq = state.requestSeq;
const controller = new AbortController();
state.controller = controller;
state.inFlight = true;
state.activeCallNode = addCall({
seq,
reason: "non-interactive",
text: userText,
});
state.assistantText = "";
state.errorText = "";
beginLatencyMeasurement(seq, "baseline", latencyStartedAt);
lockComposer(seq);
render();
let assistantText = "";
let committed = false;
try {
const response = await fetch("/api/respond", {
method: "POST",
credentials: "same-origin",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ typed: userText, history: state.history }),
signal: controller.signal,
});
if (response.status === 401) {
authView.classList.remove("hidden");
appView.classList.add("hidden");
return null;
}
if (!response.ok || !response.body) {
throw new Error(`Response failed with HTTP ${response.status}`);
}
await readEventStream(response.body, (event, data) => {
if (seq !== state.requestSeq) {
return;
}
if (event === "meta") {
updateCallMeta(state.activeCallNode, data);
}
if (event === "delta") {
assistantText += data.text || "";
state.assistantText = assistantText;
observeAssistantFirstToken(seq, performance.now());
render();
}
if (event === "result") {
assistantText = data.assistant_response || assistantText;
state.assistantText = assistantText;
observeAssistantFirstToken(seq, performance.now());
render();
}
if (event === "error") {
throw new Error(data.error || "Response failed.");
}
});
if (seq === state.requestSeq) {
markCall(state.activeCallNode, "done", "done");
committed = commitPrediction(userText, { assistant_response: assistantText });
}
return assistantText;
} catch (error) {
if (error.name === "AbortError") {
return null;
}
markCall(state.activeCallNode, "error", "error");
state.errorText = error.message || "Response failed.";
clearPendingLatency(seq);
return null;
} finally {
if (seq === state.requestSeq) {
state.inFlight = false;
state.controller = null;
state.activeCallNode = null;
if (!committed && state.lockedSeq === seq) {
unlockComposer(seq);
}
render();
}
}
}
function queueCommitFromPrediction(source = "predicted", startedAt = performance.now()) {
if (
!state.hasPrediction ||
!state.predictionTurnDone ||
!state.typed.trim()
) {
return false;
}
if (state.inFlight) {
queuePendingCommit(
state.requestSeq,
state.typed,
source,
startedAt,
state.predictionModelUserText || state.typed,
);
return true;
}
if (state.assistantText.trim()) {
beginLatencyMeasurement(state.requestSeq, source, startedAt);
observeAssistantFirstToken(state.requestSeq, startedAt);
commitPrediction(
state.typed,
{ assistant_response: state.assistantText },
state.predictionModelUserText || state.typed,
);
return true;
}
return false;
}
function queuePendingCommit(
seq,
userText,
source = "predicted",
startedAt = performance.now(),
modelUserText = userText,
) {
if (!userText.trim()) {
return;
}
state.pendingCommitSeq = seq;
state.pendingCommitText = userText;
state.pendingCommitModelText = modelUserText;
beginLatencyMeasurement(seq, source, startedAt);
observeAssistantFirstToken(seq, startedAt);
lockComposer(seq);
render();
}
function commitPrediction(userText, prediction, modelUserText = userText) {
const committedModelUser = modelUserText.trimEnd();
const committedAssistant = (prediction.assistant_response || "").trim();
if (!committedModelUser.trim()) {
return false;
}
if (!committedAssistant) {
state.errorText = "Assistant prediction was empty.";
return false;
}
observeAssistantFirstToken(null, performance.now());
if (isInteractiveMode(state.mode)) {
recordPredictionAccuracy(state.interactiveInferenceCount);
}
state.history.push({ role: "user", content: committedModelUser });
state.history.push({ role: "assistant", content: committedAssistant });
state.history = state.history.slice(-24);
state.typed = "";
composer.value = "";
resizeComposer();
stopSilenceLoop();
clearPredictionState();
resetCurrentInteractiveMetrics();
unlockComposer();
renderHistory();
return true;
}
function clearPredictionState() {
state.predictionAnchor = null;
state.predictionModelUserText = "";
state.predictedUserCompletion = "";
state.remainingUserCompletion = "";
state.assistantText = "";
state.errorText = "";
state.hasPrediction = false;
state.predictionComplete = false;
state.predictionTurnDone = false;
state.pendingCommitSeq = null;
state.pendingCommitText = "";
state.pendingCommitModelText = "";
}
function lockComposer(seq) {
state.locked = true;
state.lockedSeq = seq;
}
function unlockComposer(seq = null) {
if (seq !== null && state.lockedSeq !== seq) {
return;
}
state.locked = false;
state.lockedSeq = null;
state.pendingCommitSeq = null;
state.pendingCommitText = "";
state.pendingCommitModelText = "";
window.requestAnimationFrame(() => {
if (!state.locked && !appView.classList.contains("hidden")) {
composer.focus();
}
});
}
function beginLatencyMeasurement(seq, source, startedAt) {
if (state.measuredLatencySeqs.has(seq)) {
return;
}
if (
state.pendingLatency &&
state.pendingLatency.seq === seq &&
!state.pendingLatency.recorded
) {
return;
}
state.pendingLatency = {
seq,
source,
startedAt,
recorded: false,
};
}
function observeAssistantFirstToken(seq = null, observedAt = performance.now()) {
if (!state.pendingLatency || state.pendingLatency.recorded) {
return false;
}
if (seq !== null && state.pendingLatency.seq !== seq) {
return false;
}
if (!state.assistantText.trim()) {
return false;
}
const latencyMs = Math.max(
0,
Math.round(observedAt - state.pendingLatency.startedAt),
);
state.latencyMeasurements.push({
latencyMs,
source: state.pendingLatency.source,
});
state.latencyMeasurements = state.latencyMeasurements.slice(-100);
state.measuredLatencySeqs.add(state.pendingLatency.seq);
state.pendingLatency.recorded = true;
state.pendingLatency = null;
renderLatencyAverage();
return true;
}
function clearPendingLatency(seq) {
if (!state.pendingLatency) {
return;
}
if (seq === null || state.pendingLatency.seq === seq) {
state.pendingLatency = null;
}
}
function renderLatencyAverage() {
if (!latencyAverage) {
return;
}
if (!state.latencyMeasurements.length) {
latencyAverage.textContent = "avg ttft --";
return;
}
const total = state.latencyMeasurements.reduce(
(sum, measurement) => sum + measurement.latencyMs,
0,
);
const average = total / state.latencyMeasurements.length;
latencyAverage.textContent =
`avg ttft ${formatLatency(average)} (${state.latencyMeasurements.length})`;
}
function recordPredictionAccuracy(inferenceCount) {
const score = predictionAccuracyScore(inferenceCount);
if (score === null) {
return;
}
state.predictionAccuracies.push(score);
state.predictionAccuracies = state.predictionAccuracies.slice(-100);
renderAccuracyAverage();
}
function predictionAccuracyScore(inferenceCount) {
if (!inferenceCount) {
return null;
}
return 1 / inferenceCount;
}
function resetCurrentInteractiveMetrics() {
state.interactiveInferenceCount = 0;
}
function renderAccuracyAverage() {
if (!accuracyAverage) {
return;
}
accuracyAverage.classList.toggle("hidden", state.mode === MODE_BASELINE);
if (!state.predictionAccuracies.length) {
accuracyAverage.textContent = "avg accuracy --";
return;
}
const total = state.predictionAccuracies.reduce(
(sum, score) => sum + score,
0,
);
const average = total / state.predictionAccuracies.length;
accuracyAverage.textContent =
`avg accuracy ${formatPercent(average)} (${state.predictionAccuracies.length})`;
}
function formatPercent(value) {
return `${Math.round(value * 100)}%`;
}
function formatLatency(milliseconds) {
if (milliseconds < 1000) {
return `${Math.round(milliseconds)} ms`;
}
if (milliseconds < 10_000) {
return `${(milliseconds / 1000).toFixed(1)} s`;
}
return `${Math.round(milliseconds / 1000)} s`;
}
function normalizeInline(text) {
return text.replace(/\s+/g, " ").trim();
}
function stripSilenceTokens(text) {
return text.replaceAll(SILENCE_TOKEN, "").replace(/\s+/g, " ").trimStart();
}
function isInteractiveMode(mode) {
return mode === MODE_INTERACTIVE_BASE || mode === MODE_INTERACTIVE_RL;
}
function predictionVariantForMode(mode) {
return mode === MODE_INTERACTIVE_RL ? "rl" : "base";
}
function interactiveCallReason(mode, reason) {
const prefix = mode === MODE_INTERACTIVE_RL ? "interactive-rl" : "interactive";
return `${prefix} ${reason}`;
}
async function readEventStream(body, onEvent) {
const reader = body.getReader();
const decoder = new TextDecoder();
let buffer = "";
while (true) {
const { value, done } = await reader.read();
if (done) {
break;
}
buffer += decoder.decode(value, { stream: true });
const frames = buffer.split("\n\n");
buffer = frames.pop() || "";
for (const frame of frames) {
const parsed = parseSseFrame(frame);
if (parsed) {
onEvent(parsed.event, parsed.data);
}
}
}
if (buffer.trim()) {
const parsed = parseSseFrame(buffer);
if (parsed) {
onEvent(parsed.event, parsed.data);
}
}
}
function parseSseFrame(frame) {
const lines = frame.split(/\r?\n/);
let event = "message";
const dataLines = [];
for (const line of lines) {
if (line.startsWith("event:")) {
event = line.slice(6).trim();
}
if (line.startsWith("data:")) {
dataLines.push(line.slice(5).trimStart());
}
}
if (!dataLines.length) {
return null;
}
return { event, data: JSON.parse(dataLines.join("\n")) };
}
function render() {
renderMode();
renderHistory();
renderLatencyAverage();
renderAccuracyAverage();
composer.disabled = state.locked;
appView.classList.toggle("locked", state.locked);
typedText.textContent = state.typed;
predictedText.textContent =
isInteractiveMode(state.mode)
? stripSilenceTokens(state.remainingUserCompletion)
: "";
const isThinking =
state.inFlight &&
!state.assistantText.trim() &&
(state.mode === MODE_BASELINE || !normalizeInline(state.remainingUserCompletion));
thinking.classList.toggle("active", isThinking);
thinking.innerHTML = isThinking
? "..."
: "";
assistantResponse.textContent = state.errorText || state.assistantText;
assistantResponse.className = "assistant-response";
if (state.errorText) {
assistantResponse.classList.add("error");
return;
}
if (
(isInteractiveMode(state.mode) && state.hasPrediction && state.predictionTurnDone) ||
(state.mode === MODE_BASELINE && state.assistantText.trim())
) {
assistantResponse.classList.add("ready");
}
}
function renderMode() {
for (const button of modeButtons) {
const active = button.dataset.mode === state.mode;
button.classList.toggle("active", active);
button.setAttribute("aria-pressed", String(active));
button.disabled = state.locked;
}
}
function renderHistory() {
historyView.replaceChildren();
historyView.classList.toggle("empty", state.history.length === 0);
for (const message of state.history) {
const row = document.createElement("div");
row.className = `history-line ${message.role}`;
const role = document.createElement("span");
role.className = "history-role";
role.textContent = message.role === "user" ? "user" : "assistant";
const content = document.createElement("div");
content.className = "history-content";
content.textContent =
message.role === "user" ? stripSilenceTokens(message.content) : message.content;
row.append(role, content);
historyView.append(row);
}
}
function resizeComposer() {
composer.style.height = "auto";
composer.style.height = `${Math.max(78, composer.scrollHeight)}px`;
}
function addCall({ seq, reason, text }) {
const node = document.createElement("div");
node.className = "call-item running";
node.dataset.seq = String(seq);
node.dataset.status = "starting";
const prompt = document.createElement("span");
prompt.className = "call-prompt";
prompt.textContent = ">";
const label = document.createElement("span");
label.className = "call-label";
label.textContent = `#${seq} ${reason}`;
const meta = document.createElement("div");
meta.className = "call-meta";
meta.textContent = "starting";
const separator = document.createElement("span");
separator.className = "call-separator";
separator.textContent = "::";
const preview = document.createElement("div");
preview.className = "call-preview";
preview.textContent = stripSilenceTokens(text);
node.append(prompt, label, meta, separator, preview);
callList.prepend(node);
return node;
}
function updateCallMeta(node, data) {
if (!node) {
return;
}
const meta = node.querySelector(".call-meta");
const model = data.model || "model";
const chars = data.chars ?? 0;
const turns = data.history_turns ?? 0;
node.dataset.model = model;
node.dataset.chars = String(chars);
node.dataset.turns = String(turns);
node.dataset.status = "running";
meta.textContent = `${model} ${chars}c ${turns}t running`;
}
function markCall(node, className, label) {
if (!node) {
return;
}
node.classList.remove("running", "done", "error", "canceled");
node.classList.add(className);
node.dataset.status = label;
const meta = node.querySelector(".call-meta");
if (meta) {
const model = node.dataset.model || "model";
const chars = node.dataset.chars || "?";
const turns = node.dataset.turns || "0";
meta.textContent = `${model} ${chars}c ${turns}t ${label}`;
}
}
void boot();