Spaces:
Running
Running
| """ | |
| Memory router β persistent AI chat history, user preferences (theme + language). | |
| All endpoints require JWT authentication. | |
| """ | |
| from typing import Optional | |
| from fastapi import APIRouter, Depends, Query | |
| from sqlalchemy.orm import Session | |
| from pydantic import BaseModel | |
| from app.database.database import get_db | |
| from app.database.models import ( | |
| User, ChatSession, ChatMessage, UserPreference, generate_uuid | |
| ) | |
| from app.auth.router import get_current_user | |
| router = APIRouter(prefix="/api/memory", tags=["Memory"]) | |
| # βββ Schemas ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class SaveMessageRequest(BaseModel): | |
| session_id: Optional[str] = None | |
| role: str # user | assistant | |
| content: str | |
| session_title: Optional[str] = None | |
| class PreferenceUpdate(BaseModel): | |
| theme: Optional[str] = None # dark | light | |
| language: Optional[str] = None # en | hi | mr | |
| # βββ Helpers ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def _get_or_create_prefs(db: Session, user_id: str) -> UserPreference: | |
| prefs = db.query(UserPreference).filter(UserPreference.user_id == user_id).first() | |
| if not prefs: | |
| prefs = UserPreference(id=generate_uuid(), user_id=user_id) | |
| db.add(prefs) | |
| db.commit() | |
| db.refresh(prefs) | |
| return prefs | |
| # βββ Chat history βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def get_history( | |
| session_id: Optional[str] = None, | |
| limit: int = Query(default=50, ge=1, le=200), | |
| current_user: User = Depends(get_current_user), | |
| db: Session = Depends(get_db), | |
| ): | |
| """Return persisted chat messages for the current user.""" | |
| query = db.query(ChatMessage).filter(ChatMessage.user_id == current_user.id) | |
| if session_id: | |
| query = query.filter(ChatMessage.session_id == session_id) | |
| messages = query.order_by(ChatMessage.created_at.asc()).limit(limit).all() | |
| # Also return sessions list | |
| sessions = ( | |
| db.query(ChatSession) | |
| .filter(ChatSession.user_id == current_user.id) | |
| .order_by(ChatSession.updated_at.desc()) | |
| .limit(20) | |
| .all() | |
| ) | |
| return { | |
| "messages": [ | |
| { | |
| "id": m.id, | |
| "session_id": m.session_id, | |
| "role": m.role, | |
| "content": m.content, | |
| "created_at": m.created_at.isoformat() if m.created_at else None, | |
| } | |
| for m in messages | |
| ], | |
| "sessions": [ | |
| { | |
| "id": s.id, | |
| "title": s.title, | |
| "created_at": s.created_at.isoformat() if s.created_at else None, | |
| "updated_at": s.updated_at.isoformat() if s.updated_at else None, | |
| } | |
| for s in sessions | |
| ], | |
| "total": len(messages), | |
| } | |
| def save_message( | |
| req: SaveMessageRequest, | |
| current_user: User = Depends(get_current_user), | |
| db: Session = Depends(get_db), | |
| ): | |
| """Persist a chat message to the database.""" | |
| # Get or create session | |
| session_id = req.session_id | |
| if not session_id: | |
| # Create a new session | |
| session = ChatSession( | |
| id=generate_uuid(), | |
| user_id=current_user.id, | |
| title=req.session_title or req.content[:40] + ("..." if len(req.content) > 40 else ""), | |
| ) | |
| db.add(session) | |
| db.flush() | |
| session_id = session.id | |
| else: | |
| session = db.query(ChatSession).filter( | |
| ChatSession.id == session_id, | |
| ChatSession.user_id == current_user.id, | |
| ).first() | |
| if not session: | |
| session = ChatSession( | |
| id=session_id, | |
| user_id=current_user.id, | |
| title=req.session_title or "Chat", | |
| ) | |
| db.add(session) | |
| db.flush() | |
| msg = ChatMessage( | |
| id=generate_uuid(), | |
| user_id=current_user.id, | |
| session_id=session_id, | |
| role=req.role, | |
| content=req.content, | |
| ) | |
| db.add(msg) | |
| db.commit() | |
| db.refresh(msg) | |
| return { | |
| "id": msg.id, | |
| "session_id": session_id, | |
| "role": msg.role, | |
| "content": msg.content, | |
| "created_at": msg.created_at.isoformat() if msg.created_at else None, | |
| } | |
| def clear_history( | |
| session_id: Optional[str] = None, | |
| current_user: User = Depends(get_current_user), | |
| db: Session = Depends(get_db), | |
| ): | |
| """Clear chat history β optionally scoped to a session.""" | |
| query = db.query(ChatMessage).filter(ChatMessage.user_id == current_user.id) | |
| if session_id: | |
| query = query.filter(ChatMessage.session_id == session_id) | |
| db.query(ChatSession).filter( | |
| ChatSession.id == session_id, | |
| ChatSession.user_id == current_user.id, | |
| ).delete() | |
| deleted = query.delete() | |
| db.commit() | |
| return {"deleted": deleted, "message": "History cleared."} | |
| # βββ Preferences ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def get_preferences( | |
| current_user: User = Depends(get_current_user), | |
| db: Session = Depends(get_db), | |
| ): | |
| prefs = _get_or_create_prefs(db, current_user.id) | |
| return {"theme": prefs.theme, "language": prefs.language} | |
| def update_preferences( | |
| req: PreferenceUpdate, | |
| current_user: User = Depends(get_current_user), | |
| db: Session = Depends(get_db), | |
| ): | |
| prefs = _get_or_create_prefs(db, current_user.id) | |
| if req.theme in ("dark", "light"): | |
| prefs.theme = req.theme | |
| if req.language in ("en", "hi", "mr"): | |
| prefs.language = req.language | |
| db.commit() | |
| db.refresh(prefs) | |
| return {"theme": prefs.theme, "language": prefs.language} | |