This repository was archived by the owner on Feb 2, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
191 lines (151 loc) · 6.42 KB
/
main.py
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# ====================== [TinyGen] ======================
# Copyright (C) 2024 Edward Li - All Rights Reserved
# =======================================================
import uuid
from fastapi import FastAPI, Request, Response, BackgroundTasks, HTTPException
from fastapi.responses import FileResponse, HTMLResponse
from pydantic import BaseModel
from task import TaskManager, TaskStatus
from tinygen import TinyGenTask
# Create a FastAPI instance
app = FastAPI()
# Create a global TaskManager instance
task_manager = TaskManager()
# Define a Pydantic model for the input data
class GenerateInput(BaseModel):
repoUrl: str
prompt: str
openaiKey: str
# === Root Route ===
@app.get("/")
async def route_root():
return FileResponse("static/index.html")
# === Start TinyGen Route ===
@app.post("/generate")
async def route_generate(request: Request, background_tasks: BackgroundTasks, data: GenerateInput):
# Create a new task with the repo and prompt
task = TinyGenTask(uuid.uuid4(), data.repoUrl, data.prompt, openai_key=data.openaiKey)
task_manager.add_task(task)
# Start the task in the background
background_tasks.add_task(task.run_tinygen)
# Return the task_id and task_url
return {"task_id": str(task.task_id), "task_url": f"{request.base_url}task/{task.task_id}"}
# === Task Status Route ===
@app.get("/task/{task_id_str}")
async def route_get_task(request: Request, task_id_str: str):
# Convert the task_id_str to a UUID
try:
task_id = uuid.UUID(task_id_str)
except ValueError:
raise HTTPException(status_code=400, detail=f"Invalid task_id: {task_id_str}")
# Check if the task exists
if not task_manager.task_exists(task_id):
raise HTTPException(status_code=404, detail=f"Task {task_id_str} not found")
# Get the task
task = task_manager.get_task(task_id)
return {
"task_id": str(task.task_id),
"repo_url": task.repo_url,
"prompt": task.prompt,
"status": task.status.value,
"result_url": f"{request.base_url}task/{task.task_id}/result",
"logs_url": f"{request.base_url}task/{task.task_id}/logs",
"start_time": task.start_time.isoformat() if task.start_time else "",
"end_time": task.end_time.isoformat() if task.end_time else "",
"elapsed_time": task.elapsed_time
}
# === Task Result Route ===
@app.get("/task/{task_id_str}/result")
async def route_get_result(task_id_str: str, format: bool = False):
# Convert the task_id_str to a UUID
try:
task_id = uuid.UUID(task_id_str)
except ValueError:
return Response(f"Invalid task_id: {task_id_str}", status_code=400, media_type="text/plain")
# Check if the task exists
if not task_manager.task_exists(task_id):
return Response(f"Task {task_id_str} not found.", status_code=409, media_type="text/plain")
# Get the task
task = task_manager.get_task(task_id)
# Check if the task is done
if not task.is_done():
return Response("Task Still Pending...", status_code=404, media_type="text/plain")
if format:
# Format the diff output and return as HTML
lines = task.result.split('\n') if task.result else []
formatted_lines = []
for line in lines:
if line.startswith('+'):
formatted_line = f"<span style='color: green;'>{line}</span>"
elif line.startswith('-'):
formatted_line = f"<span style='color: red;'>{line}</span>"
elif line.startswith('@@'):
formatted_line = f"<span style='color: blue;'>{line}</span>"
else:
formatted_line = line
formatted_lines.append(formatted_line)
formatted_diff = '<br>'.join(formatted_lines)
html_output = f"<pre style='word-wrap: break-word; white-space: pre-wrap;'>{formatted_diff}</pre>"
return HTMLResponse(html_output)
else:
# Return the result
return Response(task.result, media_type="text/plain")
# === Task Logs Route ===
@app.get("/task/{task_id_str}/logs")
async def route_get_logs(task_id_str: str, follow: bool = False):
# Convert the task_id_str to a UUID
try:
task_id = uuid.UUID(task_id_str)
except ValueError:
return Response(f"Invalid task_id: {task_id_str}", status_code=400, media_type="text/plain")
# Check if the task exists
if not task_manager.task_exists(task_id):
return Response(f"Task {task_id_str} not found.", status_code=409, media_type="text/plain")
# Get the task
task = task_manager.get_task(task_id)
# Generate HTML Content
if follow:
# Create base HTML content
html_resp = "<html><body><pre style='word-wrap: break-word; white-space: pre-wrap;'>"
# If not done, refresh page after 1 second
if task.status == TaskStatus.PENDING:
html_resp += "\n".join(task.logs)
html_resp += "</pre>"
html_resp += "<meta http-equiv='refresh' content='1'>"
html_resp += "</body></html>"
# If done, redirect to result page
elif task.status == TaskStatus.DONE:
html_resp += "\n".join(task.logs)
html_resp += "</pre>"
html_resp += f"<meta http-equiv='refresh' content='5; url=/task/{task_id_str}/result?format=true'>"
html_resp += "</body></html>"
# If error, or any other status, keep the logs page
else:
html_resp += "\n".join(task.logs)
html_resp += "</pre></body></html>"
# Return the logs
return HTMLResponse(html_resp)
else:
return Response("\n".join(task.logs), media_type="text/plain")
# === Task Cancel Route ===
@app.delete("/task/{task_id_str}/cancel")
async def route_cancel_task(task_id_str: str):
# Convert the task_id_str to a UUID
try:
task_id = uuid.UUID(task_id_str)
except ValueError:
raise HTTPException(status_code=400, detail=f"Invalid task_id: {task_id_str}")
# Check if the task exists
if not task_manager.task_exists(task_id):
raise HTTPException(status_code=404, detail=f"Task {task_id_str} not found")
# Get the task
task = task_manager.get_task(task_id)
# Cancel the task
task.cancel()
# Return the task_id and status
return {"task_id": str(task.task_id), "status": task.status.value}
# === Health Check Route ===
@app.get("/health")
async def route_health():
task_summary = task_manager.get_task_summary()
return task_summary