Spaces:
Running
Reachy Tales β Continuation Guide
Voice-driven story adventures for Reachy Mini. Pure-TS story-engine library + JS HF Space app.
Status
- Plan: docs/superpowers/plans/2026-04-29-reachy-tales.md β 28 tasks, all done.
- Spec: docs/superpowers/specs/2026-04-29-reachy-tales-design.md.
- 44 tests pass (41 engine + 3 bridge).
npm run buildclean (~72 KB JS).
Layout
- packages/story-engine/ β pure-TS library, no DOM/robot/LLM deps. Public API in src/index.ts.
- src/ β Vite app. src/story-bridge.ts wires the engine to OpenAI Realtime + the Reachy Mini JS SDK.
- content/ β translated English story data (
narrator/,story_pirates/). Schema: content/SCHEMA.md. - tests/ β bridge integration test (root), uses Vitest with vitest.config.app.ts.
- Dockerfile + nginx.conf β multistage build; nginx proxies
/openai/v1/*to api.openai.com.
Commands
npm install
npm test --workspace story-engine # 41 engine tests
npm run test:app # 3 bridge tests
npm run test:all # both
npm run dev # http://localhost:5173
npm run build # tsc + vite build β dist/
Reachy Mini SDK
Pinned to v1.7.0 via jsDelivr CDN in src/main.ts. Upstream:
- Repo: https://github.com/pollen-robotics/reachy_mini
- AGENTS.md (read this before changing SDK integration): https://github.com/pollen-robotics/reachy_mini/blob/main/AGENTS.md
- JS lib source: https://github.com/pollen-robotics/reachy_mini/blob/main/js/reachy-mini.js
- Reference conversation app (plumbing was copied from here): https://huggingface.co/spaces/tfrere/reachy-mini-minimal-js-conversation-app
Adaptations from spec β read before changing the bridge
OpenaiRealtimeClientAPI differs from the plan's draft: event-based viaon(), noupdateSession(), returns tool results viasendToolResponse(callId, output). The bridge restarts the session on every story transition (not just voice changes) β visible as a small audio gap. To eliminate, add asession.updateevent-send path in src/openai-realtime.ts and use it when the voice doesn't change.- App-side tsconfig.app.json disables
noUncheckedIndexedAccessbecause the copied reference plumbing (src/move-player.ts, src/head-wobbler.ts) does matrix math with direct array indexing. The engine workspace keeps the strict setting. exactOptionalPropertyTypesis on. Engine code uses conditional spreads (...(v !== undefined && { k: v })) instead of literalundefinedassignments β see packages/story-engine/src/loader.ts and packages/story-engine/src/engine.ts.
Untested (require physical infra)
docs/playtest.md is the v1 acceptance checklist. None of those items have been verified β they need a real Reachy Mini, an OpenAI Realtime key, and a browser. CI does not cover them.
Open content gaps
content/story_pirates/storylines/chapter1/ has 17 nodes. The original French source referenced 28 follow-up nodes that were never authored. Those action.next refs were stripped during translation review. To extend the story, author the missing follow-up nodes β many leaf nodes have actions: [] as a result.
HF Space deployment
The Space at https://huggingface.co/spaces/Nico-robot/reachy-tales is the only remote. To deploy a change:
git push hf main # the `hf` remote was added by the initial create
The Space auto-builds the Docker image (~1β2 min) and serves on the HF-assigned URL. Logs visible in the Space UI.
If hf remote is missing on a fresh clone:
git remote add hf https://huggingface.co/spaces/Nico-robot/reachy-tales
To recreate the Space from scratch (one-time):
hf auth login # if not authed
hf repos create reachy-tales --repo-type space --space-sdk docker
git remote add hf https://huggingface.co/spaces/Nico-robot/reachy-tales
git push -u hf main