Something went wrong. Try again.
a tiny pet with a GPT-2 brain, living in your browser
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960import { Engine, type Effect } from "../core.ts";import type { PetCommand, PetState } from "../types.ts";import { save } from "./storage.ts";import { emit, store, toast } from "./store.ts";import { errorMessage } from "./utils.ts";
// The browser's copy of the pet lives in the shared Rust engine (core/), the// same one the host runs. `store.state` is a read-only snapshot for rendering.// In remote mode the engine only holds the server's latest checkpoint.let engine: Engine | null = null;export function petEngine(): Engine { if (!engine) throw new Error("The pet has not loaded yet."); return engine;}/** `seed` is the deployment's weather seed, shared with its host. */export function startEngine(state: PetState, seed: string) { engine?.raw.free(); engine = new Engine(state, Date.now(), seed); store.state = engine.state();}let onChange: ((effects: Effect[]) => void) | null = null;/** Runs after every change with its new effects (lifecycle.ts plays them). */export function afterChanges(hook: (effects: Effect[]) => void) { onChange = hook;}/** Refreshes the snapshot (only the body fields when `full` is false), hands on new effects and saves. */export function changed(full = true) { const e = petEngine(); store.state = full ? e.state() : { ...store.state, ...e.body() }; const effects = e.takeEffects(); onChange?.(effects); save(); emit();}/** Replaces the save: an import, a transfer or a server snapshot. */export function setState(state: PetState, keepTurns = false) { const e = petEngine(); if (keepTurns) e.edit(state); else e.replace(state, Date.now()); changed();}/** Debug and test edits of the save, keeping the turn queue. */export function editState(edit: (state: PetState) => void) { const state = petEngine().state(); edit(state); setState(state, true);}/** Runs an owner command locally. Refusals become a toast. */export function localCommand(command: PetCommand) { try { petEngine().command(command, Date.now()); return true; } catch (error) { toast(errorMessage(error)); return false; } finally { changed(); }}