-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
109 lines (85 loc) · 3.6 KB
/
Copy pathmain.py
File metadata and controls
109 lines (85 loc) · 3.6 KB
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
import os, hmac, hashlib, json
from fastapi import FastAPI, Request, HTTPException, BackgroundTasks
from fastapi.responses import HTMLResponse
from dotenv import load_dotenv
from core.debate import run_debate
from core.github import get_pr_diff, post_comment
from core.memory import get_memory_summary
load_dotenv()
app = FastAPI(title="CodeCouncil", version="2.0.0")
WEBHOOK_SECRET = os.getenv("WEBHOOK_SECRET", "codecouncil123")
def verify_signature(payload: bytes, signature: str) -> bool:
expected = "sha256=" + hmac.new(
WEBHOOK_SECRET.encode(), payload, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
def process_pr(repo: str, pr_number: int):
try:
print(f"\n🔍 Fetching PR #{pr_number} from {repo}...")
diff = get_pr_diff(repo, pr_number)
if len(diff) > 8000:
diff = diff[:8000]
print("⚠️ Diff truncated to 8000 chars")
print(f"📄 Diff fetched ({len(diff)} chars). Starting debate...")
verdict = run_debate(diff, repo=repo)
print("💬 Posting comment to GitHub...")
success = post_comment(repo, pr_number, verdict)
from core.slack import send_slack_notification
send_slack_notification(repo, pr_number, verdict)
if success:
print(f"✅ Comment posted to PR #{pr_number}")
else:
print(f"❌ Failed to post comment to PR #{pr_number}")
except Exception as e:
print(f"❌ Error processing PR #{pr_number}: {e}")
@app.get("/")
def health():
return {
"status": "CodeCouncil running",
"version": "2.0.0",
"agents": ["SecurityAuditor", "PerfEngineer", "CleanCodeReviewer", "TechLead"],
"features": ["parallel execution", "debate rounds", "conflict detection", "confidence calibration", "PR memory"]
}
@app.get("/dashboard", response_class=HTMLResponse)
async def dashboard():
with open("frontend/index.html", "r", encoding="utf-8") as f:
return f.read()
@app.post("/webhook")
async def github_webhook(request: Request, background_tasks: BackgroundTasks):
payload = await request.body()
signature = request.headers.get("X-Hub-Signature-256", "")
if not verify_signature(payload, signature):
raise HTTPException(status_code=401, detail="Invalid signature")
event = request.headers.get("X-GitHub-Event")
data = json.loads(payload)
if event == "pull_request" and data.get("action") in ["opened", "synchronize"]:
repo = data["repository"]["full_name"]
pr_number = data["pull_request"]["number"]
pr_title = data["pull_request"]["title"]
print(f"\n📥 PR received: #{pr_number} — {pr_title}")
background_tasks.add_task(process_pr, repo, pr_number)
return {
"status": "processing",
"pr": pr_number,
"repo": repo,
"message": "Debate started in background"
}
return {"status": "ignored", "event": event}
@app.post("/api/review")
async def api_review(request: Request):
data = await request.json()
repo = data.get("repo")
pr_number = data.get("pr_number")
if not repo or not pr_number:
raise HTTPException(status_code=400, detail="repo and pr_number required")
diff = get_pr_diff(repo, int(pr_number))
if len(diff) > 8000:
diff = diff[:8000]
verdict = run_debate(diff, repo=repo)
post_comment(repo, int(pr_number), verdict)
return verdict
@app.get("/memory/{owner}/{repo_name}")
async def get_memory(owner: str, repo_name: str):
repo = f"{owner}/{repo_name}"
summary = get_memory_summary(repo)
return summary