Yaswanth-Bolla's picture
add uv.lock
bbbb404
"""
Thin FastAPI server — marshals JSON in/out.
No simulation logic lives here.
"""
from __future__ import annotations
from typing import Any, Dict, Optional
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from .incident_environment import IncidentEnvironment
# ------------------------------------------------------------------
# App
# ------------------------------------------------------------------
app = FastAPI(
title="SRE Incident Response Environment",
description="An OpenEnv environment for training AI agents on production incident response.",
version="0.1.0",
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
env = IncidentEnvironment()
# ------------------------------------------------------------------
# Request / Response models (thin wrappers)
# ------------------------------------------------------------------
class ResetRequest(BaseModel):
task_name: Optional[str] = None
seed: Optional[int] = None
class StepRequest(BaseModel):
action_type: str
target_service: Optional[str] = None
parameters: Dict[str, Any] = {}
# ------------------------------------------------------------------
# Endpoints
# ------------------------------------------------------------------
@app.get("/health")
def health() -> Dict[str, str]:
"""Health check — the validator pings this first."""
return {"status": "healthy"}
from fastapi import Request
@app.post("/reset")
async def reset(request: Request) -> Dict[str, Any]:
"""
Initialize a new incident episode.
POST /reset {"task_name": "memory_leak", "seed": 42}
"""
try:
body = await request.json()
except Exception:
body = {}
if not isinstance(body, dict):
body = {}
result = env.reset(
task_name=body.get("task_name"),
seed=body.get("seed"),
)
return result
@app.post("/step")
def step(request: StepRequest) -> Dict[str, Any]:
"""
Execute one agent action.
POST /step {"action_type": "view_alerts"}
"""
action_data = {
"action_type": request.action_type,
"target_service": request.target_service,
"parameters": request.parameters,
}
result = env.step(action_data)
return result
@app.get("/state")
def state() -> Dict[str, Any]:
"""
Get current episode metadata.
GET /state
"""
return env.get_state()
@app.get("/tasks")
def list_tasks() -> Dict[str, Any]:
"""List available tasks with descriptions."""
from ..tasks import TASK_REGISTRY
tasks = {}
for name, cls in TASK_REGISTRY.items():
scenario = cls()
tasks[name] = {
"display_name": scenario.display_name,
"severity": scenario.severity,
"max_steps": scenario.max_steps,
"time_budget_minutes": scenario.time_budget_minutes,
}
return {"tasks": tasks}
def main():
import uvicorn
uvicorn.run("incident_env.server.app:app", host="0.0.0.0", port=8000, reload=False)
if __name__ == "__main__":
main()