This commit is contained in:
Mikan
2026-06-19 11:28:04 +03:00
commit 53c89829a8
80 changed files with 12482 additions and 0 deletions

View File

@@ -0,0 +1,238 @@
"""Pydantic schemas for API request/response."""
from __future__ import annotations
from datetime import datetime
from typing import Any, Dict, List, Optional
from uuid import UUID
from pydantic import BaseModel, ConfigDict, EmailStr, Field
# === Auth ===
class UserRegister(BaseModel):
email: EmailStr
username: str = Field(min_length=3, max_length=64)
password: str = Field(min_length=6, max_length=128)
class UserLogin(BaseModel):
email: EmailStr
password: str
class UserOut(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: UUID
email: EmailStr
username: str
is_admin: bool
is_active: bool
preferred_language: str
created_at: datetime
class TokenOut(BaseModel):
access_token: str
token_type: str = "bearer"
user: UserOut
class AdminSetupRequest(BaseModel):
token: str
email: EmailStr
username: str = Field(min_length=3, max_length=64)
password: str = Field(min_length=6, max_length=128)
# === Settings ===
class SettingsUpdate(BaseModel):
values: Dict[str, Any]
class SettingsOut(BaseModel):
values: Dict[str, Any]
editable_keys: List[str]
# === Presets ===
class PresetOut(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: UUID
slug: str
title: str
description: Optional[str] = None
language: str
is_public: bool
is_builtin: bool
payload: Dict[str, Any]
created_at: datetime
class PresetCreate(BaseModel):
slug: str
title: str
description: Optional[str] = None
language: str = "ru"
is_public: bool = True
payload: Dict[str, Any]
# === Worlds ===
class WorldCreate(BaseModel):
name: str = Field(min_length=1, max_length=255)
language: str = "ru"
preset_id: Optional[UUID] = None
class WorldDefinition(BaseModel):
setting_description: str = ""
rules: Dict[str, Any] = Field(default_factory=dict)
world_schema: Dict[str, Any] = Field(default_factory=dict)
plot_rails: Dict[str, Any] = Field(default_factory=dict)
initial_state: Dict[str, Any] = Field(default_factory=dict)
initial_time: Optional[str] = None
class WorldOut(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: UUID
owner_id: UUID
name: str
language: str
definition: Dict[str, Any]
state: Dict[str, Any]
current_time: Optional[str]
status: str
preset_id: Optional[UUID] = None
created_at: datetime
updated_at: datetime
class WorldUpdate(BaseModel):
name: Optional[str] = None
definition: Optional[Dict[str, Any]] = None
state: Optional[Dict[str, Any]] = None
current_time: Optional[str] = None
status: Optional[str] = None
# === World Builder ===
class WorldBuilderStart(BaseModel):
"""Kick off a new world-building conversation."""
world_name: str = Field(min_length=1, max_length=255)
language: str = "ru"
# Either pick a preset to start from, or fill the freeform brief.
preset_id: Optional[UUID] = None
setting_brief: str = ""
character_brief: str = ""
rules_brief: str = ""
notes: str = ""
class WorldBuilderMessage(BaseModel):
"""User reply in the world-builder dialogue."""
session_id: UUID
message: str
class WorldBuilderReply(BaseModel):
"""AI reply in the world-builder dialogue."""
session_id: UUID
turn: int
ai_message: str
proposed_definition: Optional[WorldDefinition] = None
is_final: bool = False # True when AI thinks world is ready to commit
followup_questions: List[str] = Field(default_factory=list)
class WorldBuilderCommit(BaseModel):
"""User accepts the proposed world definition and creates the world."""
session_id: UUID
name: Optional[str] = None
# === Sessions ===
class SessionOut(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: UUID
world_id: UUID
title: str
is_active: bool
created_at: datetime
last_played_at: Optional[datetime] = None
class SessionCreate(BaseModel):
world_id: UUID
title: Optional[str] = None
# === Messages ===
class MessageOut(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: UUID
seq: int
role: str
kind: str
content: str
payload: Dict[str, Any]
is_pinned: bool
hidden: bool
created_at: datetime
# === Iteration ===
class IterationRequest(BaseModel):
"""Player submits an action/choice for the next iteration."""
session_id: UUID
action_text: str = Field(min_length=1, max_length=4000)
class IterationEvent(BaseModel):
"""SSE event sent to the frontend during an iteration."""
type: str # status / plan / tool_call / tool_result / narrative_chunk / step_complete / error / done
data: Dict[str, Any] = Field(default_factory=dict)
# === Glossary ===
class GlossaryEntryOut(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: UUID
kind: str
name: str
description: str
payload: Dict[str, Any]
# === LLM Logs ===
class LlmLogOut(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: UUID
purpose: str
model: str
base_url: str
prompt_tokens: Optional[int]
completion_tokens: Optional[int]
total_tokens: Optional[int]
latency_ms: Optional[int]
error: Optional[str]
created_at: datetime
# === Triggers ===
class TriggerOut(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: UUID
session_id: UUID
fire_at: str
description: str
payload: Dict[str, Any]
fired: bool
created_at: datetime
class TriggerCreate(BaseModel):
session_id: UUID
fire_at: str
description: str
payload: Dict[str, Any] = Field(default_factory=dict)