Spaces:
Sleeping
Sleeping
| # server/app.py | |
| import os | |
| from fastapi.responses import HTMLResponse | |
| from fastapi import WebSocket, WebSocketDisconnect | |
| from dataclasses import asdict | |
| # Support both in-repo and standalone imports | |
| try: | |
| # In-repo imports (when running from OpenEnv repository) | |
| from openenv.core.env_server import create_fastapi_app | |
| from openenv.core.env_server.web_interface import load_environment_metadata, WebInterfaceManager | |
| from openenv.core.env_server.types import Action, Observation | |
| from ..models import WildfireAction, WildfireObservation | |
| from .wildfire_environment import WildfireEnvironment | |
| from .wildfire_web_interface import get_wildfire_web_interface_html | |
| except ImportError: | |
| # Standalone imports (when environment is standalone with openenv-core from pip) | |
| from openenv_core.env_server import create_fastapi_app | |
| from openenv_core.env_server.web_interface import load_environment_metadata, WebInterfaceManager | |
| from openenv_core.env_server.types import Action, Observation | |
| from wildfire_env.models import WildfireAction, WildfireObservation | |
| from wildfire_env.server.wildfire_environment import WildfireEnvironment | |
| from wildfire_env.server.wildfire_web_interface import get_wildfire_web_interface_html | |
| W = int(os.getenv("WILDFIRE_WIDTH", "16")) | |
| H = int(os.getenv("WILDFIRE_HEIGHT", "16")) | |
| # Factory function to create WildfireEnvironment instances | |
| def create_wildfire_environment(): | |
| """Factory function that creates WildfireEnvironment with config.""" | |
| return WildfireEnvironment(width=W, height=H) | |
| # Check if web interface should be enabled | |
| # This can be controlled via environment variable | |
| enable_web = ( | |
| os.getenv("ENABLE_WEB_INTERFACE", "false").lower() in ("true", "1", "yes") | |
| ) | |
| if enable_web: | |
| # Create an instance for metadata loading (load_environment_metadata needs an instance) | |
| env_instance = create_wildfire_environment() | |
| metadata = load_environment_metadata(env_instance, 'wildfire_env') | |
| # Create base app without web interface first | |
| # Pass the factory function instead of an instance for WebSocket session support | |
| app = create_fastapi_app(create_wildfire_environment, WildfireAction, WildfireObservation) | |
| # Create web interface manager (needed for /web/reset, /web/step, /ws endpoints) | |
| # WebInterfaceManager expects an Environment instance, not a callable | |
| web_manager = WebInterfaceManager(env_instance, WildfireAction, WildfireObservation, metadata) | |
| # Add our custom wildfire interface route | |
| async def wildfire_web_interface(): | |
| """Custom wildfire-specific web interface.""" | |
| return get_wildfire_web_interface_html(metadata) | |
| # Add web interface endpoints (these are needed for the interface to work) | |
| async def web_metadata(): | |
| """Get environment metadata.""" | |
| return asdict(metadata) | |
| async def websocket_endpoint(websocket: WebSocket): | |
| """WebSocket endpoint for real-time updates.""" | |
| await web_manager.connect_websocket(websocket) | |
| try: | |
| while True: | |
| # Keep connection alive | |
| await websocket.receive_text() | |
| except WebSocketDisconnect: | |
| await web_manager.disconnect_websocket(websocket) | |
| async def web_reset(): | |
| """Reset endpoint for web interface.""" | |
| return await web_manager.reset_environment() | |
| async def web_step(request: dict): | |
| """Step endpoint for web interface.""" | |
| action_data = request.get("action", {}) | |
| return await web_manager.step_environment(action_data) | |
| async def web_state(): | |
| """State endpoint for web interface.""" | |
| return web_manager.get_state() | |
| def main(): | |
| """Main entry point for running the server.""" | |
| import uvicorn | |
| port = int(os.getenv("PORT", "8000")) | |
| uvicorn.run(app, host="0.0.0.0", port=port) | |
| if __name__ == "__main__": | |
| main() | |