99 lines
3.1 KiB
Python
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()
|