"""Pydantic request/response models for the API.""" from pydantic import BaseModel, Field # ── Auth ─────────────────────────────────────────────── class LoginRequest(BaseModel): id: str password: str class TokenResponse(BaseModel): access_token: str token_type: str = "bearer" class UserInfo(BaseModel): user_id: str is_admin: bool = False class CreateUserRequest(BaseModel): id: str = Field(min_length=1, max_length=50, pattern=r"^[A-Za-z0-9_.-]+$") password: str = Field(min_length=8, max_length=200) is_admin: bool = False class UpdateUserRequest(BaseModel): password: str | None = Field(default=None, min_length=8, max_length=200) is_admin: bool | None = None is_active: bool | None = None class UserSummary(BaseModel): id: str is_admin: bool is_active: bool created_at: str updated_at: str # ── LLM Config ─────────────────────────────────────── class LLMConfig(BaseModel): alias: str base_url: str api_key: str model: str context_size: int # ── Translation Session ──────────────────────────────── class ProperNoun(BaseModel): original: str # 원문 고유명사 suggested: str # 제안 번역 final: str = "" # 사용자 최종 결정 (Phase 2) class Phase1Result(BaseModel): translated: str # 초벌 번역 결과 proper_nouns: list[ProperNoun] # 추출된 고유명사 리스트 summary: str # 내용 요약 style: str # 문체 분석 결과 warnings: list[str] = Field(default_factory=list) class TranslationChunk(BaseModel): source_text: str translated: str class PhaseProgress(BaseModel): phase: int chunk: int total_chunks: int status: str preview: str = "" class TranslationSession(BaseModel): """Full translation session state.""" source_text: str = "" # 원문 source_language: str = "auto" # 출발어 (auto = 자동판단) target_language: str = "한국어" # 도착어 model_phase1: str = "" # Phase 1 LLM 모델 alias model_phase2: str = "" # Phase 2 LLM 모델 alias model_phase3: str = "" # Phase 3 LLM 모델 alias model_phase4: str = "" # Phase 4 LLM 모델 alias phase1_result: Phase1Result | None = None # 초벌 번역 결과 phase1_chunks: list[TranslationChunk] = Field(default_factory=list) phase2_proper_nouns: list[ProperNoun] = Field(default_factory=list) phase2_style: str = "" # Phase 2에서 최종 확정된 문체 phase2_confirmed: bool = False phase3_result: str = "" # 재번역 결과 phase3_chunks: list[str] = Field(default_factory=list) phase4_result: str = "" # 마무리 다듬기 결과 progress: PhaseProgress | None = None # 장기 작업 진행 상태 # ── API Requests ─────────────────────────────────────── class CreateSessionRequest(BaseModel): source_text: str source_language: str = "auto" target_language: str = "한국어" model_phase1: str = "" model_phase2: str = "" model_phase3: str = "" model_phase4: str = "" title: str | None = Field(default=None, max_length=120) class PhaseUpdateRequest(BaseModel): """Partial update for a specific phase.""" source_text: str | None = None source_language: str | None = None target_language: str | None = None model_phase1: str | None = None model_phase2: str | None = None model_phase3: str | None = None model_phase4: str | None = None title: str | None = Field(default=None, max_length=120) expected_version: int class Phase2ConfirmRequest(BaseModel): """User confirms or edits proper nouns and style for Phase 2.""" proper_nouns: list[ProperNoun] style: str expected_version: int # ── API Responses ────────────────────────────────────── class SessionResponse(BaseModel): session_id: str data: TranslationSession title: str = "" status: str = "draft" current_phase: int = 0 version: int = 0 created_at: str = "" updated_at: str = "" archived_at: str | None = None class SessionSummary(BaseModel): session_id: str title: str source_preview: str target_language: str status: str current_phase: int version: int created_at: str updated_at: str archived_at: str | None = None class RevisionResponse(BaseModel): data: TranslationSession reason: str created_at: str