from __future__ import annotations import asyncio import logging from typing import Optional from fastapi import APIRouter, HTTPException, status from pydantic import BaseModel logger = logging.getLogger(__name__) router = APIRouter(prefix='/sweep', tags=['sweep']) # Track running sweep task _sweep_task: Optional[asyncio.Task] = None _last_sweep_result: Optional[dict] = None class SweepRequest(BaseModel): agents: list[str] = [] # empty = all active agents class SweepStatusResponse(BaseModel): running: bool last_result: Optional[dict] = None @router.post('', status_code=status.HTTP_202_ACCEPTED) async def trigger_sweep(req: SweepRequest): global _sweep_task if _sweep_task and not _sweep_task.done(): raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail='Sweep already running', ) from ..app_state import get_sweep_coordinator coordinator = get_sweep_coordinator() if coordinator is None: raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail='Sweep coordinator not ready') async def _run(): global _last_sweep_result try: result = await coordinator.run_sweep(agents=req.agents or None) _last_sweep_result = result except Exception as exc: logger.error('sweep run error: %s', exc) _last_sweep_result = {'error': str(exc)} _sweep_task = asyncio.create_task(_run()) return {'status': 'accepted', 'agents': req.agents or 'all'} @router.get('/status', response_model=SweepStatusResponse) async def sweep_status(): running = _sweep_task is not None and not _sweep_task.done() return SweepStatusResponse(running=running, last_result=_last_sweep_result)