Files
life-echo/api/app/features/memoir/schemas.py
Sully 53e0065e3e refactor(api): TOML 配置 SSOT、统一错误契约、Auth/事务加固与可观测性 (#33)
配置 SSOT(TOML + .env)
统一错误契约
Auth 与事务边界
Redis / Celery 可靠性:业务 Redis(DB/0)与 Celery broker/backend(DB/1)显式拆分;连接池、sync client
可观测性(OpenTelemetry + LGTM)
2026-05-22 13:44:50 +08:00

130 lines
3.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from pydantic import BaseModel, ConfigDict, Field
from app.agents.state_schema import MemoirStateSchema as MemoirStateResponse
__all__ = [
"BookResponse",
"ChapterDetailResponse",
"ChapterListItemResponse",
"CoverGenerationResponse",
"ExportPdfRequest",
"ExportPdfResponse",
"ImageAssetResponse",
"MemoirStateResponse",
"NextQuestionContextResponse",
"ReadingSegmentResponse",
"SetChapterStoryOrderRequest",
"StatusMessageResponse",
"StoryOrderResponse",
"UpdateBookRequest",
]
class ImageAssetResponse(BaseModel):
placeholder: str = ""
description: str = ""
index: int = 0
status: str = "pending"
prompt: str | None = None
url: str | None = None
provider: str | None = None
style: str | None = None
size: str | None = None
error: str | None = None
retryable: bool | None = None
created_at: str | None = None
updated_at: str | None = None
class ReadingSegmentResponse(BaseModel):
story_id: str
body_markdown: str = ""
cover_asset: ImageAssetResponse | None = None
class UpdateBookRequest(BaseModel):
title: str
subtitle: str | None = None
class ExportPdfRequest(BaseModel):
book_id: str
class SetChapterStoryOrderRequest(BaseModel):
"""按顺序绑定本章节要收录的 stories覆盖原有 chapter_story_links"""
story_ids: list[str]
class BookResponse(BaseModel):
id: str | None = None
title: str | None = None
total_pages: int | None = None
total_words: int | None = None
cover_image_url: str | None = None
has_update: bool | None = None
last_update_chapter_id: str | None = None
message: str | None = None
class StatusMessageResponse(BaseModel):
status: str
message: str | None = None
class ExportPdfResponse(BaseModel):
pdf_base64: str
filename: str
class ChapterListItemResponse(BaseModel):
model_config = ConfigDict(extra="ignore")
id: str
title: str | None = None
category: str | None = None
order_index: int | None = None
status: str = "draft"
summary: str = ""
canonical_markdown: str = ""
cover_asset: ImageAssetResponse | None = None
images: list[ImageAssetResponse] = Field(default_factory=list)
word_count: int = 0
updated_at: str | None = None
is_new: bool = False
source_segments: list[str] = Field(default_factory=list)
class ChapterDetailResponse(BaseModel):
model_config = ConfigDict(extra="ignore")
id: str
title: str | None = None
canonical_markdown: str = ""
order_index: int | None = None
status: str | None = None
category: str | None = None
images: list[ImageAssetResponse] = Field(default_factory=list)
cover_asset: ImageAssetResponse | None = None
reading_segments: list[ReadingSegmentResponse] = Field(default_factory=list)
updated_at: str | None = None
is_new: bool = False
source_segments: list[str] = Field(default_factory=list)
class CoverGenerationResponse(BaseModel):
triggered: list[str] = Field(default_factory=list)
class StoryOrderResponse(BaseModel):
status: str
chapter_id: str
story_count: int
class NextQuestionContextResponse(BaseModel):
current_stage: str | None = None
empty_slots: list[str] = Field(default_factory=list)
covered_stages: list[str] = Field(default_factory=list)