runway-zero / src /runway_zero /server.py
work-dwivediishivam's picture
Space Redeployed to preserve GPU; switched to FREE TIER; fixed GUI with Actual Replay
90bdd23
from __future__ import annotations
from pathlib import Path
from typing import Any, Dict, List, Optional
from fastapi import FastAPI
from fastapi.responses import FileResponse, JSONResponse
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel, Field
from runway_zero.simulator import RunwayZeroEnv
app = FastAPI(title="Runway Zero", version="0.1.0")
ENV = RunwayZeroEnv(stage=1, seed=7)
WEB_OUT = Path(__file__).resolve().parents[2] / "web" / "out"
class ResetRequest(BaseModel):
stage: int = Field(default=1, ge=1, le=4)
seed: int = 7
class StepRequest(BaseModel):
actions: List[Dict[str, Any]] = Field(default_factory=list)
def environment_metadata() -> Dict[str, Any]:
return {
"name": "Runway Zero",
"description": "OpenEnv airport crisis recovery environment",
"endpoints": {
"reset": "/reset",
"step": "/step",
"state": "/state",
"close": "/close",
"metadata": "/api",
},
"demo": {
"homepage": "/",
"stage_1": "/sim/?stage=1",
"stage_2": "/sim/?stage=2",
"stage_3": "/sim/?stage=3",
"stage_4": "/sim/?stage=4",
"training": "/training/",
},
}
@app.get("/")
def root() -> Any:
index = WEB_OUT / "index.html"
if index.exists():
return FileResponse(index)
return JSONResponse(environment_metadata())
@app.get("/api")
def api_metadata() -> Dict[str, Any]:
return environment_metadata()
@app.get("/healthz")
def healthz() -> Dict[str, str]:
return {"status": "ok"}
@app.post("/reset")
def reset(request: Optional[ResetRequest] = None) -> Dict[str, Any]:
payload = request or ResetRequest()
observation = ENV.reset(stage=payload.stage, seed=payload.seed)
return {"observation": observation, "state": ENV.state}
@app.post("/step")
def step(request: StepRequest) -> Dict[str, Any]:
result = ENV.step(request.actions)
return {
"observation": result.observation,
"reward": result.reward,
"done": result.done,
"info": result.info,
}
@app.get("/state")
def state() -> Dict[str, Any]:
return ENV.state
@app.post("/close")
def close() -> Dict[str, str]:
return {"status": "closed"}
if WEB_OUT.exists():
app.mount("/_next", StaticFiles(directory=WEB_OUT / "_next"), name="next-static")
app.mount("/pitch", StaticFiles(directory=WEB_OUT / "pitch", html=True), name="pitch")
app.mount("/sim", StaticFiles(directory=WEB_OUT / "sim", html=True), name="sim")
app.mount("/training", StaticFiles(directory=WEB_OUT / "training", html=True), name="training")