""" Agent status and history API endpoints. """ import logging from typing import Optional from fastapi import APIRouter, Depends, Query from sqlalchemy import select, func from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db from app.models import AgentExecution, AgentExecutionStatus from app.schemas import AgentStatus, AgentExecutionResponse from app.workflows import AGENT_LABELS, AGENT_MODELS log = logging.getLogger("foxy.api.agents") router = APIRouter(prefix="/api/agents", tags=["agents"]) @router.get("", response_model=list[AgentStatus]) async def list_agents(db: AsyncSession = Depends(get_db)): """List all agents with their current status and stats.""" agents = [] for display_name, label in AGENT_LABELS.items(): # Count executions total_q = await db.execute( select(func.count(AgentExecution.id)) .where(AgentExecution.agent_name == display_name) ) total = total_q.scalar() or 0 success_q = await db.execute( select(func.count(AgentExecution.id)) .where(AgentExecution.agent_name == display_name) .where(AgentExecution.status == AgentExecutionStatus.SUCCESS) ) success = success_q.scalar() or 0 failure_q = await db.execute( select(func.count(AgentExecution.id)) .where(AgentExecution.agent_name == display_name) .where(AgentExecution.status == AgentExecutionStatus.FAILED) ) failure = failure_q.scalar() or 0 # Check if currently running running_q = await db.execute( select(AgentExecution) .where(AgentExecution.agent_name == display_name) .where(AgentExecution.status == AgentExecutionStatus.RUNNING) .limit(1) ) running_exec = running_q.scalar_one_or_none() current_status = "running" if running_exec else "idle" current_project = None if running_exec: current_project = str(running_exec.project_id) agents.append(AgentStatus( name=label, display_name=display_name, model=AGENT_MODELS.get(display_name, "unknown"), current_status=current_status, current_project=current_project, total_executions=total, success_count=success, failure_count=failure, )) return agents @router.get("/{agent_name}/history", response_model=list[AgentExecutionResponse]) async def get_agent_history( agent_name: str, limit: int = Query(50, le=200), db: AsyncSession = Depends(get_db), ): """Get execution history for a specific agent.""" # Map label to display name display_name = None for dn, label in AGENT_LABELS.items(): if label == agent_name or dn == agent_name: display_name = dn break if not display_name: display_name = agent_name result = await db.execute( select(AgentExecution) .where(AgentExecution.agent_name == display_name) .order_by(AgentExecution.started_at.desc()) .limit(limit) ) return result.scalars().all()