"""后台管理接口:任务/Agent/日志/手动管控。""" from typing import Optional from fastapi import APIRouter, Body, Depends, Header, HTTPException, Request from app.constants import TaskStatus from app.models.schemas import AgentInfo, LogEntry, TaskInfo from app.repository.log_repo import LogRepo from app.constants import AgentStatus from app.services.agent_service import AgentService from app.services.security import require_admin from app.services.task_service import TaskService router = APIRouter() def require_admin_dep(x_admin_auth: str = Header(..., alias="X-Admin-Auth")) -> None: """后台管理接口鉴权:校验 X-Admin-Auth 头与 ADMIN_AUTH 一致。""" require_admin(x_admin_auth) def get_task_service(request: Request) -> TaskService: return TaskService(request.app.state.redis) def get_agent_service(request: Request) -> AgentService: return AgentService(request.app.state.redis) def get_log_repo(request: Request) -> LogRepo: return LogRepo(request.app.state.redis) # ---------- 任务管理 ---------- @router.get("/tasks", response_model=list[TaskInfo], summary="任务列表") async def list_tasks( status: Optional[TaskStatus] = None, limit: int = 100, svc: TaskService = Depends(get_task_service), _admin: None = Depends(require_admin_dep), ): return await svc.list(status=status, limit=limit) @router.get("/tasks/{request_id}", response_model=TaskInfo, summary="任务详情") async def task_detail( request_id: str, svc: TaskService = Depends(get_task_service), _admin: None = Depends(require_admin_dep), ): task = await svc.get(request_id) if not task: raise HTTPException(status_code=404, detail="task not found") return task @router.post("/tasks/{request_id}/cancel", summary="取消任务") async def admin_cancel( request_id: str, svc: TaskService = Depends(get_task_service), _admin: None = Depends(require_admin_dep), ): if not await svc.cancel(request_id): raise HTTPException(status_code=400, detail="cannot cancel task") return {"ok": True} @router.post("/tasks/{request_id}/reset", summary="重置任务状态") async def admin_reset( request_id: str, svc: TaskService = Depends(get_task_service), _admin: None = Depends(require_admin_dep), ): if not await svc.reset(request_id): raise HTTPException(status_code=400, detail="cannot reset task") return {"ok": True} # ---------- Agent 管理 ---------- @router.get("/agents", response_model=list[AgentInfo], summary="Agent 列表") async def list_agents( svc: AgentService = Depends(get_agent_service), _admin: None = Depends(require_admin_dep), ): return await svc.all() @router.post("/agents/{agent_id}/unavailable", summary="置 Agent 不可用") async def agent_unavailable( agent_id: str, svc: AgentService = Depends(get_agent_service), _admin: None = Depends(require_admin_dep), ): if not await svc.set_unavailable(agent_id): raise HTTPException(status_code=404, detail="agent not found") return {"ok": True} @router.post("/agents/{agent_id}/available", summary="置 Agent 可用") async def agent_available( agent_id: str, svc: AgentService = Depends(get_agent_service), _admin: None = Depends(require_admin_dep), ): if not await svc.set_available(agent_id): raise HTTPException(status_code=404, detail="agent not found") return {"ok": True} @router.post("/agents/{agent_id}/priority", response_model=AgentInfo, summary="设置 Agent 优先级") async def agent_priority( agent_id: str, priority: int = Body(..., ge=1, le=5, description="优先级 1-5,越小越先分配"), svc: AgentService = Depends(get_agent_service), _admin: None = Depends(require_admin_dep), ): agent = await svc.set_priority(agent_id, priority) if not agent: raise HTTPException(status_code=404, detail="agent not found") return agent # ---------- 日志审计 ---------- @router.get("/logs", response_model=list[LogEntry], summary="日志审计") async def logs( limit: int = 200, request_id: Optional[str] = None, agent_id: Optional[str] = None, repo: LogRepo = Depends(get_log_repo), _admin: None = Depends(require_admin_dep), ): return await repo.list(limit=limit, request_id=request_id, agent_id=agent_id) # ---------- 概览 ---------- @router.get("/overview", summary="概览统计") async def overview( task_svc: TaskService = Depends(get_task_service), agent_svc: AgentService = Depends(get_agent_service), _admin: None = Depends(require_admin_dep), ): tasks = await task_svc.list(limit=1000) agents = await agent_svc.all() from collections import Counter status_count = Counter(t.status.value for t in tasks) return { "task_total": len(tasks), "task_pending": status_count.get(TaskStatus.PENDING.value, 0), "task_running": status_count.get(TaskStatus.RUNNING.value, 0), "task_success": status_count.get(TaskStatus.SUCCESS.value, 0), "task_failed": status_count.get(TaskStatus.FAILED.value, 0), "agent_total": len(agents), "agent_ready": sum(1 for a in agents if a.status == AgentStatus.READY), "agent_processing": sum(1 for a in agents if a.status == AgentStatus.PROCESSING), "agent_stopping": sum(1 for a in agents if a.status == AgentStatus.STOPPING), "agent_offline": sum(1 for a in agents if a.status == AgentStatus.OFFLINE), "agent_unavailable": sum(1 for a in agents if a.status == AgentStatus.UNAVAILABLE), }