File size: 3,770 Bytes
03d4a62 dfe8917 9b30c36 03d4a62 9b30c36 03d4a62 dfe8917 03d4a62 9b30c36 03d4a62 9b30c36 a1853a9 | 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 | from typing import Optional
from fastapi import FastAPI, HTTPException, Body
from fastapi.responses import HTMLResponse
from pydantic import BaseModel
from environment.env import CodeSentinelEnv
from environment.models import (
Action, TaskId, StepResponse, ResetResponse,
EnvironmentState, ValidateResponse, Observation
)
app = FastAPI(
title = "CodeSentinel OpenEnv",
description = "AI environment for automated code review agents",
version = "1.0.0",
)
env = CodeSentinelEnv()
class ResetRequest(BaseModel):
task_id: TaskId = TaskId.bug_detection
seed: int = 42
@app.get("/", response_class=HTMLResponse, include_in_schema=False)
def root():
return """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CodeSentinel — AI Code Review Environment</title>
<meta name="description" content="OpenEnv-compliant AI training environment for code review agents.">
<style>
body{font-family:system-ui,sans-serif;max-width:860px;margin:2rem auto;padding:0 1rem;background:#0d1117;color:#e6edf3;}
h1{font-size:2rem;color:#58a6ff;}
h2{color:#79c0ff;border-bottom:1px solid #30363d;padding-bottom:.4rem;}
a{color:#58a6ff;}
table{border-collapse:collapse;width:100%;margin:1rem 0;}
th,td{border:1px solid #30363d;padding:.5rem 1rem;text-align:left;}
th{background:#161b22;}
code{background:#161b22;padding:2px 6px;border-radius:4px;}
.easy{color:#3fb950;}.medium{color:#d29922;}.hard{color:#f85149;}
</style>
</head>
<body>
<h1>🛡️ CodeSentinel</h1>
<p>A real-world OpenEnv environment where AI agents learn to review code like a senior engineer.</p>
<h2>Tasks</h2>
<table>
<tr><th>Task</th><th>Difficulty</th><th>Max Steps</th></tr>
<tr><td>bug_detection</td><td class="easy">Easy</td><td>20</td></tr>
<tr><td>security_audit</td><td class="medium">Medium</td><td>30</td></tr>
<tr><td>architecture_review</td><td class="hard">Hard</td><td>50</td></tr>
</table>
<h2>API</h2>
<ul>
<li><a href="/validate">GET /validate</a> — Health check</li>
<li><a href="/docs">GET /docs</a> — Swagger UI</li>
<li>POST /reset — Start episode</li>
<li>POST /step — Submit action</li>
<li>GET /state — Inspect state</li>
</ul>
</body>
</html>
"""
@app.get("/validate", response_model=ValidateResponse)
def validate():
return ValidateResponse(
valid = True,
version = "1.0.0",
tasks = ["bug_detection", "security_audit", "architecture_review"],
message = "CodeSentinel is healthy and ready.",
)
@app.post("/reset", response_model=Observation)
def reset(req: Optional[ResetRequest] = Body(None)):
if req is None:
req = ResetRequest()
try:
resp = env.reset(task_id=req.task_id, seed=req.seed)
return resp.observation
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.post("/step", response_model=StepResponse)
def step(action: Action):
try:
return env.step(action)
except RuntimeError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
import traceback
traceback.print_exc()
raise HTTPException(status_code=500, detail=str(e))
@app.get("/state", response_model=EnvironmentState)
def state():
try:
return env.state()
except RuntimeError as e:
raise HTTPException(status_code=400, detail=str(e))
def main():
import uvicorn
uvicorn.run("server.app:app", host="0.0.0.0", port=7860)
if __name__ == "__main__":
main()
|