societysim / devui /schema /play_api.schema.json
polter-dev's picture
Deploy viewer and games (part 2)
92799f3 verified
Raw History Blame Contribute Delete
17.1 kB
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "play_api.schema.json",
"x-contract-version": 1,
"x-endpoints": {
"POST /api/games": {
"request": "StartGame",
"response": "StartedGame"
},
"GET /api/games/{id}/me": {
"auth": "seat_token",
"response": "Me"
},
"POST /api/games/{id}/action": {
"auth": "seat_token",
"request": "ActionBody",
"response": "Accepted"
},
"POST /api/games/{id}/leave": {
"auth": "seat_token or watch_token",
"response": "Accepted"
},
"GET /api/limits": {
"response": "Limits"
},
"GET /api/health": {
"response": "Health"
}
},
"x-error": "Error",
"$defs": {
"Accepted": {
"additionalProperties": false,
"properties": {
"accepted": {
"const": true,
"default": true,
"title": "Accepted",
"type": "boolean"
}
},
"title": "Accepted",
"type": "object"
},
"ActionBody": {
"additionalProperties": false,
"description": "POST /api/games/{id}/action: the `action` shape for `pending_action.kind`\n(agents/schemas.py). Statement text and wolf chat messages: 1 to 280 characters after\ncontrol characters are stripped. `private_reasoning` is optional: players left out of\n`suspicion` are logged as not rated, and `thoughts` is not logged.",
"properties": {
"private_reasoning": {
"anyOf": [
{
"$ref": "#/$defs/HumanReasoning"
},
{
"type": "null"
}
],
"default": null
},
"action": {
"anyOf": [
{
"$ref": "#/$defs/StatementAction"
},
{
"$ref": "#/$defs/VoteAction"
},
{
"$ref": "#/$defs/WolfChatAction"
},
{
"$ref": "#/$defs/TargetAction"
}
],
"title": "Action"
}
},
"required": [
"action"
],
"title": "ActionBody",
"type": "object"
},
"Error": {
"additionalProperties": false,
"description": "Every error response: a fixed code, and a message safe to show the visitor.",
"properties": {
"error": {
"enum": [
"rate_limited",
"too_many_games_today",
"active_game_exists",
"at_capacity",
"bot_check_failed",
"forbidden",
"budget_exhausted",
"play_disabled",
"invalid_request",
"not_your_turn",
"game_not_found",
"unauthorized",
"payload_too_large",
"internal_error"
],
"title": "Error",
"type": "string"
},
"message": {
"title": "Message",
"type": "string"
}
},
"required": [
"error",
"message"
],
"title": "Error",
"type": "object"
},
"GameSetup": {
"additionalProperties": false,
"description": "One game's settings. Every default is the Basic setup.\n\nValidate with `GameSetup.model_validate(data)`; model names are checked against\nconfigs/models.yaml unless `context={\"models\": {...}}` gives another set.",
"properties": {
"mode": {
"default": "basic",
"description": "basic allows only seed and human_seat to change.",
"enum": [
"basic",
"advanced"
],
"title": "Mode",
"type": "string"
},
"n_players": {
"default": 10,
"maximum": 10,
"minimum": 7,
"title": "N Players",
"type": "integer"
},
"n_wolves": {
"default": 2,
"description": "Must be fewer than the villager side.",
"minimum": 1,
"title": "N Wolves",
"type": "integer"
},
"special_roles": {
"$ref": "#/$defs/SpecialRoles",
"default": {
"seer": true,
"doctor": true
}
},
"seats": {
"anyOf": [
{
"items": {
"$ref": "#/$defs/SeatModel"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"description": "One entry per seat p0..p{n_players-1}. Excludes model_pool.",
"title": "Seats"
},
"model_pool": {
"anyOf": [
{
"items": {
"type": "string"
},
"minItems": 1,
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"description": "Models to fill the seats from; null means the default lineup.",
"title": "Model Pool"
},
"rotation": {
"default": "shuffle",
"description": "How model_pool fills the model seats: in_order repeats the pool from p0; shuffle first shuffles the pool with the seed.",
"enum": [
"in_order",
"shuffle"
],
"title": "Rotation",
"type": "string"
},
"human_seat": {
"anyOf": [
{
"pattern": "^p[0-9]$",
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The seat a person plays, or null.",
"title": "Human Seat"
},
"seed": {
"title": "Seed",
"type": "integer"
}
},
"title": "GameSetup",
"type": "object"
},
"Health": {
"additionalProperties": false,
"properties": {
"ok": {
"const": true,
"default": true,
"title": "Ok",
"type": "boolean"
},
"providers_ready": {
"additionalProperties": {
"type": "boolean"
},
"title": "Providers Ready",
"type": "object"
},
"games_running": {
"title": "Games Running",
"type": "integer"
}
},
"required": [
"providers_ready",
"games_running"
],
"title": "Health",
"type": "object"
},
"HumanReasoning": {
"additionalProperties": false,
"description": "A visitor's optional scratchpad. `thoughts` is not logged; `suspicion` may rate any of\nthe other living players, or none.",
"properties": {
"thoughts": {
"default": "",
"title": "Thoughts",
"type": "string"
},
"suspicion": {
"default": [],
"items": {
"$ref": "#/$defs/SuspicionEntry"
},
"title": "Suspicion",
"type": "array"
}
},
"title": "HumanReasoning",
"type": "object"
},
"Limits": {
"additionalProperties": false,
"properties": {
"play_enabled": {
"title": "Play Enabled",
"type": "boolean"
},
"remaining_today": {
"title": "Remaining Today",
"type": "integer"
},
"client_ip_hint": {
"title": "Client Ip Hint",
"type": "string"
},
"allowed_models": {
"items": {
"type": "string"
},
"title": "Allowed Models",
"type": "array"
}
},
"required": [
"play_enabled",
"remaining_today",
"client_ip_hint",
"allowed_models"
],
"title": "Limits",
"type": "object"
},
"Me": {
"additionalProperties": false,
"description": "GET /api/games/{id}/me: what the seat knows, nothing more.",
"properties": {
"game_id": {
"title": "Game Id",
"type": "string"
},
"status": {
"enum": [
"running",
"finished",
"forfeit",
"failed"
],
"title": "Status",
"type": "string"
},
"winner": {
"anyOf": [
{
"enum": [
"wolves",
"villagers",
"draw"
],
"type": "string"
},
{
"type": "null"
}
],
"title": "Winner"
},
"seat": {
"pattern": "^p[0-9]$",
"title": "Seat",
"type": "string"
},
"name": {
"title": "Name",
"type": "string"
},
"role": {
"$ref": "#/$defs/Role"
},
"alive": {
"title": "Alive",
"type": "boolean"
},
"day": {
"title": "Day",
"type": "integer"
},
"phase": {
"$ref": "#/$defs/Phase"
},
"observation": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Observation"
},
"pending_action": {
"anyOf": [
{
"$ref": "#/$defs/PendingAction"
},
{
"type": "null"
}
]
},
"players": {
"items": {
"$ref": "#/$defs/Player"
},
"title": "Players",
"type": "array"
}
},
"required": [
"game_id",
"status",
"winner",
"seat",
"name",
"role",
"alive",
"day",
"phase",
"observation",
"pending_action",
"players"
],
"title": "Me",
"type": "object"
},
"PendingAction": {
"additionalProperties": false,
"properties": {
"kind": {
"enum": [
"statement",
"vote",
"wolf_chat",
"lone_wolf",
"seer",
"doctor"
],
"title": "Kind",
"type": "string"
},
"targets": {
"items": {
"type": "string"
},
"title": "Targets",
"type": "array"
},
"others": {
"items": {
"type": "string"
},
"title": "Others",
"type": "array"
},
"deadline": {
"title": "Deadline",
"type": "number"
}
},
"required": [
"kind",
"targets",
"others",
"deadline"
],
"title": "PendingAction",
"type": "object"
},
"Phase": {
"enum": [
"setup",
"night",
"day",
"vote"
],
"title": "Phase",
"type": "string"
},
"Player": {
"additionalProperties": false,
"properties": {
"seat": {
"pattern": "^p[0-9]$",
"title": "Seat",
"type": "string"
},
"name": {
"title": "Name",
"type": "string"
},
"alive": {
"title": "Alive",
"type": "boolean"
}
},
"required": [
"seat",
"name",
"alive"
],
"title": "Player",
"type": "object"
},
"Role": {
"enum": [
"wolf",
"seer",
"doctor",
"villager"
],
"title": "Role",
"type": "string"
},
"SeatModel": {
"additionalProperties": false,
"properties": {
"seat": {
"pattern": "^p[0-9]$",
"title": "Seat",
"type": "string"
},
"model": {
"description": "A model name from models_catalog.json, or 'human'.",
"title": "Model",
"type": "string"
}
},
"required": [
"seat",
"model"
],
"title": "SeatModel",
"type": "object"
},
"SeerReport": {
"additionalProperties": false,
"properties": {
"target": {
"title": "Target",
"type": "string"
},
"result": {
"enum": [
"wolf",
"not_wolf"
],
"title": "Result",
"type": "string"
},
"night": {
"title": "Night",
"type": "integer"
}
},
"required": [
"target",
"result",
"night"
],
"title": "SeerReport",
"type": "object"
},
"SpecialRoles": {
"additionalProperties": false,
"properties": {
"seer": {
"default": true,
"title": "Seer",
"type": "boolean"
},
"doctor": {
"default": true,
"title": "Doctor",
"type": "boolean"
}
},
"title": "SpecialRoles",
"type": "object"
},
"StartGame": {
"additionalProperties": false,
"description": "POST /api/games. The server draws the seed; human_seat defaults to p0 unless watching.",
"properties": {
"setup": {
"$ref": "#/$defs/GameSetup"
},
"turnstile_token": {
"default": "",
"maxLength": 2048,
"title": "Turnstile Token",
"type": "string"
},
"watch_only": {
"default": false,
"title": "Watch Only",
"type": "boolean"
}
},
"title": "StartGame",
"type": "object"
},
"StartedGame": {
"additionalProperties": false,
"properties": {
"game_id": {
"title": "Game Id",
"type": "string"
},
"seat": {
"anyOf": [
{
"pattern": "^p[0-9]$",
"type": "string"
},
{
"type": "null"
}
],
"title": "Seat"
},
"seat_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Seat Token"
},
"watch_token": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"title": "Watch Token"
}
},
"required": [
"game_id",
"seat",
"seat_token"
],
"title": "StartedGame",
"type": "object"
},
"StatementAction": {
"additionalProperties": false,
"properties": {
"text": {
"title": "Text",
"type": "string"
},
"accuse": {
"items": {
"type": "string"
},
"title": "Accuse",
"type": "array"
},
"claim_role": {
"anyOf": [
{
"$ref": "#/$defs/Role"
},
{
"type": "null"
}
]
},
"seer_report": {
"anyOf": [
{
"$ref": "#/$defs/SeerReport"
},
{
"type": "null"
}
]
}
},
"required": [
"text",
"accuse",
"claim_role",
"seer_report"
],
"title": "StatementAction",
"type": "object"
},
"SuspicionEntry": {
"additionalProperties": false,
"properties": {
"player": {
"title": "Player",
"type": "string"
},
"p": {
"title": "P",
"type": "number"
}
},
"required": [
"player",
"p"
],
"title": "SuspicionEntry",
"type": "object"
},
"TargetAction": {
"additionalProperties": false,
"properties": {
"target": {
"title": "Target",
"type": "string"
}
},
"required": [
"target"
],
"title": "TargetAction",
"type": "object"
},
"VoteAction": {
"additionalProperties": false,
"properties": {
"vote": {
"title": "Vote",
"type": "string"
}
},
"required": [
"vote"
],
"title": "VoteAction",
"type": "object"
},
"WolfChatAction": {
"additionalProperties": false,
"properties": {
"message": {
"title": "Message",
"type": "string"
},
"proposed_target": {
"title": "Proposed Target",
"type": "string"
}
},
"required": [
"message",
"proposed_target"
],
"title": "WolfChatAction",
"type": "object"
}
}
}