"""聊天 API schema。""" from typing import Any from pydantic import BaseModel, ConfigDict, Field class CreateSessionRequest(BaseModel): model_config = ConfigDict( json_schema_extra={ "examples": [ { "title": "大模型联调会话", "character_id": "character_ec83d55746c54e47ab6f98d683032626", } ] } ) title: str | None = Field(default=None, max_length=200, description="会话标题。") character_id: str | None = Field(default=None, description="人物 ID;为空时使用当前激活人物。") class UpdateSessionRequest(BaseModel): model_config = ConfigDict( json_schema_extra={ "examples": [ {"title": "新的会话标题"}, {"status": "archived"}, ] } ) title: str | None = Field(default=None, max_length=200, description="新标题;为空时保持不变。") status: str | None = Field( default=None, description="会话状态切换:active / archived。deleted 请走 DELETE 端点。", ) class ChatSessionResponse(BaseModel): model_config = ConfigDict( json_schema_extra={ "examples": [ { "session_id": "session_2e7c3cbd4ef8472bab59718b7d012f80", "character_id": "character_ec83d55746c54e47ab6f98d683032626", "title": "大模型联调会话", "status": "active", "created_at": "2026-06-19T09:06:47.515000Z", "updated_at": "2026-06-19T09:10:52.690000Z", } ] } ) session_id: str = Field(description="会话 ID,前缀为 session_。") character_id: str = Field(description="会话所属人物 ID。") title: str | None = Field(description="会话标题。") status: str = Field(description="会话状态:active / archived / deleted。") created_at: str = Field(description="创建时间,UTC ISO 8601 字符串。") updated_at: str = Field(description="更新时间,UTC ISO 8601 字符串。") message_count: int = Field(default=0, description="会话内未删除消息数(用户 + 助手)。") last_message_preview: str | None = Field(default=None, description="最近一条消息的内容摘要。") class ChatSessionListResponse(BaseModel): model_config = ConfigDict( json_schema_extra={ "examples": [ { "items": [ { "session_id": "session_2e7c3cbd4ef8472bab59718b7d012f80", "character_id": "character_ec83d55746c54e47ab6f98d683032626", "title": "大模型联调会话", "status": "active", "created_at": "2026-06-19T09:06:47.515000Z", "updated_at": "2026-06-19T09:10:52.690000Z", } ], "total": 1, } ] } ) items: list[ChatSessionResponse] = Field(description="当前页会话列表。") total: int = Field(description="符合条件的会话总数。") class SendMessageRequest(BaseModel): model_config = ConfigDict( json_schema_extra={ "examples": [ { "content": "你好,请简单介绍一下你自己。", "modality": "text", "model_hint": "deepseek-v4-flash", }, { "content": "请用三句话总结我们刚才聊到的内容。", "modality": "text", "model_hint": "default-chat", }, ] } ) content: str = Field(min_length=1, description="用户消息正文。") modality: str = Field(default="text", description="消息模态;当前阶段仅支持 text。") model_hint: str | None = Field( default=None, description="逻辑模型名或能力槽位,例如 default-chat、deepseek-v4-flash;为空时使用人物默认模型。", ) thinking: bool = Field( default=False, description="是否开启思考模式(reasoning);模型不支持时忽略。" ) reasoning_effort: str | None = Field( default=None, description="思考力度:low / medium / high。thinking=false 时忽略,使用模型默认。", ) prior_versions: list[dict] | None = Field( default=None, description="重答时携带的历史版本列表,每项含 content 和 created_at。后端将其合并到新消息的 versions_json 中(前置插入)," "同时软删除前一条 assistant 消息,避免刷新后出现重复消息。", ) class SendMessageResponse(BaseModel): model_config = ConfigDict( json_schema_extra={ "examples": [ { "message_id": "message_462927da6f0e4af780dd28fd58f73314", "assistant_message_id": "message_2f9b7bf7d3b84231b67b28bb39fbfa7a", "run_id": "run_a2c8ecc73c0e4cc7bc2fafbaeada74e0", "session_id": "session_2e7c3cbd4ef8472bab59718b7d012f80", "character_id": "character_ec83d55746c54e47ab6f98d683032626", "status": "completed", "stream_url": "/api/v1/runs/run_a2c8ecc73c0e4cc7bc2fafbaeada74e0/stream", } ] } ) message_id: str = Field(description="本次写入的用户消息 ID。") assistant_message_id: str | None = Field(description="模型回复消息 ID;失败时可能为空。") run_id: str = Field(description="本次对话运行 ID,可用于查询 Run 或 SSE。") session_id: str = Field(description="会话 ID。") character_id: str = Field(description="人物 ID。") status: str = Field(description="运行状态。成功完成时为 completed。") stream_url: str = Field(description="SSE 事件流 URL(前置于此,前端可直接 new EventSource)。") class ChatMessageResponse(BaseModel): model_config = ConfigDict( json_schema_extra={ "examples": [ { "message_id": "message_2f9b7bf7d3b84231b67b28bb39fbfa7a", "session_id": "session_2e7c3cbd4ef8472bab59718b7d012f80", "character_id": "character_ec83d55746c54e47ab6f98d683032626", "role": "assistant", "content": "你好,我是魂镜中的默认人物,会结合记忆和当前会话与你对话。", "modality": "text", "run_id": "run_a2c8ecc73c0e4cc7bc2fafbaeada74e0", "metadata": {"model_hint": "deepseek-v4-flash", "provider": "deepseek"}, "sensitivity": "low", "created_at": "2026-06-19T09:10:52.676462Z", "deleted_at": None, } ] } ) message_id: str = Field(description="消息 ID,前缀为 message_。") session_id: str = Field(description="所属会话 ID。") character_id: str = Field(description="所属人物 ID。") role: str = Field(description="消息角色:user / assistant / system / tool。") content: str = Field(description="消息正文。") modality: str = Field(description="消息模态:text / image / audio / file。") run_id: str | None = Field(description="关联运行 ID。") metadata: dict[str, Any] = Field(description="消息元数据,例如模型名、provider 等。") sensitivity: str = Field(description="敏感等级:none / low / medium / high。") versions: list[dict] = Field( default=[], description="版本历史列表,每项含 content 和 created_at。", ) active_version_idx: int = Field( default=0, description="当前活跃版本在 versions 中的索引。", ) created_at: str = Field(description="创建时间,UTC ISO 8601 字符串。") deleted_at: str | None = Field(description="删除时间;未删除时为空。") class ChatMessageListResponse(BaseModel): model_config = ConfigDict( json_schema_extra={ "examples": [ { "items": [ { "message_id": "message_462927da6f0e4af780dd28fd58f73314", "session_id": "session_2e7c3cbd4ef8472bab59718b7d012f80", "character_id": "character_ec83d55746c54e47ab6f98d683032626", "role": "user", "content": "你好,请简单介绍一下你自己。", "modality": "text", "run_id": "run_a2c8ecc73c0e4cc7bc2fafbaeada74e0", "metadata": {}, "sensitivity": "low", "created_at": "2026-06-19T09:10:52.660153Z", "deleted_at": None, }, { "message_id": "message_2f9b7bf7d3b84231b67b28bb39fbfa7a", "session_id": "session_2e7c3cbd4ef8472bab59718b7d012f80", "character_id": "character_ec83d55746c54e47ab6f98d683032626", "role": "assistant", "content": "你好,我是魂镜中的默认人物,会结合记忆和当前会话与你对话。", "modality": "text", "run_id": "run_a2c8ecc73c0e4cc7bc2fafbaeada74e0", "metadata": {"model_hint": "deepseek-v4-flash", "provider": "deepseek"}, "sensitivity": "low", "created_at": "2026-06-19T09:10:52.676462Z", "deleted_at": None, }, ], "total": 2, } ] } ) items: list[ChatMessageResponse] = Field(description="按创建时间升序排列的消息列表。") total: int = Field(description="符合条件的消息总数。") class SelectVersionRequest(BaseModel): model_config = ConfigDict( json_schema_extra={ "examples": [ {"version_idx": 0}, {"version_idx": 2}, ] } ) version_idx: int = Field( ge=0, description="要激活的版本在消息 versions 数组中的索引(0-based)。", )