Something went wrong. Try again.
a tiny pet with a GPT-2 brain, living in your browser
Something went wrong. Try again.
4.9 kB · 136 lines
TSX
at cloud-pet
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137import { useEffect, useRef } from "preact/hooks";import { brainHas, BRAINS, closeUpgrade, getBrain, olderBrain, onMobileData, startUpgrade,} from "../app/brain.ts";import { CFG, FEATURE_TEXT } from "../app/config.ts";import { brain, store, ui, upgrade } from "../app/store.ts";import { fmtMB } from "../app/utils.ts";import { isRemote } from "../app/hosting.ts";export function BrainNotice() { if (ui.hostingBusy || isRemote()) return ( <div id="chat-cta" class="brain-notice cta" hidden={!ui.hostingBusy && !ui.remoteError && brain.state === "ready"} > <p id="chat-cta-text" role="status"> {ui.hostingBusy ? "Moving your pet safely…" : ui.remoteError || "Connecting to your pet's server…"} </p> <button id="chat-brain" type="button" class="primary" disabled={ui.hostingBusy} onClick={getBrain} > reconnect to server </button> </div> ); const name = store.state.pet?.name; const up = upgrade.state, dozing = brain.state === "off" || brain.state === "error"; const hidden = !name || !(dozing || olderBrain() || up === "swapping"); const text = dozing ? `${name} is dozing: its brain isn't in this browser yet. It downloads once and stays here.${onMobileData() ? " (You seem to be on mobile data.)" : ""}` : up === "downloading" ? `Downloading ${name}'s new brain… ${fmtMB(upgrade.loaded)} of ${fmtMB(CFG.size)}` : up === "swapping" ? `${name} is waking up with its new brain…` : up === "error" ? `The new brain didn't download (${upgrade.error}). ${name} still has its old one.` : `A new brain is ready for ${name}. ${CFG.news || ""}`.trim(); return ( <div id="chat-cta" class="brain-notice" hidden={hidden}> <p id="chat-cta-text" role="status"> {text} </p> <button id="chat-brain" type="button" class="primary" hidden={up === "downloading" || up === "swapping"} onClick={getBrain} > {dozing ? "download brain" : up === "error" ? "try again" : "upgrade"} ({fmtMB(CFG.size)}) </button> </div> );}export function UpgradeDialog() { const dialog = useRef<HTMLDialogElement>(null), name = store.state.pet?.name || "your pet"; useEffect(() => { const d = dialog.current; if (ui.upgradeOpen && !d?.open) d?.showModal(); else if (!ui.upgradeOpen && d?.open) d.close(); }, [ui.upgradeOpen]); const gains = BRAINS[0].features.filter((f) => !brainHas(f)).map((f) => FEATURE_TEXT[f] || f); return ( <dialog ref={dialog} id="brain-upgrade" class="pet-dialog" aria-labelledby="upgrade-title" onClose={closeUpgrade} onCancel={closeUpgrade} > <h2 id="upgrade-title">A new brain for {name}</h2> <div id="upgrade-text"> <p>{CFG.news || `${CFG.modelId} is ready.`}</p> {!!gains.length && <p>It can also: {gains.join("; ")}.</p>} <p> Download: about {fmtMB(CFG.size)}. {name} keeps its memories, chat and diary; only the brain changes, and {name} stays awake while it downloads. </p> {onMobileData() && ( <p class="warn"> You seem to be on mobile data. You can keep the current brain and upgrade later on Wi-Fi. </p> )} </div> <div class="pet-row"> <button id="upgrade-later" type="button" class="text-button" onClick={closeUpgrade}> not now </button> <button id="upgrade-now" type="button" class="primary" onClick={startUpgrade}> upgrade ({fmtMB(CFG.size)}) </button> </div> </dialog> );}export function brainStatus() { if (isRemote()) return ( ui.remoteError || (brain.state === "ready" ? `${brain.id || CFG.modelId}, connected to your server. Your pet keeps thinking while this app is closed.` : "Connecting to the server's brain…") ); const id = brain.id || CFG.modelId, up = upgrade.state; return { off: "Not downloaded. Without it your pet just dozes.", downloading: brain.progress ? `Downloading ${id}… ${fmtMB(brain.progress.loaded)} of ${fmtMB(brain.progress.total)}` : "Starting…", warming: "Waking up…", ready: `${id}, awake and running on this device${brain.threads === 1 ? " (one thread)" : ""}${brain.tps ? ` · ${brain.tps.toFixed(1)} tokens/s` : ""}.` + (olderBrain() ? ` A newer brain, ${CFG.modelId}, is available${up === "downloading" ? `: downloading, ${fmtMB(upgrade.loaded)} of ${fmtMB(CFG.size)}` : up === "error" ? ` (the download failed: ${upgrade.error})` : ""}.` : ""), error: `Could not load: ${brain.error}`, }[brain.state];}