wai-rs gains the feature floor (the mandatory floor of SPEC 5: PNG, FLAC and zstd, decoded with no system codec library) and quickstart (the floor, and the receipt checks hello and verify run). The wai command line gains four verbs, one module each, named in one table (dx::VERBS): - hello: name, dispatch, rebuild and receipt on a picture made here, the receipt laid out as http-delivery 8 lays receipts beside an object; - create: a new project from one of the examples, whose files the binary holds; tests/cli_dx.rs holds them to wai/examples/ byte for byte; - dev: the relay, the room service and the room page on one loopback origin, as a production front serves them; --check checks each piece through it; - verify: the receipt indexes under a directory, checked offline. The project file a template writes, wai.json, is read in one place (dx/project.rs). wai/examples/ holds video-room, watch-together, messaging, encoder-ingest, package-and-deliver, verify-receipts, apple-app, android-app and remote-desktop, each with a README and a test that runs it through wai create and wai dev. wai/quickstart/ builds the room client and the archive that holds wai, the relay, the room service, the remote host and the packager. Co-Authored-By: Claude Opus 5.5 <[email protected]>
40 lines
2.9 KiB
JavaScript
40 lines
2.9 KiB
JavaScript
// The remote-desktop example in a browser: `wai create` makes the project, `wai dev` runs the
|
|
// room in remote desktop mode, host.sh shares a drawn pattern, and a browser joins. Its page
|
|
// must decode the host's screen, every frame verified first, and hold a controller's grant;
|
|
// asking for control, it must be given the floor and see its pointer applied by the host.
|
|
//
|
|
// node wai/examples/remote-desktop/test/remote-desktop.test.mjs
|
|
import { spawn } from "node:child_process";
|
|
import { check, create, dev, dump, finish, launch, open, STEP, tmpdir, until } from "../../../quickstart/test/lib.mjs";
|
|
|
|
const out = tmpdir("remote-desktop");
|
|
const dir = await create("remote-desktop", out);
|
|
const d = await dev(dir);
|
|
const host = spawn("sh", ["host.sh", "--pattern", "--seconds", "240"], { cwd: dir, env: { ...process.env, WAI_DEV_ORIGIN: d.url }, stdio: "ignore" });
|
|
const browser = await launch();
|
|
const pages = [];
|
|
const remoteOf = (p) => p.evaluate(() => { const r = window.roomTest.remote; return r && { screen: r.screen && { width: r.screen.width, state: r.screen.state }, holder: r.holder, frames: r.frames.size, counts: r.counts, me: r.me, joined: r.joined, control: r.control }; });
|
|
try {
|
|
await until("the host's screen reaches the room", STEP, async () => { const v = await (await fetch(`${d.url}/room-api/room`)).json(); return v.remote && v.remote.screen; }, 250);
|
|
const p = await open(browser, `${d.url}/`, "alice");
|
|
pages.push(p);
|
|
await until("the room page ready", STEP, () => p.evaluate(() => window.roomTest && window.roomTest.state && window.roomTest.state.phase === "idle"), 200);
|
|
await p.click("#join");
|
|
const seen = await until("alice decodes the host's screen", STEP, async () => { const r = await remoteOf(p); return r && r.joined && r.screen && r.frames >= 5 && r; }, 250);
|
|
check("the page decodes the host's screen, each frame verified against its receipt first", seen.frames >= 5, `${seen.frames} frames, ${seen.screen.width} wide`);
|
|
check("the page made its key and holds a controller's grant the room service issued for it", seen.control > 0, `control ${seen.control}`);
|
|
await p.click("#remote-request");
|
|
await until("the host gives alice the floor", STEP, async () => { const r = await remoteOf(p); return r.holder === r.me; }, 200);
|
|
const box = await p.locator("#remote-canvas").boundingBox();
|
|
await p.mouse.click(box.x + box.width / 2, box.y + box.height / 2);
|
|
const done = await until("alice's click applied by the host", STEP, async () => { const r = await remoteOf(p); return r.counts.applied >= 1 && r; }, 250);
|
|
check("with the floor, the page's input reaches the host and is applied", done.counts.applied >= 1, `${done.counts.sent} sent, ${done.counts.applied} applied`);
|
|
} catch (e) {
|
|
check("the example ran to its end", false, (e && e.stack || String(e)).split("\n").slice(0, 3).join(" | "));
|
|
} finally {
|
|
dump(pages, out);
|
|
await browser.close().catch(() => {});
|
|
host.kill("SIGINT");
|
|
await d.stop();
|
|
}
|
|
finish("remote-desktop");
|