Skip to content

Latest commit

 

History

History
203 lines (154 loc) · 8.83 KB

File metadata and controls

203 lines (154 loc) · 8.83 KB

SideQuest API

Rust game engine for the SideQuest AI Narrator -- a tabletop RPG engine where coordinated Claude agents run the game. Ported from Python (sq-2).

Players connect via WebSocket. Seven Claude agents collaborate as the game master: narrating scenes, building worlds, creating creatures, managing dialogue, and routing player intent. The ML stack (image generation, audio mixing) stays in Python as a sidecar daemon.

Architecture

React Client (sidequest-ui)
    |                                |
    | WebSocket /ws                  | REST /api/*
    v                                v
+------------------------------------------------+
|  sidequest-server                              |
|  axum HTTP/WS, session lifecycle, CORS,        |
|  structured tracing, watcher telemetry         |
+------------------------+-----------------------+
                         | GameService trait
                         v
+------------------------------------------------+
|  sidequest-agents                              |
|  7 agents, orchestrator state machine,         |
|  ClaudeClient, prompt framework, JSON extract  |
+------------+-------------------+---------------+
             |                   |
             v                   v
+--------------------+  +--------------------+  +---------------------------+
| sidequest-game     |  | sidequest-genre    |  | sidequest-daemon-client   |
| GameSnapshot, NPCs,|  | YAML pack loader,  |  | Unix socket client for    |
| combat, chase,     |  | trope inheritance,  |  | Python media daemon       |
| persistence, turns |  | name gen, cache    |  | (JSON-RPC)                |
+---------+----------+  +---------+----------+  +---------------------------+
          |                       |
          +-----------+-----------+
                      |
          +-----------+-----------+-----------+
          v                       v           v
+--------------------+  +---------------+  +---------------+  +---------------+
| sidequest-protocol |  | encountergen  |  | loadoutgen    |  | namegen       |
| GameMessage enum,  |  | CLI: enemy    |  | CLI: starting |  | CLI: NPC      |
| newtypes, sanitize |  | stat blocks   |  | equipment     |  | identity      |
+--------------------+  +---------------+  +---------------+  +---------------+

Crates

sidequest-protocol -- COMPLETE

Communication protocol between UI and server. Defines the GameMessage enum, typed payloads for every message type, input sanitization, and newtype wrappers for domain IDs.

Depends on: nothing

sidequest-genre -- COMPLETE

YAML genre pack loader and narrative models. Handles pack loading and validation, trope inheritance resolution, name generation (Markov chains + template blending), and a genre cache for hot-reloading packs at runtime.

Depends on: protocol

sidequest-game -- 95% COMPLETE

Core game state engine. 59 modules (~23.7k LOC) covering:

  • GameSnapshot -- composable game state
  • Characters/NPCs -- full model with inventory, abilities, disposition
  • Combat -- classification, resolution, turn management
  • Chase -- cinematic chase engine (ADR-017)
  • Turn modes -- exploration, combat, chase, character creation
  • Session lifecycle -- start, save, load, resume
  • Persistence -- SQLite via rusqlite
  • Character builder -- state machine (ADR-015)
  • Tension tracker -- dual-track model (ADR-024)
  • Beat filter, render queue -- pacing control (ADR-025)
  • Music director, audio mixer, voice router -- cinematic audio cues and pre-rendered music selection
  • Multiplayer, guest NPC -- concurrent player sessions
  • Lore store, conlang -- knowledge indexing and constructed languages
  • Prerender scheduler -- speculative image rendering between narration turns

One module stubbed: perception.rs (RED phase, story 8-6).

Depends on: protocol, genre

sidequest-agents -- COMPLETE

Claude CLI subprocess orchestration. All LLM calls go through claude -p as a Tokio subprocess, never through the Anthropic SDK (ADR-001).

5 agents (post ADR-067): Narrator (unified — exploration/combat/chase/dialogue), WorldBuilder, Troper, Resonator, IntentRouter. CreatureSmith, Ensemble, and Dialectician were absorbed into Narrator via conditional prompt sections.

Infrastructure:

  • Orchestrator -- GameService trait, agent state machine
  • ClaudeClient -- subprocess management, timeout handling
  • Prompt framework -- attention zones (EARLY/VALLEY/LATE) (ADR-009)
  • JSON extractor -- 3-tier fallback (ADR-013)
  • Context builder, turn record telemetry, patch legality, entity tracking

Depends on: protocol, game

sidequest-server -- COMPLETE

axum HTTP/WebSocket server. REST endpoints for save/load, character listing, genre pack metadata. WebSocket at /ws for real-time game events. Includes session lifecycle, CORS, structured tracing via tracing-subscriber, a /watcher endpoint for telemetry (ADR-031), and graceful shutdown.

Depends on: all other crates

sidequest-daemon-client -- COMPLETE

Unix socket client for the Python media daemon (sidequest-daemon). JSON-RPC protocol for image generation and embedding requests. Typed request/response structs with error handling.

Depends on: protocol

sidequest-encountergen -- COMPLETE

CLI binary that generates enemy stat blocks from genre pack data. Produces culture-appropriate names (Markov chains), class/archetype stats, HP, abilities, weaknesses, OCEAN personality, trope connections, and visual prompts.

Depends on: genre

sidequest-loadoutgen -- COMPLETE

CLI binary that generates starting equipment sets from genre pack inventory catalogs. Resolves items, applies tier scaling, and generates narrative hooks.

Depends on: genre

sidequest-namegen -- COMPLETE

CLI binary that generates complete NPC identity blocks from genre pack data. Culture-appropriate names, archetype personality, OCEAN profile, dialogue quirks, inventory hints, and trope connections.

Depends on: genre

Build and Test

cargo build                           # Build all 9 crates
cargo test                            # Run all tests (182 test files)
cargo clippy -- -D warnings           # Lint
cargo fmt -- --check                  # Format check
cargo run -p sidequest-server         # Run the server

Requires Rust 1.80+ (edition 2021). See rust-toolchain.toml for the pinned version.

Key Design Decisions

Decision Rationale ADR
Claude CLI only Subprocess calls (claude -p), not the SDK. Simpler auth, observable, debuggable. 001
GameService facade Server depends on a trait, never on game internals. Keeps axum layer thin and testable. --
JSON delta patches Agents emit state patches, not full state replacements. Bandwidth-efficient, auditable. 011
Genre packs as YAML Runtime-swappable narrative configuration. Any genre, any setting. 003
Graceful degradation Agent timeouts produce degraded responses instead of errors. The game never crashes. 006
Attention-aware prompts Prompt zones (EARLY/VALLEY/LATE) place critical context where the LLM pays attention. 009
3-tier JSON extraction Regex, then partial parse, then re-prompt. Handles malformed LLM output. 013
Story-driven testing Tests named by feature story (e.g., combat_classification_story_5_2_tests.rs). --

All ADRs live in the orchestrator at docs/adr/.

Python Equivalents

For developers coming from the Python codebase:

Python (sq-2) Rust (this repo)
Pydantic models serde structs
asyncio tokio
aiohttp axum
pyyaml serde_yaml
sqlite3 rusqlite
subprocess.run(["claude", "-p", ...]) tokio::process::Command

Related Repos

Git Workflow

Default branch: develop (gitflow). Feature branches: feat/{description}. PRs target develop.