from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from ..cursors import decode, encode from ..db import get_session from ..models import Agent as AgentModel from ..schemas import Agent, AgentsPage router = APIRouter() def _to_schema(a: AgentModel) -> Agent: return Agent( agent_id=a.agent_id, hostname=a.hostname, status=a.status, last_seen_at=a.last_seen_at, features=a.features or {"push": False, "metrics": False}, labels=a.labels or {}, ) @router.get("/agents", response_model=AgentsPage) async def list_agents( cursor: str | None = Query(default=None, max_length=512), limit: int = Query(default=100, ge=1, le=500), session: AsyncSession = Depends(get_session), ) -> AgentsPage: stmt = select(AgentModel).order_by(AgentModel.agent_id) if cursor is not None: (last_id,) = decode(cursor, 1) stmt = stmt.where(AgentModel.agent_id > last_id) rows = (await session.execute(stmt.limit(limit + 1))).scalars().all() next_cursor = None if len(rows) > limit: rows = rows[:limit] next_cursor = encode(rows[-1].agent_id) return AgentsPage(items=[_to_schema(a) for a in rows], next_cursor=next_cursor) @router.get("/agents/{agent_id}", response_model=Agent) async def get_agent(agent_id: str, session: AsyncSession = Depends(get_session)) -> Agent: res = await session.execute(select(AgentModel).where(AgentModel.agent_id == agent_id)) a = res.scalar_one_or_none() if a is None: raise HTTPException(status_code=404, detail="agent not found") return _to_schema(a)