"""API 层 Pydantic 请求体。 注意:``/api/chat`` 本身**没有** Pydantic 请求体——它是 multipart/form-data (为了带文件上传),字段用 FastAPI 的 ``Form``/``File`` 声明。1.5 也是这个 形状,保持一致以免前端要改。本文件只放 JSON 体的接口模型。 """ from __future__ import annotations from typing import Any from pydantic import BaseModel, Field class ResumeRequest(BaseModel): """中断恢复请求(字段与 1.5 逐字对齐)。 2.0 内部把它翻译成官方 HITL 的 ``{"decisions": [...]}``,翻译逻辑见 ``api/chat_routes._to_official_resume``。 """ session_id: str = Field(..., description="会话 ID") thread_id: str | None = Field(None, description="LangGraph 线程 ID(服务端强制等于 session_id)") answers: list[str] | None = Field( None, description="提问卡的用户答案列表(与问题一一对应)" ) status: str = Field( "answered", description="响应状态:answered / cancelled / error" ) error: str | None = Field(None, description="错误详情(status=error 时可选)") approved: bool | None = Field(None, description="工具审批:是否批准本次工具调用") remember: bool = Field( False, description="工具审批:是否长期允许(2.0 骨架未实现长期规则,收到即忽略)" ) user_name: str | None = Field(None, description="归属用户,缺省 default") class ModeUpdateRequest(BaseModel): """会话权限模式。""" mode: str = Field(..., description="plan | full") class PinUpdateRequest(BaseModel): """会话置顶。""" pinned: bool = Field(..., description="是否置顶") class TitleUpdateRequest(BaseModel): """会话标题。""" title: str = Field(..., max_length=255, description="新标题") class ThinkingUpdateRequest(BaseModel): """思考级别切换。""" level: str = Field(..., description="off | high | highest") class PreferenceRequest(BaseModel): """用户偏好写入。""" key: str = Field(..., max_length=128, description="偏好键") value: str = Field(..., description="偏好值") class ScheduleCreateRequest(BaseModel): """新建定时任务。""" title: str = Field("", max_length=255, description="任务标题") cron: str = Field(..., max_length=64, description="5 段 cron 表达式,如 '0 9 * * *'") prompt: str = Field(..., description="触发时喂给 agent 的指令") mode: str = Field("full", description="plan | full") enabled: bool = Field(True, description="是否立即启用") user_name: str | None = Field(None, description="归属用户,缺省 default") class ScheduleUpdateRequest(BaseModel): """更新定时任务(只传要改的字段)。""" title: str | None = Field(None, max_length=255) cron: str | None = Field(None, max_length=64) prompt: str | None = None mode: str | None = None enabled: bool | None = None class QuotaUpdateRequest(BaseModel): """调整每日额度。""" user_name: str | None = Field(None, description="归属用户,缺省 default") limit_tokens: int = Field(..., ge=0, description="每日 token 上限,0 = 不限") class ErrorPayload(BaseModel): """错误响应的统一载荷(与 1.5 的 {code,message} 契约一致)。""" code: str message: str detail: dict[str, Any] | None = None