# api/v1/sessions.py from typing import List, Optional from fastapi import Body, Query, Path, WebSocket, WebSocketDisconnect from services import redis_service from fastapi import APIRouter from models.session import SessionMeta import json import asyncio router = APIRouter() # ------------------------- # WebSocket per aggiornamenti sessioni # ------------------------- @router.websocket("/ws/sessions") async def sessions_ws(websocket: WebSocket, user_id: str = Query(...)): await websocket.accept() try: sessions = redis_service.get_sessions(user_id) await websocket.send_json({"type": "full_list", "sessions": sessions}) pubsub = redis_service.r.pubsub() channel = f"sessions:{user_id}" await pubsub.subscribe(channel) async for message in pubsub.listen(): if message["type"] != "message": continue try: data = json.loads(message["data"]) await websocket.send_json(data) except Exception as e: print(f"[WS] Errore parsing messaggio: {e}") except WebSocketDisconnect: print(f"[WS] Disconnesso: {user_id}") finally: await pubsub.unsubscribe(channel) await pubsub.close() # ------------------------- # Endpoint REST # ------------------------- @router.get("/sessions", response_model=List[dict]) async def list_sessions_endpoint(user_id: str = Query(...)): return redis_service.get_sessions(user_id) @router.get("/sessions/{session_id}", response_model=dict) async def get_session_meta_endpoint( user_id: str = Query(..., description="User ID"), session_id: str = Path(..., description="Session ID") ): return redis_service.get_session_meta(user_id, session_id) or {} @router.post("/sessions", response_model=dict) async def create_session_endpoint( user_id: str = Query(..., description="User ID"), first_message: str = Body("", embed=True), model_name: Optional[str] = Body(None, embed=True) # <-- Accept model_name ): meta = redis_service.create_session(user_id, first_message, model_name=model_name) redis_service.r.publish( f"sessions:{user_id}", json.dumps({"type": "created", "session": meta}) ) return meta @router.patch("/sessions/{session_id}", response_model=dict) async def update_session_endpoint( user_id: str = Query(..., description="User ID"), session_id: str = Path(..., description="Session ID"), session_name: Optional[str] = Body(None, embed=True), model_name: Optional[str] = Body(None, embed=True) # <-- Allow model update ): updated = redis_service.update_session_meta( user_id, session_id, session_name=session_name, model_name=model_name ) or {} if updated: redis_service.r.publish( f"sessions:{user_id}", json.dumps({"type": "updated", "session": updated}) ) return updated @router.delete("/sessions/{session_id}", response_model=dict) async def delete_session_endpoint( user_id: str = Query(..., description="User ID"), session_id: str = Path(..., description="Session ID") ): redis_service.delete_session(user_id, session_id) redis_service.r.publish( f"sessions:{user_id}", json.dumps({"type": "deleted", "session_id": session_id}) ) return {"status": "deleted"}