Something went wrong. Try again.
a tiny pet with a GPT-2 brain, living in your browser
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175// Disposable preview/profile only. Configure REMOTE_ENDPOINT in the preview and// run: playwright-cli -s=host run-code --filename=test/hosting-flow.js// Uses the real host and browser brains; never prints access keys.async function hostingFlow(page) { const check = (ok, message) => { if (!ok) throw new Error(message); }; const ready = () => page.waitForFunction(() => window.tokenling?.brain.state === "ready", null, { timeout: 120000, }); const identity = () => page.evaluate(() => { const s = tokenling.state(); return { owner: s.owner, name: s.pet.name, hatched: s.pet.hatched, traits: s.pet.traits }; }); const privateConnection = () => page.evaluate(() => JSON.parse(localStorage.getItem("tokenling.remote.v1"))); const readHost = async (c) => { const response = await page.request.get(c.base + "/api/pets/" + c.id, { headers: { Authorization: "Bearer " + c.key }, }); check(response.ok(), "Private host read failed"); return response.json(); }; const results = []; await page.waitForFunction(() => !!window.tokenling); check(await page.locator("#setup-owner").isVisible(), "Use a fresh test profile"); await page.setViewportSize({ width: 360, height: 900 }); await page.fill("#owner-name", "Sam"); await page.check("#setup-remote"); check(!!(await page.inputValue("#setup-server")), "Configure REMOTE_ENDPOINT in the preview"); let dropped = false; const transfers = "**/api/pets/*/transfer"; await page.route(transfers, async (route) => { if (!dropped && route.request().postDataJSON().mode === "remote") { dropped = true; await route.fetch(); // Commit the activation, then lose its acknowledgement. await route.abort("failed"); } else await route.continue(); }); await page.click("#setup-owner button"); await ready(); await page.unroute(transfers); await page.fill("#pet-name", "Mochi"); await page.click("#hatch-btn"); await page.waitForFunction( () => tokenling.state().pet && tokenling.state().chat.some((l) => l.startsWith("Mochi:")), null, { timeout: 120000 }, ); check( await page.evaluate( () => !tokenling.brain.worker && !performance.getEntriesByType("resource").some((r) => r.name.includes(".onnx")), ), "Remote setup loaded a local model", ); check(dropped, "Lost acknowledgement was not exercised"); results.push("remote creation and lost-activation reconciliation without model download"); const original = await identity(); const c = await privateConnection(); const initial = await readHost(c); const appUrl = page.url(); await page.goto("about:blank"); await page.waitForTimeout(20000); const away = await readHost(c); check(away.state.lastTick > initial.state.lastTick, "Host body stopped with the page closed"); check(away.state.stats.tummy < initial.state.stats.tummy, "Host body did not decay"); await page.goto(appUrl); await ready(); await page.click("#tab-care"); await page.check("#hosting-local"); await page.click("#hosting-switch"); await ready(); check( await page.evaluate( () => tokenling.state().hosting.mode === "local" && !!tokenling.brain.worker, ), "Local handoff did not load the browser brain", ); check( JSON.stringify(await identity()) === JSON.stringify(original), "Local handoff changed identity", ); check((await readHost(c)).authority === "local", "Old host executor was not parked"); await page.check("#hosting-remote"); await page.click("#hosting-switch"); await ready(); check( await page.evaluate( () => tokenling.state().hosting.mode === "remote" && !tokenling.brain.worker, ), "Return to remote kept a browser brain", ); check( JSON.stringify(await identity()) === JSON.stringify(original), "Remote handoff changed identity", ); results.push("closed-page body/thoughts and both transfer directions preserve identity"); const outage = c.base + "/api/**"; await page.route(outage, (route) => route.abort("failed")); await page.waitForFunction( () => document.querySelector("#hosting-recover")?.offsetParent !== null, ); // Auto-accept this recovery confirmation only in the disposable test page. await page.evaluate(() => { window.confirm = () => true; }); await page.click("#hosting-recover"); await ready(); check( await page.evaluate(() => tokenling.state().hosting.mode === "local"), "Offline recovery did not resume locally", ); const checkpoint = await page.evaluate(() => { // Explicit fixture on the local recovery branch, edited through the engine. tokenling.debug.edit((s) => { s.memories.push("Sam likes frogs"); }); return tokenling.state().pet.hatched; }); const alternate = await page.evaluate((base) => { const url = new URL(base); if (!["localhost", "127.0.0.1"].includes(url.hostname)) return null; url.hostname = url.hostname === "localhost" ? "127.0.0.1" : "localhost"; return url.href; }, c.base); if (alternate) { // Two loopback addresses stand in for different hosts while the first is // unreachable. They create separate hosted pet records and capabilities. await page.check("#hosting-remote"); await page.fill("#hosting-server", alternate); await page.click("#hosting-switch"); await ready(); check( await page.evaluate(() => !!localStorage.getItem("tokenling.remote-stops.v1")), "Moving to another host discarded the pending stop", ); } await page.unroute(outage); await page.evaluate(() => dispatchEvent(new Event("online"))); await page.waitForFunction(() => !localStorage.getItem("tokenling.remote-stops.v1"), null, { timeout: 30000, }); check((await readHost(c)).authority === "local", "Recovered host was not stopped on reconnect"); check( await page.evaluate( (h) => tokenling.state().pet.hatched === h && tokenling.state().memories.includes("Sam likes frogs"), checkpoint, ), "A stop response overwrote newer local progress", ); results.push("offline checkpoint recovery and eventual stop preserve the local branch"); if (alternate) results.push("a new host preserves and delivers the unreachable old host's stop"); for (const width of [1280, 768, 360]) { await page.setViewportSize({ width, height: 900 }); for (const panel of ["chat", "diary", "shelf", "care"]) { await page.click("#tab-" + panel); check( await page.evaluate(() => document.documentElement.scrollWidth === innerWidth), `Overflow in ${panel} at ${width}`, ); } } results.push("hosting controls and panels fit 1280/768/360 px"); await page.evaluate((r) => { window.hostingFlowResults = r; }, results); return results;}