| """Pydantic request/response models for the GODSEED HTTP API. |
| |
| Shapes follow ARCHITECTURE.md §HTTP API exactly: |
| |
| GET /api/state -> StateResponse |
| POST /api/wish {text} -> WishAccepted (errors: 400/429/503 with a poetic `detail` string) |
| GET /api/wishes -> list[WishSummary] |
| GET /api/wishes/{id} -> raw WishTrace dict (passed through, engine-owned shape) |
| |
| Features and WishTraces are deliberately NOT strict models here: the engine owns those |
| shapes and the server passes them through untouched (the "her" pattern — transport never |
| reinterprets world facts). |
| """ |
|
|
| from __future__ import annotations |
|
|
| from typing import Any, Optional |
|
|
| from pydantic import BaseModel, ConfigDict, Field, field_validator |
|
|
| |
| |
| |
| TRANSPORT_MAX_WISH_CHARS = 2000 |
|
|
|
|
| class WishRequest(BaseModel): |
| """Body of POST /api/wish.""" |
|
|
| model_config = ConfigDict(str_strip_whitespace=True) |
|
|
| text: str = Field(..., min_length=1, max_length=TRANSPORT_MAX_WISH_CHARS) |
|
|
| @field_validator("text") |
| @classmethod |
| def _not_blank(cls, value: str) -> str: |
| if not value.strip(): |
| raise ValueError("a wish needs words") |
| return value.strip() |
|
|
|
|
| class WishAccepted(BaseModel): |
| """Response of POST /api/wish.""" |
|
|
| wish_id: str |
| position: int = Field(..., ge=1, description="1-based place in the queue") |
|
|
|
|
| class CurrentWish(BaseModel): |
| """The wish the god is granting right now.""" |
|
|
| wish_id: str |
| text_preview: str |
|
|
|
|
| class QueueInfo(BaseModel): |
| length: int = 0 |
| current: Optional[CurrentWish] = None |
|
|
|
|
| class WorldState(BaseModel): |
| """Snapshot of the deterministic world: ordered feature list + counters.""" |
|
|
| version: int = Field(..., ge=0, description="total number of features") |
| epoch: int = Field(..., ge=0, description="number of granted wishes") |
| features: list[dict[str, Any]] |
|
|
|
|
| class WishSummary(BaseModel): |
| """One row of the Genesis Log index (GET /api/wishes).""" |
|
|
| wish_id: str |
| text: str |
| epitaph: str = "" |
| epoch: int |
| ts: float |
|
|
|
|
| class StateResponse(BaseModel): |
| """GET /api/state.""" |
|
|
| world: WorldState |
| queue: QueueInfo |
| wishes_recent: list[WishSummary] |
|
|