| 
									
										
										
										
											2024-11-09 14:32:24 -08:00
										 |  |  | # api/routes/sessions.py | 
					
						
							|  |  |  | from typing import Dict | 
					
						
							| 
									
										
										
										
											2024-11-26 15:39:36 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | from fastapi import APIRouter, Depends, HTTPException | 
					
						
							|  |  |  | from loguru import logger | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from ...datamodel import Message, Run, Session | 
					
						
							| 
									
										
										
										
											2024-11-09 14:32:24 -08:00
										 |  |  | from ..deps import get_db | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | router = APIRouter() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @router.get("/") | 
					
						
							| 
									
										
										
										
											2024-11-26 15:39:36 -08:00
										 |  |  | async def list_sessions(user_id: str, db=Depends(get_db)) -> Dict: | 
					
						
							| 
									
										
										
										
											2024-11-09 14:32:24 -08:00
										 |  |  |     """List all sessions for a user""" | 
					
						
							|  |  |  |     response = db.get(Session, filters={"user_id": user_id}) | 
					
						
							| 
									
										
										
										
											2024-11-26 15:39:36 -08:00
										 |  |  |     return {"status": True, "data": response.data} | 
					
						
							| 
									
										
										
										
											2024-11-09 14:32:24 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @router.get("/{session_id}") | 
					
						
							| 
									
										
										
										
											2024-11-26 15:39:36 -08:00
										 |  |  | async def get_session(session_id: int, user_id: str, db=Depends(get_db)) -> Dict: | 
					
						
							| 
									
										
										
										
											2024-11-09 14:32:24 -08:00
										 |  |  |     """Get a specific session""" | 
					
						
							| 
									
										
										
										
											2024-11-26 15:39:36 -08:00
										 |  |  |     response = db.get(Session, filters={"id": session_id, "user_id": user_id}) | 
					
						
							| 
									
										
										
										
											2024-11-09 14:32:24 -08:00
										 |  |  |     if not response.status or not response.data: | 
					
						
							|  |  |  |         raise HTTPException(status_code=404, detail="Session not found") | 
					
						
							| 
									
										
										
										
											2024-11-26 15:39:36 -08:00
										 |  |  |     return {"status": True, "data": response.data[0]} | 
					
						
							| 
									
										
										
										
											2024-11-09 14:32:24 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @router.post("/") | 
					
						
							| 
									
										
										
										
											2024-11-26 15:39:36 -08:00
										 |  |  | async def create_session(session: Session, db=Depends(get_db)) -> Dict: | 
					
						
							| 
									
										
										
										
											2024-11-09 14:32:24 -08:00
										 |  |  |     """Create a new session""" | 
					
						
							|  |  |  |     response = db.upsert(session) | 
					
						
							|  |  |  |     if not response.status: | 
					
						
							|  |  |  |         raise HTTPException(status_code=400, detail=response.message) | 
					
						
							| 
									
										
										
										
											2024-11-26 15:39:36 -08:00
										 |  |  |     return {"status": True, "data": response.data} | 
					
						
							| 
									
										
										
										
											2024-11-09 14:32:24 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @router.put("/{session_id}") | 
					
						
							| 
									
										
										
										
											2024-11-26 15:39:36 -08:00
										 |  |  | async def update_session(session_id: int, user_id: str, session: Session, db=Depends(get_db)) -> Dict: | 
					
						
							| 
									
										
										
										
											2024-11-09 14:32:24 -08:00
										 |  |  |     """Update an existing session""" | 
					
						
							|  |  |  |     # First verify the session belongs to user | 
					
						
							| 
									
										
										
										
											2024-11-26 15:39:36 -08:00
										 |  |  |     existing = db.get(Session, filters={"id": session_id, "user_id": user_id}) | 
					
						
							| 
									
										
										
										
											2024-11-09 14:32:24 -08:00
										 |  |  |     if not existing.status or not existing.data: | 
					
						
							|  |  |  |         raise HTTPException(status_code=404, detail="Session not found") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Update the session | 
					
						
							|  |  |  |     response = db.upsert(session) | 
					
						
							|  |  |  |     if not response.status: | 
					
						
							|  |  |  |         raise HTTPException(status_code=400, detail=response.message) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-26 15:39:36 -08:00
										 |  |  |     return {"status": True, "data": response.data, "message": "Session updated successfully"} | 
					
						
							| 
									
										
										
										
											2024-11-09 14:32:24 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @router.delete("/{session_id}") | 
					
						
							| 
									
										
										
										
											2024-11-26 15:39:36 -08:00
										 |  |  | async def delete_session(session_id: int, user_id: str, db=Depends(get_db)) -> Dict: | 
					
						
							| 
									
										
										
										
											2024-11-09 14:32:24 -08:00
										 |  |  |     """Delete a session""" | 
					
						
							| 
									
										
										
										
											2024-11-26 15:39:36 -08:00
										 |  |  |     db.delete(filters={"id": session_id, "user_id": user_id}, model_class=Session) | 
					
						
							|  |  |  |     return {"status": True, "message": "Session deleted successfully"} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @router.get("/{session_id}/runs") | 
					
						
							|  |  |  | async def list_session_runs(session_id: int, user_id: str, db=Depends(get_db)) -> Dict: | 
					
						
							|  |  |  |     """Get complete session history organized by runs""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         # 1. Verify session exists and belongs to user | 
					
						
							|  |  |  |         session = db.get(Session, filters={"id": session_id, "user_id": user_id}, return_json=False) | 
					
						
							|  |  |  |         if not session.status: | 
					
						
							|  |  |  |             raise HTTPException(status_code=500, detail="Database error while fetching session") | 
					
						
							|  |  |  |         if not session.data: | 
					
						
							|  |  |  |             raise HTTPException(status_code=404, detail="Session not found or access denied") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # 2. Get ordered runs for session | 
					
						
							|  |  |  |         runs = db.get(Run, filters={"session_id": session_id}, order="asc", return_json=False) | 
					
						
							|  |  |  |         if not runs.status: | 
					
						
							|  |  |  |             raise HTTPException(status_code=500, detail="Database error while fetching runs") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # 3. Build response with messages per run | 
					
						
							|  |  |  |         run_data = [] | 
					
						
							|  |  |  |         if runs.data:  # It's ok to have no runs | 
					
						
							|  |  |  |             for run in runs.data: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     # Get messages for this specific run | 
					
						
							|  |  |  |                     messages = db.get(Message, filters={"run_id": run.id}, order="asc", return_json=False) | 
					
						
							|  |  |  |                     if not messages.status: | 
					
						
							|  |  |  |                         logger.error(f"Failed to fetch messages for run {run.id}") | 
					
						
							|  |  |  |                         # Continue processing other runs even if one fails | 
					
						
							|  |  |  |                         messages.data = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     run_data.append( | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             "id": str(run.id), | 
					
						
							|  |  |  |                             "created_at": run.created_at, | 
					
						
							|  |  |  |                             "status": run.status, | 
					
						
							|  |  |  |                             "task": run.task, | 
					
						
							|  |  |  |                             "team_result": run.team_result, | 
					
						
							|  |  |  |                             "messages": messages.data or [], | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     ) | 
					
						
							|  |  |  |                 except Exception as e: | 
					
						
							|  |  |  |                     logger.error(f"Error processing run {run.id}: {str(e)}") | 
					
						
							|  |  |  |                     # Include run with error state instead of failing entirely | 
					
						
							|  |  |  |                     run_data.append( | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             "id": str(run.id), | 
					
						
							|  |  |  |                             "created_at": run.created_at, | 
					
						
							|  |  |  |                             "status": "ERROR", | 
					
						
							|  |  |  |                             "task": run.task, | 
					
						
							|  |  |  |                             "team_result": None, | 
					
						
							|  |  |  |                             "messages": [], | 
					
						
							|  |  |  |                             "error": f"Failed to process run: {str(e)}", | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return {"status": True, "data": {"runs": run_data}} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     except HTTPException: | 
					
						
							|  |  |  |         raise  # Re-raise HTTP exceptions | 
					
						
							|  |  |  |     except Exception as e: | 
					
						
							|  |  |  |         logger.error(f"Unexpected error in list_messages: {str(e)}") | 
					
						
							|  |  |  |         raise HTTPException(status_code=500, detail="Internal server error while fetching session data") from e |