Files
pr-agent-server/src/callback_server.py
T
asepharyana bc8e1739e9 refactor: restructure into proper project layout + improve docs
Project layout:
- src/: application modules (run_server, auto_merge_bot, health-check, sync-key, trivial_merge, callback_server, start_server)
- scripts/: setup/deployment helpers (setup_all, setup_app, generate_manifest)
- templates/: manifest.json (GitHub App manifest template)
- docs/  + CONTRIBUTING.md: documentation

Improvements:
- flake.nix: added pr-agent-auto-merge wrapper binary, updated installPhase paths
- deploy.yml: syntax check covers all modules including health-check.py and sync-key.py
- README.md: comprehensive with architecture, layout, dev, ops, deployment
- CONTRIBUTING.md: standards and testing checklist
- .gitignore: added *.log, *.pid, .env.*
- Cleanup: removed duplicate manifest_current.json / manifest_final.json
- Fix: health-check.py docstring updated to claude-opus-5

Verification:
-  python3 -m py_compile: all 11 modules pass
-  nix flake check: passes
2026-08-20 11:38:24 +07:00

55 lines
2.1 KiB
Python

#!/usr/bin/env python3
"""Quick callback server to receive GitHub App credentials after manifest creation"""
import json, os, sys
sys.path.insert(0, os.path.expanduser("~/hermes-agent/.venv/lib/python3.12/site-packages"))
from fastapi import FastAPI, Request
import uvicorn
app = FastAPI()
@app.get("/setup/callback")
@app.post("/setup/callback")
async def callback(request: Request):
params = dict(request.query_params)
print(f"[CALLBACK] Received params: {json.dumps(params, indent=2)}")
# If we got a code, exchange it for credentials
if "code" in params:
import httpx
code = params["code"]
print(f"[CALLBACK] Exchanging code: {code[:20]}...")
async with httpx.AsyncClient() as client:
resp = await client.post(
f"https://api.github.com/app-manifests/{code}/conversions",
headers={"Accept": "application/vnd.github.v3+json"}
)
if resp.status_code == 201:
data = resp.json()
# Save credentials
creds = {
"app_id": data.get("id"),
"app_slug": data.get("slug"),
"pem": data.get("pem"),
"webhook_secret": data.get("webhook_secret"),
"client_id": data.get("client_id"),
"client_secret": data.get("client_secret")
}
with open("/opt/pr-agent-server/app_credentials.json", "w") as f:
json.dump(creds, f, indent=2)
print(f"[CALLBACK] App created! ID: {creds['app_id']}, Slug: {creds['app_slug']}")
return {"status": "success", "app_id": creds["app_id"], "app_slug": creds["app_slug"]}
else:
print(f"[CALLBACK] Exchange failed: {resp.status_code} - {resp.text}")
return {"status": "error", "detail": resp.text}
return {"status": "waiting", "params": params}
@app.get("/health")
async def health():
return {"status": "ok"}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=3000, log_level="info")