Files
2026-10-05 00:19:55 +02:00

92 lines
2.8 KiB
Python

import os
import requests
from fastapi import FastAPI, HTTPException, status
from openai import OpenAI
from pydantic import BaseModel
allowed_host_env = os.getenv("LLM_REVIEW_ALLOWED_HOST")
allowed_hosts = []
allowed_hosts_not_empty = True
if allowed_host_env is None:
allowed_hosts_not_empty = False
else:
allowed_hosts = allowed_host_env.split(',')
if len(allowed_hosts) == 0:
allowed_hosts_not_empty = False
for (i, host) in enumerate(allowed_hosts):
allowed_hosts[i] = host.rstrip('/')
print(f'allowed host: {allowed_hosts}')
app = FastAPI()
class ReviewRequest(BaseModel):
gitea_token: str
gitea_host: str
openrouter_key: str
model: str
repo: str
pr_number: int
@app.get("/health")
def test():
try:
r = requests.get("https://openrouter.ai/api/v1/models")
r.raise_for_status()
return {"status": "ok"}
except requests.exceptions.RequestException as e:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail=f"OpenRouter health check failed: {e}",
)
@app.post("/")
def review(
request_body: ReviewRequest,
):
gitea_host = request_body.gitea_host.rstrip("/")
if allowed_hosts_not_empty and gitea_host not in allowed_hosts:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Request source is not allowed host",
)
headers = {"Authorization": f"token {request_body.gitea_token}"}
diff_res = requests.get(f"{gitea_host}/api/v1/repos/{request_body.repo}/pulls/{request_body.pr_number}.diff", headers=headers)
if diff_res.status_code != 200 or not diff_res.text.strip():
return
diff_text = diff_res.text
client = OpenAI(base_url="https://openrouter.ai/api/v1", api_key=request_body.openrouter_key)
prompt = (
"You are an automated senior code reviewer. Review the following git diff.\n"
"Focus on: critical bugs, security vulnerabilities, edge cases, and code smells.\n"
"Keep it short and clear, don't give me long solutions.\n"
"Dont point out good things only problems, errors, etc.\n"
"Format your answer cleanly in Markdown with actionable feedback.\n\n"
f"```diff\n{diff_text}\n```"
)
completion = client.chat.completions.create(
model=request_body.model,
messages=[{"role": "user", "content": prompt}]
)
review_content = completion.choices[0].message.content
review_body = f"# llm review\n\n{review_content}"
requests.post(
f"{gitea_host}/api/v1/repos/{request_body.repo}/pulls/{request_body.pr_number}/reviews",
headers=headers,
json={"body": review_body, "event": "COMMENT"}
)
return {"status": "done"}