Team Ai
Apppublic

jester1177/cloudnative-devops-debug-env

sourceHugging Faceupdated 6mo agoView on Hugging Face
0likes
app.py242 linesDownload Raw Back to server
1"""FastAPI server for the Cloud-Native DevOps Debug Environment."""2 3from pathlib import Path4from typing import Optional5 6import uvicorn7from fastapi import FastAPI, HTTPException8from fastapi.middleware.cors import CORSMiddleware9from fastapi.responses import HTMLResponse10from fastapi.staticfiles import StaticFiles11 12from server.environment import CloudNativeDebugEnvironment13from server.graders import run_grader14from server.models import (15    Action,16    BaselineRequest,17    BaselineResponse,18    EnvironmentInfo,19    GraderRequest,20    GraderResponse,21    Observation,22    ResetRequest,23    ResetResponse,24    StateResponse,25    StepRequest,26    StepResponse,27    TaskInfo,28)29from server.tasks.task_registry import TASK_REGISTRY30 31STATIC_DIR = Path(__file__).resolve().parent / "static"32 33app = FastAPI(34    title="Cloud-Native Debug Environment",35    description="OpenEnv-style environment for Docker + GitHub Actions + Kubernetes debugging",36    version="1.0.0",37)38 39app.add_middleware(40    CORSMiddleware,41    allow_origins=["*"],42    allow_credentials=True,43    allow_methods=["*"],44    allow_headers=["*"],45)46 47# Serve static assets (CSS, JS, images if needed later)48app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static")49 50env: Optional[CloudNativeDebugEnvironment] = None51 52 53@app.get("/", response_class=HTMLResponse)54async def root():55    html_path = STATIC_DIR / "index.html"56    return HTMLResponse(content=html_path.read_text(encoding="utf-8"), status_code=200)57 58 59@app.get("/health")60async def health():61    return {"status": "healthy"}62 63 64@app.get("/metadata")65async def metadata():66    return {67        "name": "cloud-native-devops-env",68        "description": "Debug broken GitHub Actions workflows, Dockerfiles, and Kubernetes manifests. AI agents identify and fix cloud-native deployment pipeline issues.",69        "version": "1.0.0",70        "author": "Krishna",71        "tags": ["devops", "docker", "github-actions", "kubernetes", "debugging", "infrastructure", "cloud-native"],72    }73 74 75@app.get("/schema")76async def schema():77    return {78        "action": Action.model_json_schema(),79        "observation": Observation.model_json_schema(),80        "state": StateResponse.model_json_schema(),81    }82 83 84@app.post("/mcp")85async def mcp(request: dict = None):86    """JSON-RPC 2.0 MCP endpoint."""87    request = request or {}88    method = request.get("method", "")89    req_id = request.get("id", 1)90 91    if method == "initialize":92        return {93            "jsonrpc": "2.0",94            "id": req_id,95            "result": {96                "protocolVersion": "2024-11-05",97                "capabilities": {"tools": {}},98                "serverInfo": {"name": "cloud-native-devops-env", "version": "1.0.0"},99            },100        }101    elif method == "tools/list":102        return {103            "jsonrpc": "2.0",104            "id": req_id,105            "result": {106                "tools": [107                    {108                        "name": "reset",109                        "description": "Reset the environment and start a new episode",110                        "inputSchema": ResetRequest.model_json_schema(),111                    },112                    {113                        "name": "step",114                        "description": "Take an action in the environment",115                        "inputSchema": Action.model_json_schema(),116                    },117                    {118                        "name": "get_state",119                        "description": "Get the current environment state",120                        "inputSchema": {"type": "object", "properties": {}},121                    },122                ]123            },124        }125    else:126        return {127            "jsonrpc": "2.0",128            "id": req_id,129            "error": {"code": -32601, "message": f"Method not found: {method}"},130        }131 132 133@app.post("/reset", response_model=ResetResponse)134async def reset(request: Optional[ResetRequest] = None):135    global env136 137    request = request or ResetRequest()138    env = CloudNativeDebugEnvironment()139    try:140        observation = env.reset(141            task_id=request.task_id,142            scenario_id=request.scenario_id,143            seed=request.seed,144        )145    except ValueError as exc:146        raise HTTPException(status_code=400, detail=str(exc)) from exc147 148    return ResetResponse(149        observation=observation,150        info={151            "task_id": env.current_task_id,152            "scenario_id": env.current_scenario_id,153            "difficulty": env.current_difficulty,154        },155    )156 157 158@app.post("/step", response_model=StepResponse)159async def step(request: StepRequest):160    global env161 162    if env is None:163        raise HTTPException(status_code=400, detail="Environment not initialized. Call /reset first.")164 165    observation, reward, done, info = env.step(request.action)166    return StepResponse(observation=observation, reward=reward, done=done, info=info)167 168 169@app.get("/state", response_model=StateResponse)170async def get_state():171    global env172 173    if env is None:174        raise HTTPException(status_code=400, detail="Environment not initialized. Call /reset first.")175 176    return StateResponse(177        observation=env.get_observation(),178        episode_reward=env.episode_reward,179        steps_taken=env.step_count,180        done=env.done,181    )182 183 184@app.get("/info", response_model=EnvironmentInfo)185async def get_info():186    tasks = [187        TaskInfo(188            id=task_id,189            name=task_cls.NAME,190            description=task_cls.DESCRIPTION,191            difficulty=task_cls.DIFFICULTY,192            num_scenarios=len(task_cls.SCENARIOS),193        )194        for task_id, task_cls in TASK_REGISTRY.items()195    ]196    return EnvironmentInfo(197        tasks=tasks,198        max_steps=10,199        action_space=Action.model_json_schema(),200        observation_space=Observation.model_json_schema(),201    )202 203 204@app.get("/tasks")205async def get_tasks():206    return {207        "tasks": [208            {209                "id": task_id,210                "name": task_cls.NAME,211                "description": task_cls.DESCRIPTION,212                "difficulty": task_cls.DIFFICULTY.value,213            }214            for task_id, task_cls in TASK_REGISTRY.items()215        ]216    }217 218 219@app.post("/grader", response_model=GraderResponse)220async def grade(request: GraderRequest):221    result = run_grader(task_id=request.task_id, trajectory=request.trajectory)222    return GraderResponse(result=result)223 224 225@app.post("/baseline", response_model=BaselineResponse)226async def run_baseline(request: Optional[BaselineRequest] = None):227    request = request or BaselineRequest()228 229    from baseline_runner import run_baseline_episodes230 231    results = run_baseline_episodes(task_id=request.task_id, num_episodes=request.num_episodes)232    aggregate = sum(r.score for r in results) / len(results) if results else 0.0233    return BaselineResponse(results=results, aggregate_score=aggregate)234 235 236def main():237    uvicorn.run(app, host="0.0.0.0", port=7860)238 239 240if __name__ == "__main__":241    main()242