|
|
|
|
|
|
|
|
|
|
|
|
| """
|
| FastAPI application for the Adaptive Project Manager Environment.
|
|
|
| This module creates an HTTP server that exposes the AdaptiveProjectManagerEnv
|
| over HTTP and WebSocket endpoints, compatible with EnvClient.
|
|
|
| Endpoints:
|
| - POST /reset: Reset the environment
|
| - POST /step: Execute an action
|
| - GET /state: Get current environment state
|
| - GET /schema: Get action/observation schemas
|
| - WS /ws: WebSocket endpoint for persistent sessions
|
|
|
| Usage:
|
| # Development (with auto-reload):
|
| uvicorn server.app:app --reload --host 0.0.0.0 --port 8000
|
|
|
| # Production:
|
| uvicorn server.app:app --host 0.0.0.0 --port 8000 --workers 4
|
|
|
| # Or run directly:
|
| python -m server.app
|
| """
|
|
|
| try:
|
| from openenv.core.env_server.http_server import create_app
|
| except Exception as e:
|
| raise ImportError(
|
| "openenv is required for the web interface. Install dependencies with '\n uv sync\n'"
|
| ) from e
|
|
|
| import os
|
| from pathlib import Path
|
|
|
| from fastapi.responses import HTMLResponse
|
|
|
| try:
|
| from ..models import ProjectAction, ProjectObservation
|
| from .hustlers_env_environment import AdaptiveProjectManagerEnv
|
| from .custom_gradio_ui import build_gradio_ui
|
| except ImportError:
|
| from models import ProjectAction, ProjectObservation
|
| from server.hustlers_env_environment import AdaptiveProjectManagerEnv
|
| from server.custom_gradio_ui import build_gradio_ui
|
|
|
|
|
|
|
|
|
| repo_root = Path(__file__).resolve().parent.parent
|
| readme_path = repo_root / "README.md"
|
| os.environ.setdefault("ENABLE_WEB_INTERFACE", "true")
|
| if readme_path.exists():
|
| os.environ.setdefault("ENV_README_PATH", str(readme_path))
|
|
|
|
|
|
|
| app = create_app(
|
| AdaptiveProjectManagerEnv,
|
| ProjectAction,
|
| ProjectObservation,
|
| env_name="adaptive-project-manager",
|
| max_concurrent_envs=1,
|
| gradio_builder=build_gradio_ui,
|
| )
|
|
|
|
|
| @app.get("/dashboard", response_class=HTMLResponse)
|
| async def dashboard() -> HTMLResponse:
|
| """Serve static dashboard HTML if present."""
|
| dashboard_file = repo_root / "server" / "static" / "index.html"
|
| if dashboard_file.exists():
|
| return HTMLResponse(content=dashboard_file.read_text(encoding="utf-8"))
|
| return HTMLResponse(
|
| content="<h1>Dashboard not found</h1><p>Add server/static/index.html and refresh.</p>",
|
| status_code=404,
|
| )
|
|
|
|
|
| def main(host: str = "0.0.0.0", port: int = 8000):
|
| """
|
| Entry point for direct execution via uv run or python -m.
|
|
|
| This function enables running the server without Docker:
|
| uv run --project . server
|
| uv run --project . server --port 8001
|
| python -m hustlers_env.server.app
|
|
|
| Args:
|
| host: Host address to bind to (default: "0.0.0.0")
|
| port: Port number to listen on (default: 8000)
|
|
|
| For production deployments, consider using uvicorn directly with
|
| multiple workers:
|
| uvicorn hustlers_env.server.app:app --workers 4
|
| """
|
| import uvicorn
|
|
|
| uvicorn.run(app, host=host, port=port)
|
|
|
|
|
| if __name__ == "__main__":
|
| import argparse
|
|
|
| parser = argparse.ArgumentParser()
|
| parser.add_argument("--port", type=int, default=8000)
|
| args = parser.parse_args()
|
|
|
|
|
| if args.port != 8000:
|
| main(port=args.port)
|
| else:
|
| main()
|
|
|