"""辰正时态 API schema(设计 §10)。对外字段不带 _json 后缀。""" from pydantic import BaseModel, ConfigDict, Field from app.modules.time_sense.modulation import ModulationFactors from app.modules.time_sense.snapshot import TemporalSnapshot class SnapshotResponse(BaseModel): """GET /time/snapshot 响应:快照 + 因子 + context_text。""" model_config = ConfigDict(from_attributes=True) snapshot: TemporalSnapshot | None factors: ModulationFactors | None context_text: str class AnniversaryCreateRequest(BaseModel): model_config = ConfigDict( json_schema_extra={ "examples": [ { "name": "我们的相遇日", "calendar": "solar", "date": "2025-09-19", "recurs_yearly": True, "kind": "anniversary", "subject_type": "relationship", "source": "manual", } ] } ) name: str = Field(max_length=200, description="纪念日名称。") calendar: str = Field(description="历法:solar / lunar。") date: str = Field(description="日期:公历 ISO 或农历编码。") recurs_yearly: bool = Field(default=True, description="是否每年 recur。") kind: str = Field(description="类型,取值见契约 §11.4.2。") subject_type: str = Field(description="对象类型,取值见契约 §11.4.3。") source: str = Field(default="manual", description="来源,取值见契约 §11.4.4。") class AnniversaryUpdateRequest(BaseModel): name: str | None = Field(default=None, max_length=200) calendar: str | None = None date: str | None = None recurs_yearly: bool | None = None kind: str | None = None subject_type: str | None = None source: str | None = None class AnniversaryResponse(BaseModel): model_config = ConfigDict(from_attributes=True) id: str name: str calendar: str date: str recurs_yearly: bool kind: str subject_type: str source: str class AcquaintanceResponse(BaseModel): total_days: int natural_language: str class TimeConfigResponse(BaseModel): """GET /time/config:当前时态相关配置(只读,v1 经 env 覆盖)。""" user_timezone: str home_timezone: str default_city: str offline_active_minutes: float offline_short_absence_minutes: float offline_long_absence_minutes: float offline_reunion_impact_minutes: float care_enabled: bool jetlag_threshold_minutes: int