99 lines
3.1 KiB
Python

"""
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()