Spaces:
Sleeping
Sleeping
File size: 5,116 Bytes
877b38e eb71740 877b38e | 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 | # main.py
from fastapi import FastAPI, HTTPException, BackgroundTasks
from pydantic import BaseModel
import requests,time, os
from dotenv import load_dotenv
from github import Github # from PyGithub
from llm_utils import generate_app_files # your LLM logic
from typing import Optional, List, Dict
app = FastAPI()
load_dotenv() # take environment variables from .env
SHARED_SECRET = os.getenv("SECRET_KEY")
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
class TaskRequest(BaseModel):
email: str
task: str
brief: str
checks: List[str]
round: int
nonce: str
secret: str
evaluation_url: str
attachments: Optional[List[Dict[str, str]]] = None # added to accept attachments like data URIs
@app.get("/")
def root():
return {"status": "ok"}
async def process_task_in_background(req: TaskRequest):
# 2. Generate files and handle repo based on round
app_files = generate_app_files(
brief=req.brief,
checks=req.checks,
attachments=req.attachments,
round=req.round,
task=req.task
)
# Validate LLM output
if not isinstance(app_files, dict) or "index" not in app_files or "README" not in app_files:
raise HTTPException(status_code=500, detail="LLM did not return expected file structure")
# Initialize GitHub client
g = Github(GITHUB_TOKEN)
user = g.get_user()
repo_name = f"{req.task}"
if req.round == 1:
# Round 1: Create new repo
try:
repo = user.create_repo(repo_name, private=False, auto_init=False, license_template="mit")
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to create repo: {e}")
else:
# Round >1: Get existing repo and update
try:
# Use get_repo with full path
repo = g.get_repo(f"{user.login}/{repo_name}")
except Exception as e:
raise HTTPException(status_code=404, detail=f"Repository not found: {e}")
# Prepare files to commit
files_to_commit = {
"index.html": app_files["index"],
"README.md": app_files["README"],
}
if isinstance(app_files.get("assets"), dict):
files_to_commit.update(app_files["assets"])
# Add/Update files & commit
for path, content in files_to_commit.items():
try:
if req.round == 1:
# Create new file for round 1
repo.create_file(path, f"add {path}", content)
else:
# Update existing file for later rounds
try:
# Get current file content
file = repo.get_contents(path)
# Update file
repo.update_file(path, f"update {path} for round {req.round}", content, file.sha)
except Exception:
# File doesn't exist, create it
repo.create_file(path, f"add {path} for round {req.round}", content)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to handle file {path}: {e}")
# Enable GitHub Pages only for round 1
if req.round == 1:
try:
requests.post(
f"https://api.github.com/repos/{user.login}/{repo_name}/pages",
headers={
"Authorization": f"token {GITHUB_TOKEN}",
"Accept": "application/vnd.github.v3+json",
},
json={"source": {"branch": "main", "path": "/"}}
)
except Exception:
pass
# Get latest commit SHA
commit_sha = repo.get_commits()[0].sha
# Prepare evaluation JSON
payload = {
"email": req.email,
"task": req.task,
"round": req.round,
"nonce": req.nonce,
"repo_url": repo.html_url,
"commit_sha": commit_sha,
"pages_url": f"https://{user.login}.github.io/{repo_name}/",
}
time.sleep(60)
# 8. POST to evaluation URL (with exponential backoff) — include JSON Content-Type & try up to 5 times
delay = 1
headers = {"Content-Type": "application/json"}
for _ in range(5):
try:
r = requests.post(req.evaluation_url, json=payload, headers=headers, timeout=10)
if r.status_code == 200:
break
except Exception:
pass
time.sleep(delay)
delay *= 2
@app.post("/task1")
async def handle_task(req: TaskRequest, background_tasks: BackgroundTasks):
# 1. Secret verification
if req.secret != SHARED_SECRET:
raise HTTPException(status_code=403, detail="Invalid secret")
if req.email!="22f3000730@ds.study.iitm.ac.in":
raise HTTPException(status_code=403, detail="Invalid email")
# Add the processing to background tasks
background_tasks.add_task(process_task_in_background, req)
# Return simple acknowledgment
return {"status": "accepted", "message": "Request received and processing"}
if __name__ == "__main__":
import uvicorn
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True) |