| from fastapi import APIRouter, UploadFile, File, Form, HTTPException |
| from fastapi.responses import JSONResponse, FileResponse |
| from typing import Optional |
| import tempfile |
| import shutil |
| import os |
|
|
| from core.registry.loader import get_tasks |
| from core.execution.executor import execute_task |
|
|
|
|
| |
| |
| |
|
|
| def build_api_router() -> APIRouter: |
| """ |
| Dynamically builds API routes from TASK REGISTRY. |
| |
| Generated endpoints: |
| |
| POST /execute/{task} |
| GET /tasks |
| GET /health |
| """ |
|
|
| router = APIRouter(tags=["API"]) |
|
|
| |
| |
| |
| @router.post("/execute/{task_name}") |
| async def execute( |
| task_name: str, |
| file: Optional[UploadFile] = File(None), |
| url_input: Optional[str] = Form(None), |
| ): |
| """ |
| Universal execution endpoint. |
| Accepts: |
| - file upload |
| - url_input |
| """ |
|
|
| tasks = get_tasks() |
|
|
| if task_name not in tasks: |
| raise HTTPException( |
| status_code=404, |
| detail=f"Task '{task_name}' not found", |
| ) |
|
|
| temp_path = None |
|
|
| try: |
| |
| |
| |
| if file: |
| suffix = os.path.splitext(file.filename)[1] |
|
|
| with tempfile.NamedTemporaryFile( |
| delete=False, |
| suffix=suffix, |
| ) as tmp: |
| shutil.copyfileobj(file.file, tmp) |
| temp_path = tmp.name |
|
|
| |
| |
| |
| payload = { |
| "file_path": temp_path, |
| "url_input": url_input, |
| } |
|
|
| |
| |
| |
| result = await execute_task(task_name, payload) |
|
|
| |
| |
| |
| if isinstance(result, dict) and result.get("file"): |
| output_file = result["file"] |
|
|
| if os.path.exists(output_file): |
| return FileResponse( |
| output_file, |
| filename=os.path.basename(output_file), |
| ) |
|
|
| |
| |
| |
| return JSONResponse(result) |
|
|
| except Exception as e: |
| raise HTTPException( |
| status_code=500, |
| detail=str(e), |
| ) |
|
|
| finally: |
| |
| |
| |
| if temp_path and os.path.exists(temp_path): |
| os.unlink(temp_path) |
|
|
| |
| |
| |
| @router.get("/tasks") |
| async def list_tasks(): |
| """ |
| Returns registry tasks. |
| Used by UI and Docs builder. |
| """ |
|
|
| tasks = get_tasks() |
|
|
| return { |
| name: { |
| "category": getattr(t, "category", "general"), |
| "description": getattr(t, "description", ""), |
| } |
| for name, t in tasks.items() |
| } |
|
|
| |
| |
| |
| @router.get("/health") |
| async def health(): |
| return { |
| "status": "ok", |
| "tasks_loaded": len(get_tasks()), |
| } |
|
|
| return router |