from typing import Any, Literal from pydantic import BaseModel, Field class SceneAnalyzeRequest(BaseModel): timestamp: int audio_blob: str = Field(description="Base64 encoded audio or placeholder") device_id: str context_hints: dict[str, Any] = Field(default_factory=dict) class SceneAnalyzeResponse(BaseModel): scene: str confidence: float greeting_strategy: Literal["contextual", "generic"] suggested_intent: str class DialogueStreamPayload(BaseModel): dialogue_id: str text: str audio_url: str | None = None intent_type: str difficulty_level: str class MqttHeader(BaseModel): version: str | None = None device_id: str req_id: str | None = None timestamp: int ttl: int | None = None class MqttCommand(BaseModel): header: MqttHeader action: str payload: dict[str, Any] = Field(default_factory=dict) class MqttReport(BaseModel): header: MqttHeader msg_type: Literal["state", "event", "log", "ack", "progress"] payload: dict[str, Any] = Field(default_factory=dict) class DeviceState(BaseModel): device_id: str cpu: float | None = None mem: float | None = None battery: float | None = None net: str | None = None mode: str | None = None last_seen: int class InitTaskRequest(BaseModel): device_id: str course_id: str | None = None force: bool = False