# [DEF:TasksRouter:Module] # @SEMANTICS: api, router, tasks, create, list, get # @PURPOSE: Defines the FastAPI router for task-related endpoints, allowing clients to create, list, and get the status of tasks. # @LAYER: UI (API) # @RELATION: Depends on the TaskManager. It is included by the main app. from typing import List, Dict, Any, Optional from fastapi import APIRouter, Depends, HTTPException, status from pydantic import BaseModel from ...core.task_manager import TaskManager, Task, TaskStatus, LogEntry from ...dependencies import get_task_manager router = APIRouter() class CreateTaskRequest(BaseModel): plugin_id: str params: Dict[str, Any] class ResolveTaskRequest(BaseModel): resolution_params: Dict[str, Any] class ResumeTaskRequest(BaseModel): passwords: Dict[str, str] @router.post("/", response_model=Task, status_code=status.HTTP_201_CREATED) async def create_task( request: CreateTaskRequest, task_manager: TaskManager = Depends(get_task_manager) ): """ Create and start a new task for a given plugin. """ try: task = await task_manager.create_task( plugin_id=request.plugin_id, params=request.params ) return task except ValueError as e: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e)) @router.get("/", response_model=List[Task]) async def list_tasks( limit: int = 10, offset: int = 0, status: Optional[TaskStatus] = None, task_manager: TaskManager = Depends(get_task_manager) ): """ Retrieve a list of tasks with pagination and optional status filter. """ return task_manager.get_tasks(limit=limit, offset=offset, status=status) @router.get("/{task_id}", response_model=Task) async def get_task( task_id: str, task_manager: TaskManager = Depends(get_task_manager) ): """ Retrieve the details of a specific task. """ task = task_manager.get_task(task_id) if not task: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Task not found") return task @router.get("/{task_id}/logs", response_model=List[LogEntry]) async def get_task_logs( task_id: str, task_manager: TaskManager = Depends(get_task_manager) ): """ Retrieve logs for a specific task. """ task = task_manager.get_task(task_id) if not task: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Task not found") return task_manager.get_task_logs(task_id) @router.post("/{task_id}/resolve", response_model=Task) async def resolve_task( task_id: str, request: ResolveTaskRequest, task_manager: TaskManager = Depends(get_task_manager) ): """ Resolve a task that is awaiting mapping. """ try: await task_manager.resolve_task(task_id, request.resolution_params) return task_manager.get_task(task_id) except ValueError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) @router.post("/{task_id}/resume", response_model=Task) async def resume_task( task_id: str, request: ResumeTaskRequest, task_manager: TaskManager = Depends(get_task_manager) ): """ Resume a task that is awaiting input (e.g., passwords). """ try: task_manager.resume_task_with_password(task_id, request.passwords) return task_manager.get_task(task_id) except ValueError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) @router.delete("/", status_code=status.HTTP_204_NO_CONTENT) async def clear_tasks( status: Optional[TaskStatus] = None, task_manager: TaskManager = Depends(get_task_manager) ): """ Clear tasks matching the status filter. If no filter, clears all non-running tasks. """ task_manager.clear_tasks(status) return # [/DEF]