// Static demo for web/autocomplete.ts. Bundle with: // bun build web/demo.ts --outfile web/demo.js --target browser --minify import { CompiledAutocomplete, type Policy } from "./autocomplete.ts"; const $ = (id: string) => document.getElementById(id) as T; const promptEl = $("prompt"); const ghostEl = $("ghost"); const statusEl = $("status"); const guessEl = $("guess"); const tauEl = $("tau"); const tauLabel = $("tau-label"); const loadEl = $("load"); const EXAMPLES = [ "write a python fun", "how do i ", "Write a function to find the ", "how to convert a ", "can you explain ", "I hope this email ", "Once upon a ", "what is the difference between ", ]; function esc(s: string): string { return s.replace(/[&<>]/g, (c) => ({ "&": "&", "<": "<", ">": ">" })[c]!); } async function main(): Promise { const t0 = performance.now(); const ac = await CompiledAutocomplete.load("model.bin", (f) => (loadEl.textContent = `downloading model... ${Math.round(f * 100)}%`)); const loadMs = performance.now() - t0; const policy: Policy = { ...ac.policy }; tauEl.value = String(policy.tau); tauLabel.textContent = `${Math.round(policy.tau * 100)}%`; loadEl.textContent = `${(ac.bytes / 1e6).toFixed(1)} MB · ${ac.contexts.toLocaleString()} compiled contexts · ` + `${ac.order}-token context · ${ac.vocab.length.toLocaleString()} words · loaded in ${Math.round(loadMs)} ms`; promptEl.disabled = false; promptEl.focus(); let ghost = ""; const render = () => { const text = promptEl.value; const start = performance.now(); const s = ac.suggest(text, policy); const ms = performance.now() - start; ghost = s.ghost; ghostEl.innerHTML = esc(text) + "" + esc(ghost) + ""; promptEl.style.height = "auto"; promptEl.style.height = Math.max(promptEl.scrollHeight, ghostEl.scrollHeight) + "px"; statusEl.textContent = text ? `${ms.toFixed(2)} ms` : ""; // First step that adds text (the first step is empty when the typed word is already complete). const i = s.steps.findIndex((st) => st.text); const guess = i < 0 ? "" : s.steps.slice(0, i + 1).map((st) => st.text).join(""); if (!text) guessEl.textContent = ""; else if (ghost) guessEl.textContent = `suggesting with ${Math.round(s.prob * 100)}% confidence`; else if (guess) guessEl.textContent = `staying quiet: best guess "${guess}" is only ${Math.round(s.steps[i].prob * 100)}% likely`; else guessEl.textContent = "staying quiet: nothing known for this prefix"; }; promptEl.addEventListener("input", render); promptEl.addEventListener("keydown", (e) => { if (e.key === "Tab" && ghost) { e.preventDefault(); promptEl.value += ghost; render(); } }); tauEl.addEventListener("input", () => { policy.tau = Number(tauEl.value); tauLabel.textContent = `${Math.round(policy.tau * 100)}%`; render(); }); for (const ex of EXAMPLES) { const b = document.createElement("button"); b.className = "ex"; b.textContent = ex.trim(); b.onclick = () => { promptEl.value = ex; render(); promptEl.focus(); }; $("examples").appendChild(b); } render(); } main().catch((e) => (loadEl.textContent = String(e)));