"""Pydantic models for the Transcription system.""" from pydantic import BaseModel, Field from typing import Optional, List from datetime import datetime # --- Session Models --- class TranscriptionSessionCreate(BaseModel): user_id: str title: Optional[str] = None canvas_type: str = "teaching-canvas" class TranscriptionSessionUpdate(BaseModel): title: Optional[str] = None ended_at: Optional[datetime] = None timetable_period_id: Optional[str] = None timetable_event_type: Optional[str] = None timetable_event_label: Optional[str] = None auto_tagged: Optional[bool] = None llm_provider: Optional[str] = None llm_model: Optional[str] = None class TranscriptionSessionResponse(BaseModel): id: str user_id: str title: Optional[str] = None canvas_type: str started_at: datetime ended_at: Optional[datetime] = None duration_seconds: Optional[int] = None timetable_period_id: Optional[str] = None timetable_event_type: Optional[str] = None timetable_event_label: Optional[str] = None auto_tagged: bool = False llm_provider: Optional[str] = None llm_model: Optional[str] = None word_count: int = 0 segment_count: int = 0 metadata: dict = {} created_at: datetime updated_at: datetime class Config: from_attributes = True class SessionListResponse(BaseModel): sessions: List[TranscriptionSessionResponse] total: int page: int page_size: int # --- Segment Models --- class TranscriptionSegmentCreate(BaseModel): session_id: str sequence_index: int text: str start_seconds: float end_seconds: float is_final: bool = True speaker_label: Optional[str] = None keyword_matches: Optional[List[str]] = None class TranscriptionSegmentResponse(BaseModel): id: str session_id: str sequence_index: int text: str start_seconds: float end_seconds: float is_final: bool = True speaker_label: Optional[str] = None keyword_matches: Optional[List[str]] = None created_at: datetime class Config: from_attributes = True # --- Canvas Event Models --- class CanvasEventCreate(BaseModel): session_id: Optional[str] = None user_id: str timestamp: Optional[datetime] = None session_elapsed_seconds: Optional[float] = None event_type: str event_payload: dict = {} canvas_snapshot_url: Optional[str] = None tldraw_page_id: Optional[str] = None tldraw_shape_ids: Optional[List[str]] = None class CanvasEventResponse(BaseModel): id: str session_id: Optional[str] = None user_id: str timestamp: datetime session_elapsed_seconds: Optional[float] = None event_type: str event_payload: dict = {} canvas_snapshot_url: Optional[str] = None tldraw_page_id: Optional[str] = None tldraw_shape_ids: Optional[List[str]] = None class Config: from_attributes = True # --- Summary Models --- class SummaryGenerateRequest(BaseModel): summary_type: str # full_lesson, questions_asked, teaching_style, key_moments, segment provider: str # anthropic, openai, ollama, openrouter, google model: str api_key: str # from frontend user settings, passed per-request segment_range: Optional[List[Optional[int]]] = None # [start, end], null = all include_canvas_snapshots: bool = False class SummaryResponse(BaseModel): id: str session_id: str user_id: str summary_type: str content: str prompt_used: Optional[str] = None llm_provider: str llm_model: str input_tokens: Optional[int] = None output_tokens: Optional[int] = None segment_range_start: Optional[int] = None segment_range_end: Optional[int] = None canvas_snapshot_urls: Optional[List[str]] = None created_at: datetime class Config: from_attributes = True # --- Keyword Watch Models --- class KeywordWatchCreate(BaseModel): user_id: str keyword: str match_type: str = "contains" # contains, exact, starts_with, regex action: str = "log" # log, alert, canvas_shape, webhook class KeywordWatchResponse(BaseModel): id: str user_id: str keyword: str match_type: str = "contains" action: str = "log" is_active: bool = True created_at: datetime class Config: from_attributes = True # --- Keyword Event Models --- class KeywordEventCreate(BaseModel): session_id: str segment_id: Optional[str] = None keyword_watch_id: Optional[str] = None keyword_text: str matched_in_text: str session_elapsed_seconds: Optional[float] = None class KeywordEventResponse(BaseModel): id: str session_id: str segment_id: Optional[str] = None keyword_watch_id: Optional[str] = None keyword_text: str matched_in_text: str session_elapsed_seconds: Optional[float] = None created_at: datetime class Config: from_attributes = True # --- Export Models --- class ExportFormat(BaseModel): format: str # srt, txt, json # --- Timetable Models --- class CurrentPeriodResponse(BaseModel): period_id: Optional[str] = None event_type: Optional[str] = None event_label: Optional[str] = None start_time: Optional[datetime] = None end_time: Optional[datetime] = None