Spaces:
Sleeping
Sleeping
| # api_server.py | |
| # FastAPI wrapper for FORGE-v4 Environment (OpenEnv standard). | |
| import os | |
| import random | |
| from typing import Any, List, Optional | |
| import uvicorn | |
| from fastapi import FastAPI, HTTPException | |
| from pydantic import BaseModel | |
| from config import GLOBAL_RANDOM_SEED | |
| from env import FORGEEnv | |
| from memory import CoachMemory | |
| app = FastAPI(title="FORGE-v4 OpenEnv API") | |
| # Persistent environment instance | |
| memory = CoachMemory() | |
| env = FORGEEnv(memory=memory) | |
| class Action(BaseModel): | |
| coder_code: str | |
| coder_version: str = "unknown" | |
| candidate_solutions: Optional[List[str]] = None | |
| async def reset(): | |
| """Reset the environment and return the initial state.""" | |
| # Default: varied tasks per reset (real sandbox episodes). Set FORGE_DETERMINISTIC_RESET=1 | |
| # to re-seed RNG for harnesses that need identical first-task distributions. | |
| if os.getenv("FORGE_DETERMINISTIC_RESET", "").strip().lower() in ("1", "true", "yes"): | |
| random.seed(GLOBAL_RANDOM_SEED) | |
| state = env.reset() | |
| return state | |
| async def step(action: Action): | |
| """Perform a step in the environment.""" | |
| try: | |
| # exclude_none: otherwise candidate_solutions=None breaks env (get() returns None, not default []). | |
| result = env.step(action.model_dump(exclude_none=True)) | |
| return result | |
| except RuntimeError as e: | |
| raise HTTPException(status_code=400, detail=str(e)) | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail="Internal Server Error") | |
| async def get_state(): | |
| """Get the current state of the environment.""" | |
| return env.get_state() | |
| async def health(): | |
| return {"status": "healthy", "version": "0.2.0"} | |
| if __name__ == "__main__": | |
| uvicorn.run(app, host="0.0.0.0", port=8000) | |