"""对话路由:会话管理 + REST 非流式对话。""" from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from ..core.deps import get_current_user from ..core.response import ok from ..database import get_db from ..models import Agent, ChatMessage, ChatSession, User from ..schemas.chat import ChatRequest, ChatSessionCreate from ..services import chat_service router = APIRouter(prefix="/chat", tags=["对话"]) def _session_out(s: ChatSession) -> dict: return { "id": s.id, "title": s.title, "agent_id": s.agent_id, "model": s.model, "created_at": s.created_at.isoformat(), "updated_at": s.updated_at.isoformat(), } def _message_out(m: ChatMessage) -> dict: return {"id": m.id, "session_id": m.session_id, "role": m.role, "content": m.content, "model": m.model, "created_at": m.created_at.isoformat()} def _get_owned_session(db: Session, user: User, session_id: int) -> ChatSession: s = db.get(ChatSession, session_id) if not s or s.user_id != user.id: raise HTTPException(status_code=404, detail="会话不存在") return s @router.get("/sessions") def list_sessions(user: User = Depends(get_current_user), db: Session = Depends(get_db)): sessions = ( db.query(ChatSession).filter(ChatSession.user_id == user.id) .order_by(ChatSession.updated_at.desc()).all() ) return ok([_session_out(s) for s in sessions]) @router.post("/sessions") def create_session(body: ChatSessionCreate, user: User = Depends(get_current_user), db: Session = Depends(get_db)): if body.agent_id: agent = db.get(Agent, body.agent_id) if not agent or (agent.user_id and agent.user_id != user.id and not agent.is_public): raise HTTPException(status_code=404, detail="智能体不存在") s = ChatSession(user_id=user.id, title=body.title, agent_id=body.agent_id, model=body.model) db.add(s) db.commit() db.refresh(s) return ok(_session_out(s)) @router.get("/sessions/{session_id}/messages") def list_messages(session_id: int, user: User = Depends(get_current_user), db: Session = Depends(get_db)): s = _get_owned_session(db, user, session_id) messages = db.query(ChatMessage).filter(ChatMessage.session_id == s.id).order_by(ChatMessage.id).all() return ok([_message_out(m) for m in messages]) @router.post("/sessions/{session_id}/messages") async def send_message(session_id: int, body: ChatRequest, user: User = Depends(get_current_user), db: Session = Depends(get_db)): s = _get_owned_session(db, user, session_id) try: reply = await chat_service.chat_once(db, user, s, body.content, body.agent_id, body.model) except LookupError as e: raise HTTPException(status_code=404, detail=str(e)) except Exception as e: raise HTTPException(status_code=502, detail=f"模型调用失败:{e}") # 自动生成会话标题 if s.title == "新对话" and len(body.content) <= 40: s.title = body.content[:20] db.commit() return ok(_message_out(reply)) @router.delete("/sessions/{session_id}") def delete_session(session_id: int, user: User = Depends(get_current_user), db: Session = Depends(get_db)): s = _get_owned_session(db, user, session_id) db.delete(s) db.commit() return ok(message="已删除")