"""会话创建与历史查询接口""" from typing import Annotated from fastapi import APIRouter, Depends, Query, Request from app.common.response import ApiResponse, success_response from app.core.auth import get_current_user from app.core.exceptions import BizException from app.schemas.conversation import ( ConversationCreate, ConversationCreated, ConversationDetail, ConversationList, ConversationRename, ) from app.schemas.user import CurrentUser MAX_OFFSET = 10000 router = APIRouter(prefix="/conversations", tags=["Conversation"]) @router.post("") async def create_conversation( request: Request, user: CurrentUser = Depends(get_current_user), body: ConversationCreate | None = None, ) -> ApiResponse[ConversationCreated]: store = request.app.state.conversation_store screen_id = body.screen_id if body else None # 会话挂到大屏上,大屏必须是自己的;没配 MongoDB(没有大屏服务)时无从校验,直接放过 screens = getattr(request.app.state, "screen_service", None) if screen_id is not None and screens is not None: if not await screens.exists(screen_id, user.id): raise BizException(404, "大屏不存在或已删除") return success_response( ConversationCreated(conversation_id=await store.create(user.id, screen_id)) ) @router.get("") async def list_conversations( request: Request, user: Annotated[CurrentUser, Depends(get_current_user)], limit: Annotated[int, Query(ge=1, le=100)] = 20, offset: Annotated[int, Query(ge=0, le=MAX_OFFSET)] = 0, screen_id: Annotated[str | None, Query(min_length=1)] = None, ) -> ApiResponse[ConversationList]: store = request.app.state.conversation_store return success_response( ConversationList( conversations=await store.list_by_user(user.id, limit, offset, screen_id), total=await store.count_by_user(user.id, screen_id), ) ) @router.get("/{conversation_id}") async def get_conversation( conversation_id: str, request: Request, user: CurrentUser = Depends(get_current_user), ) -> ApiResponse[ConversationDetail]: store = request.app.state.conversation_store # 他人的会话与不存在同样返回 404 if not await store.exists(conversation_id, user.id): raise BizException(404, "会话不存在或已过期") turns = await store.load_turns(conversation_id, None) return success_response( ConversationDetail(conversation_id=conversation_id, turns=turns) ) @router.patch("/{conversation_id}") async def rename_conversation( conversation_id: str, body: ConversationRename, request: Request, user: CurrentUser = Depends(get_current_user), ) -> ApiResponse[dict]: store = request.app.state.conversation_store if not await store.rename(conversation_id, user.id, body.title): raise BizException(404, "会话不存在或已过期") return success_response() @router.delete("/{conversation_id}") async def delete_conversation( conversation_id: str, request: Request, user: CurrentUser = Depends(get_current_user), ) -> ApiResponse[dict]: store = request.app.state.conversation_store if not await store.delete(conversation_id, user.id): raise BizException(404, "会话不存在或已过期") return success_response()