Something went wrong. Try again.
a tiny pet with a GPT-2 brain, living in your browser
Something went wrong. Try again.
5.5 kB · 161 lines
TSX
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162import { useState } from "preact/hooks";import { disturbanceCount } from "../app/animation.ts";import { offerThing } from "../app/care.ts";import { DAY, MIN, STAGE_AGE } from "../app/config.ts";import { copyText, setAge } from "../app/debug.ts";import { writeDiary } from "../app/diary.ts";import { age, dayNum, worldState } from "../app/simulation.ts";import { save } from "../app/storage.ts";import { brain, emit, store, ui, view } from "../app/store.ts";import type { Disturbance, Stat } from "../types.ts";import { header, wakeChance } from "../world.ts";export function Debug() { const s = store.state, pet = s.pet; const [days, setDays] = useState(() => (age() / DAY).toFixed(2)); const n = disturbanceCount() + 1; return ( <> <h2>Pet</h2> {pet ? ( <> <p class="muted small">{`brain ${brain.id || "none"} · ${pet.stage}, day ${dayNum()} (${(age() / DAY).toFixed(2)} days old) · offer open: ${s.offer ? offerThing(s.offer) : "none"}`}</p> <div class="pet-row"> {STAGE_AGE.slice() .reverse() .map(([stage, ms]) => ( <button key={stage} type="button" class={stage === pet.stage ? "primary" : "text-button"} onClick={() => { setAge(ms + MIN); setDays((age() / DAY).toFixed(2)); }} > {stage} </button> ))} </div> <label for="debug-age">age in days</label> <div class="pet-row"> <input id="debug-age" type="number" min={0} step={0.25} value={days} inputMode="decimal" onInput={(e) => setDays(e.currentTarget.value)} /> <button type="button" class="text-button" onClick={() => setAge(Math.max(0, +days || 0) * DAY)} > set age </button> </div> <div class="debug-grid"> {(Object.keys(s.stats) as Stat[]).map((k) => ( <div class="debug-stat" key={k}> <label for={`debug-${k}`}>{k}</label> <input id={`debug-${k}`} type="range" min={0} max={100} value={Math.round(s.stats[k])} onInput={(e) => { s.stats[k] = +e.currentTarget.value; save(); emit(); }} /> <span>{Math.round(s.stats[k])}</span> </div> ))} </div> <label class="pet-check"> <input type="checkbox" checked={s.sick} onChange={(e) => { s.sick = e.currentTarget.checked; save(); emit(); }} /> sick </label> <p class="muted small" data-debug-wake=""> {`${s.asleep ? "Asleep" : "Awake"} · next disturbance #${n}: `} {(["talk", "touch", "light"] as Disturbance[]) .map((k) => `${k} ${Math.round(wakeChance(s.stats.energy, k, n) * 100)}%`) .join(" · ")} </p> <p class="muted small"> Write today's page using the log so far, even if it is short. An early page skips bedtime writing; rewrite it later to include new events. </p> <button type="button" class="text-button" data-debug-diary="" disabled={brain.busy || brain.state !== "ready" || !!view.game} onClick={() => writeDiary(s.today.date, true)} > {s.diary.some((e) => e.date === s.today.date) ? "rewrite today's page" : "write today's page"} </button> </> ) : ( <p class="muted small">No pet yet.</p> )} <h2>Context</h2> <p class="muted small"> The last prompts sent to the brain, newest first; what it wrote is highlighted. Only kept until the page reloads. </p> <div class="pet-row"> <button type="button" class="primary" disabled={!ui.debugLog.length} onClick={() => { const d = ui.debugLog.at(-1); if (d) void copyText(d.prompt + d.text); }} > copy latest </button> <button type="button" class="text-button" disabled={!pet} onClick={() => copyText(header("chat", worldState()) + s.chat.map((l) => l + "\n").join("")) } > copy full chat </button> </div> {ui.debugLog .slice() .reverse() .map((d) => ( <details key={d.id}> <summary>{`${d.at.toLocaleTimeString()} · ${d.mode} · ${d.promptTokens} prompt tokens · stopped: ${d.reason}`}</summary> <pre class="debug-pre"> {d.prompt} <span class="debug-out">{d.text}</span> </pre> <button type="button" class="text-button" onClick={() => copyText(d.prompt + d.text)}> copy </button> </details> ))} </> );}