"""v1 daemon list endpoint — caller-scoped daemon list (REQ-045).""" from __future__ import annotations import logging from fastapi import APIRouter, Depends from app.core.auth import AuthContext, require_read from app.repositories.factory import get_portfolio_repository_from_settings from app.schemas.v1 import DaemonListResponse, DaemonResponse logger = logging.getLogger(__name__) router = APIRouter(prefix="/v1", tags=["v1"]) def _get_repo(settings=None): from app.core.config import get_settings return get_portfolio_repository_from_settings(settings or get_settings()) # --------------------------------------------------------------------------- # GET /v1/daemons — caller-scoped daemon list (REQ-045) # --------------------------------------------------------------------------- @router.get("/daemons", response_model=DaemonListResponse) def list_daemons( auth: AuthContext = Depends(require_read), ) -> DaemonListResponse: """Return all daemons owned by the caller (auth.user_id). - Caller scope only: returns daemons belonging to auth.user_id. - admin token with user_id also returns only that user's daemons. - env/service tokens with user_id=None return an empty list (HTTP 200). - Returns all daemons (active and inactive) with is_active field for distinction. """ if auth.user_id is None: return DaemonListResponse(daemons=[], total=0) repo = _get_repo() try: daemons = repo.list_daemons_for_user(auth.user_id) finally: if callable(getattr(type(repo), "close", None)): repo.close() items = [ DaemonResponse( id=d.id, daemon_slug=d.daemon_slug, display_name=d.display_name, is_active=d.is_active, ) for d in daemons ] return DaemonListResponse(daemons=items, total=len(items))