File size: 4,164 Bytes
0afd1e2
 
 
 
 
 
 
76dc4d0
 
 
 
0afd1e2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76dc4d0
0afd1e2
 
 
 
 
 
 
 
 
76dc4d0
0afd1e2
76dc4d0
0afd1e2
 
 
 
 
 
 
76dc4d0
0afd1e2
 
 
 
 
 
 
 
 
76dc4d0
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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


# =====================================================
# ROUTER BUILDER
# =====================================================

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"])

    # =================================================
    # EXECUTE TASK
    # =================================================
    @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:
            # -----------------------------------------
            # SAVE UPLOADED FILE
            # -----------------------------------------
            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

            # -----------------------------------------
            # BUILD INPUT PAYLOAD
            # -----------------------------------------
            payload = {
                "file_path": temp_path,
                "url_input": url_input,
            }

            # -----------------------------------------
            # EXECUTE TASK
            # -----------------------------------------
            result = await execute_task(task_name, payload)

            # -----------------------------------------
            # FILE RESPONSE
            # -----------------------------------------
            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),
                    )

            # -----------------------------------------
            # JSON RESPONSE
            # -----------------------------------------
            return JSONResponse(result)

        except Exception as e:
            raise HTTPException(
                status_code=500,
                detail=str(e),
            )

        finally:
            # -----------------------------------------
            # CLEANUP TEMP FILE
            # -----------------------------------------
            if temp_path and os.path.exists(temp_path):
                os.unlink(temp_path)

    # =================================================
    # TASK LIST
    # =================================================
    @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()
        }

    # =================================================
    # HEALTH CHECK
    # =================================================
    @router.get("/health")
    async def health():
        return {
            "status": "ok",
            "tasks_loaded": len(get_tasks()),
        }

    return router