Download openenv/flood_openenv/server.py from bpHigh/FloodGate: direct link, hf CLI and curl.
- Browser
- Download file 5.35 kB
-
https://huggingface.co/spaces/bpHigh/FloodGate/resolve/main/openenv/flood_openenv/server.py
- Command line
-
hf download hf://spaces/bpHigh/FloodGate/openenv/flood_openenv/server.py
-
curl -L -o server.py https://huggingface.co/spaces/bpHigh/FloodGate/resolve/main/openenv/flood_openenv/server.py
5.35 kB
| """The server: OpenEnv's app plus read-only JSON about the tasks on the same port. | |
| OpenEnv provides `/reset`, `/step`, `/state`, `/schema`, `/ws`, `/mcp`, `/health`, the Task API and its web UI at | |
| `/web`. We add: | |
| /api/tasks task summaries with the references' costs | |
| /api/tasks/{id} a public task (what the agent sees, structured) | |
| /api/tasks/{id}/reference the optimum and the baselines - for people; no tool shows them | |
| /api/episodes live episodes on this server (newest first) | |
| /api/tasks/{id}/plans the plans the replay can show: optimum, baselines, the Corps, live policies, and | |
| every model's plan in the committed runs (results/rollouts, or FLOOD_RUNS_DIR) | |
| /api/tasks/{id}/replay?plan=... a plan on the true river: releases, storage, gauge flows, flood categories, cost | |
| /twin/ the 3D replay of the basin (USGS terrain and hydrography) for any plan | |
| uvicorn flood_openenv.server:app --port 8000 | |
| """ | |
| from __future__ import annotations | |
| import os | |
| from pathlib import Path | |
| from fastapi import HTTPException | |
| from fastapi.responses import RedirectResponse | |
| from fastapi.staticfiles import StaticFiles | |
| from openenv.core.env_server.http_server import create_app | |
| from openenv.core.env_server.mcp_types import CallToolAction, CallToolObservation | |
| from flood_core import TaskPack, load_pack | |
| try: | |
| from .environment import STORE, FloodOpsEnvironment, FloodState | |
| except ImportError: | |
| from environment import STORE, FloodOpsEnvironment, FloodState | |
| ENV_NAME = "flood_ops" | |
| WEB = Path(__file__).resolve().parent / "web" | |
| _UP = Path(__file__).resolve().parents | |
| RUNS_DIR = Path(os.environ.get("FLOOD_RUNS_DIR") or (_UP[4] if len(_UP) > 4 else _UP[-1]) / "results" / "rollouts") | |
| def mount_api(app, pack: TaskPack): | |
| def tasks(): | |
| return [{"task_id": t["task_id"], "split": t["split"], "tier": t["tier"], "start_local": t["start_local"], | |
| "steps": t["steps"], **{k: v for k, v in t["reference"].items() if k.endswith("_cost")}} | |
| for t in pack.tasks] | |
| def _get(tid: str) -> dict: | |
| try: | |
| return pack.get(tid) | |
| except KeyError: | |
| raise HTTPException(404, f"no task {tid}") from None | |
| def task(tid: str): | |
| return pack.public(_get(tid)) | |
| def reference(tid: str): | |
| return _get(tid)["reference"] | |
| def episodes(n: int = 50): | |
| return [e.summary() for e in STORE.recent(n)] | |
| from flood_core.replay import plans as _plans | |
| from flood_core.replay import replay as _replay | |
| def task_plans(tid: str): | |
| return _plans(_get(tid), RUNS_DIR) | |
| def task_replay(tid: str, plan: str = "optimum"): | |
| try: | |
| return _replay(_get(tid), plan, RUNS_DIR) | |
| except KeyError as e: | |
| raise HTTPException(404, str(e)) from None | |
| def twin_slash(): | |
| return RedirectResponse("/twin/") | |
| app.mount("/twin/", StaticFiles(directory=WEB / "twin", html=True), name="twin") | |
| async def no_stale_pages(request, call_next): | |
| # browsers cache static pages without Cache-Control and keep showing an old replay after a deploy | |
| resp = await call_next(request) | |
| if request.url.path.startswith("/twin"): | |
| resp.headers["Cache-Control"] = "no-cache" | |
| return resp | |
| def build_app(pack: TaskPack | None = None, mode: str | None = None): | |
| """FLOOD_MODE=live serves live mode (forecast scenarios, block commits); the default is plan mode.""" | |
| pack = pack or load_pack() | |
| mode = mode or os.environ.get("FLOOD_MODE", "plan") | |
| if mode == "live": | |
| try: | |
| from .live_env import FloodLiveEnvironment as Env | |
| except ImportError: | |
| from live_env import FloodLiveEnvironment as Env | |
| else: | |
| Env = FloodOpsEnvironment | |
| def factory(): | |
| return Env(pack) | |
| kw = {} | |
| if os.environ.get("ENABLE_WEB_INTERFACE", "").lower() == "true": | |
| try: | |
| from .gradio_ui import build_ui | |
| except ImportError: | |
| from gradio_ui import build_ui | |
| kw = dict(gradio_builder=build_ui, custom_tab_name="Explore", custom_tab_primary=True, show_default_tab=True, | |
| title_override=f"FloodGate v1 ({mode} mode)") | |
| app = create_app(factory, CallToolAction, CallToolObservation, env_name=ENV_NAME, | |
| max_concurrent_envs=int(os.environ.get("MAX_CONCURRENT_ENVS", "64")), state_cls=FloodState, **kw) | |
| mount_api(app, pack) | |
| def healthz(): | |
| return {"status": "ok", "mode": mode, "tasks": {s: pack.count(s) for s in pack.splits()}} | |
| if not kw: | |
| def root(): | |
| return RedirectResponse("/twin/") | |
| return app | |
| _app = None | |
| def __getattr__(name: str): | |
| global _app | |
| if name == "app": | |
| if _app is None: | |
| _app = build_app() | |
| return _app | |
| raise AttributeError(name) | |