| 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 |
| ? "<span>.</span><span>.</span><span>.</span>" |
| : ""; |
|
|
| 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(); |
|
|