init
This commit is contained in:
158
api/debates.py
Normal file
158
api/debates.py
Normal file
@@ -0,0 +1,158 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
from middleware.auth import require_auth
|
||||
from sse_starlette.sse import EventSourceResponse
|
||||
from typing import Dict, Any
|
||||
import asyncio
|
||||
import json
|
||||
|
||||
from orchestrator.debate_orchestrator import DebateOrchestrator
|
||||
from models.debate import DebateRequest
|
||||
from storage.session_manager import SessionManager
|
||||
from db_models import get_db
|
||||
|
||||
router = APIRouter(tags=["debates"])
|
||||
|
||||
|
||||
@router.post("/debate/create", dependencies=[Depends(require_auth)])
|
||||
async def create_debate(debate_request: DebateRequest, db=Depends(get_db)) -> Dict[str, Any]:
|
||||
"""
|
||||
Create a new debate session with specified parameters
|
||||
"""
|
||||
try:
|
||||
orchestrator = DebateOrchestrator(db)
|
||||
session_id = await orchestrator.create_session(debate_request)
|
||||
|
||||
return {
|
||||
"session_id": session_id,
|
||||
"status": "created",
|
||||
"message": f"Debate session {session_id} created successfully"
|
||||
}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.get("/debate/{session_id}")
|
||||
async def get_debate(session_id: str, db=Depends(get_db)) -> Dict[str, Any]:
|
||||
"""
|
||||
Get the current state of a debate session
|
||||
"""
|
||||
try:
|
||||
orchestrator = DebateOrchestrator(db)
|
||||
session = await orchestrator.get_session_status(session_id)
|
||||
|
||||
if not session:
|
||||
raise HTTPException(status_code=404, detail=f"Debate session {session_id} not found")
|
||||
|
||||
return session.dict()
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.post("/debate/{session_id}/start", dependencies=[Depends(require_auth)])
|
||||
async def start_debate(session_id: str, db=Depends(get_db)) -> Dict[str, Any]:
|
||||
"""
|
||||
Start a debate session and stream the results
|
||||
"""
|
||||
try:
|
||||
orchestrator = DebateOrchestrator(db)
|
||||
session = await orchestrator.run_debate(session_id)
|
||||
|
||||
return {
|
||||
"session_id": session_id,
|
||||
"status": session.status,
|
||||
"message": f"Debate session {session_id} completed"
|
||||
}
|
||||
except Exception as e:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.delete("/debate/{session_id}", dependencies=[Depends(require_auth)])
|
||||
async def end_debate(session_id: str, db=Depends(get_db)) -> Dict[str, Any]:
|
||||
"""
|
||||
End a debate session prematurely
|
||||
"""
|
||||
try:
|
||||
orchestrator = DebateOrchestrator(db)
|
||||
await orchestrator.terminate_session(session_id)
|
||||
|
||||
return {"session_id": session_id, "status": "terminated"}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.get("/debate/{session_id}/stream")
|
||||
async def stream_debate(session_id: str, db=Depends(get_db)) -> EventSourceResponse:
|
||||
"""
|
||||
Stream debate updates in real-time using Server-Sent Events
|
||||
"""
|
||||
async def event_generator():
|
||||
session_manager = SessionManager()
|
||||
|
||||
# Check if the session exists
|
||||
session = await session_manager.get_session(db, session_id)
|
||||
if not session:
|
||||
yield {"event": "error", "data": json.dumps({"error": f"Session {session_id} not found"})}
|
||||
return
|
||||
|
||||
# Yield initial state
|
||||
yield {"event": "update", "data": json.dumps({
|
||||
"session_id": session_id,
|
||||
"status": session.status,
|
||||
"rounds": [round.dict() for round in session.rounds],
|
||||
"evidence_library": [e.dict() for e in session.evidence_library],
|
||||
"message": "Debate session initialized"
|
||||
}, default=str)}
|
||||
|
||||
last_round_count = len(session.rounds)
|
||||
# Poll until debate completes or times out (max 5 min)
|
||||
for _ in range(150): # 150 × 2s = 300s timeout
|
||||
await asyncio.sleep(2)
|
||||
|
||||
# Reset transaction so we see commits from the run_debate request
|
||||
db.commit()
|
||||
|
||||
updated_session = await session_manager.get_session(db, session_id)
|
||||
if not updated_session:
|
||||
break
|
||||
|
||||
# Only yield update when rounds actually changed
|
||||
if len(updated_session.rounds) != last_round_count or updated_session.status != session.status:
|
||||
last_round_count = len(updated_session.rounds)
|
||||
session = updated_session
|
||||
yield {"event": "update", "data": json.dumps({
|
||||
"session_id": session_id,
|
||||
"status": updated_session.status,
|
||||
"rounds": [round.dict() for round in updated_session.rounds],
|
||||
"evidence_library": [e.dict() for e in updated_session.evidence_library],
|
||||
"current_round": len(updated_session.rounds)
|
||||
}, default=str)}
|
||||
|
||||
if updated_session.status in ("completed", "terminated"):
|
||||
yield {"event": "complete", "data": json.dumps({
|
||||
"session_id": session_id,
|
||||
"status": updated_session.status,
|
||||
"summary": updated_session.summary,
|
||||
"rounds": [round.dict() for round in updated_session.rounds],
|
||||
"evidence_library": [e.dict() for e in updated_session.evidence_library]
|
||||
}, default=str)}
|
||||
break
|
||||
|
||||
return EventSourceResponse(event_generator())
|
||||
|
||||
|
||||
@router.get("/sessions")
|
||||
async def list_sessions(db=Depends(get_db)) -> Dict[str, Any]:
|
||||
"""
|
||||
List all debate sessions
|
||||
"""
|
||||
try:
|
||||
session_manager = SessionManager()
|
||||
sessions = await session_manager.list_sessions(db)
|
||||
return {"sessions": sessions}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
Reference in New Issue
Block a user