| |
| import uuid |
| import json |
| from fastapi import APIRouter, HTTPException |
| from pydantic import BaseModel |
| from backend.database.connection import get_connection |
|
|
| router = APIRouter() |
|
|
|
|
| class CreateConversationRequest(BaseModel): |
| title: str = "New Chat" |
| conv_type: str = "general" |
|
|
|
|
| class RenameRequest(BaseModel): |
| title: str |
|
|
|
|
| @router.post("/conversations") |
| def create_conversation(req: CreateConversationRequest): |
| """Create a new conversation (like clicking 'New Chat' in ChatGPT).""" |
| conv_id = str(uuid.uuid4()) |
| with get_connection() as conn: |
| cursor = conn.cursor() |
| cursor.execute( |
| "INSERT INTO conversations (id, title, conv_type) VALUES (%s, %s, %s)", |
| (conv_id, req.title, req.conv_type) |
| ) |
| conn.commit() |
| return {"id": conv_id, "title": req.title, "conv_type": req.conv_type} |
|
|
|
|
| @router.get("/conversations") |
| def list_conversations(): |
| """Return all conversations ordered by most recent.""" |
| with get_connection() as conn: |
| cursor = conn.cursor(dictionary=True) |
| cursor.execute(""" |
| SELECT c.id, c.title, c.created_at, c.updated_at, |
| COUNT(h.id) AS message_count |
| FROM conversations c |
| LEFT JOIN chat_history h ON h.conversation_id = c.id |
| GROUP BY c.id, c.title, c.created_at, c.updated_at |
| ORDER BY c.updated_at DESC |
| LIMIT 50 |
| """) |
| rows = cursor.fetchall() |
| for r in rows: |
| if r["created_at"]: |
| r["created_at"] = r["created_at"].isoformat() |
| if r["updated_at"]: |
| r["updated_at"] = r["updated_at"].isoformat() |
| return {"conversations": rows} |
|
|
|
|
| @router.get("/conversations/{conv_id}/messages") |
| def get_conversation_messages(conv_id: str): |
| """Load full message history for a specific conversation.""" |
| with get_connection() as conn: |
| cursor = conn.cursor(dictionary=True) |
| |
| cursor.execute("SELECT id, title FROM conversations WHERE id = %s", (conv_id,)) |
| conv = cursor.fetchone() |
| if not conv: |
| raise HTTPException(status_code=404, detail="Conversation not found") |
|
|
| cursor.execute(""" |
| SELECT id, question, answer, sources_used AS sourcesUsed, created_at AS createdAt |
| FROM chat_history |
| WHERE conversation_id = %s |
| ORDER BY created_at ASC |
| """, (conv_id,)) |
| messages = cursor.fetchall() |
|
|
| for m in messages: |
| if m["createdAt"]: |
| m["createdAt"] = m["createdAt"].isoformat() |
| if m["sourcesUsed"] and isinstance(m["sourcesUsed"], str): |
| m["sourcesUsed"] = json.loads(m["sourcesUsed"]) |
|
|
| return {"conversation": conv, "messages": messages} |
|
|
|
|
| @router.patch("/conversations/{conv_id}") |
| def rename_conversation(conv_id: str, req: RenameRequest): |
| """Rename a conversation.""" |
| with get_connection() as conn: |
| cursor = conn.cursor() |
| cursor.execute( |
| "UPDATE conversations SET title = %s WHERE id = %s", |
| (req.title, conv_id) |
| ) |
| conn.commit() |
| return {"id": conv_id, "title": req.title} |
|
|
|
|
| @router.delete("/conversations/{conv_id}") |
| def delete_conversation(conv_id: str): |
| """Delete a conversation and all its messages.""" |
| with get_connection() as conn: |
| cursor = conn.cursor() |
| cursor.execute("DELETE FROM conversations WHERE id = %s", (conv_id,)) |
| conn.commit() |
| return {"message": "Conversation deleted", "id": conv_id} |
|
|