""" app/api/routes_status.py HTTP endpoints for server/agent status and SSE events. """ from __future__ import annotations import logging from datetime import datetime, timezone from fastapi import APIRouter from fastapi.responses import StreamingResponse from app.config import APP_VERSION from app.models import ( AgentInfo, HealthResponse, QueueCounts, ServerInfo, StatusResponse, ) from app.services import config_service, event_service, instruction_service, status_service logger = logging.getLogger(__name__) router = APIRouter(tags=["status"]) @router.get("/healthz", response_model=HealthResponse) def health(): return HealthResponse(status="ok", server_time=datetime.now(timezone.utc)) @router.get("/api/status", response_model=StatusResponse) def get_status(): agent_row = status_service.get_latest_agent_activity() connected = status_service.is_agent_connected() agent_info = AgentInfo( connected=connected, last_seen_at=datetime.fromisoformat(agent_row["last_seen_at"]) if agent_row else None, last_fetch_at=datetime.fromisoformat(agent_row["last_fetch_at"]) if agent_row else None, agent_id=agent_row["agent_id"] if agent_row else None, ) counts = instruction_service.get_queue_counts() cfg = config_service.get_config() return StatusResponse( server=ServerInfo( status="up", started_at=status_service.server_started_at(), version=APP_VERSION, type="python", ), agent=agent_info, queue=QueueCounts(**counts), settings=cfg, ) @router.get("/api/events") async def sse_events(): q = event_service.subscribe() async def stream(): async for chunk in event_service.event_generator(q): yield chunk return StreamingResponse( stream(), media_type="text/event-stream", headers={ "Cache-Control": "no-cache", "X-Accel-Buffering": "no", "Connection": "keep-alive", }, )