Spaces:
Sleeping
Sleeping
| """ | |
| Pure HTML investigation dashboard: persistent env + JSON API. | |
| OpenEnv's HTTP POST /reset and /step spin up a new environment each call, | |
| so this UI uses a singleton AdFraudEnvironment for multi-step episodes. | |
| Does not replace /ws or competition endpoints. | |
| """ | |
| from __future__ import annotations | |
| from pathlib import Path | |
| from typing import Any, Dict, Optional | |
| from fastapi import Body, FastAPI, HTTPException | |
| from fastapi.responses import FileResponse, RedirectResponse | |
| from fastapi.staticfiles import StaticFiles | |
| from openenv.core.env_server import serialize_observation | |
| from pydantic import BaseModel, Field | |
| try: | |
| from ..models import AdReviewAction | |
| from .environment import AdFraudEnvironment | |
| except ImportError: | |
| from models import AdReviewAction | |
| from server.environment import AdFraudEnvironment | |
| _ui_env: Optional[AdFraudEnvironment] = None | |
| def _get_ui_env() -> AdFraudEnvironment: | |
| global _ui_env | |
| if _ui_env is None: | |
| _ui_env = AdFraudEnvironment() | |
| return _ui_env | |
| class UIResetBody(BaseModel): | |
| task_id: str = Field(default="task_1") | |
| seed: int = Field(default=42, ge=0) | |
| def register_investigate_ui(app: FastAPI) -> None: | |
| static_dir = Path(__file__).resolve().parent / "static" | |
| async def root_to_investigate() -> RedirectResponse: | |
| return RedirectResponse(url="/investigate", status_code=302) | |
| async def web_to_investigate() -> RedirectResponse: | |
| return RedirectResponse(url="/investigate", status_code=302) | |
| app.mount("/static", StaticFiles(directory=str(static_dir)), name="static") | |
| async def investigate_page() -> FileResponse: | |
| path = static_dir / "investigate_hq.html" | |
| if not path.is_file(): | |
| raise HTTPException(status_code=404, detail="investigate_hq.html missing") | |
| return FileResponse(path, media_type="text/html; charset=utf-8") | |
| async def investigate_api_reset(body: UIResetBody) -> Dict[str, Any]: | |
| env = _get_ui_env() | |
| obs = env.reset(task_id=body.task_id, seed=body.seed) | |
| return serialize_observation(obs) | |
| async def investigate_api_step(body: Dict[str, Any] = Body(...)) -> Dict[str, Any]: | |
| try: | |
| action = AdReviewAction(**body) | |
| except Exception as e: | |
| raise HTTPException(status_code=422, detail=str(e)) from e | |
| env = _get_ui_env() | |
| obs = env.step(action) | |
| return serialize_observation(obs) | |
| async def investigate_api_state() -> Dict[str, Any]: | |
| return _get_ui_env().state.model_dump() | |