File size: 3,902 Bytes
02eac4b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bf6e620
 
 
 
 
 
 
 
 
 
 
 
02eac4b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import logging
import os
from pathlib import Path

import uvicorn
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles

# Import the existing API
from src.api import app as api_app

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    handlers=[logging.StreamHandler(), logging.FileHandler("server.log")],
)

logger = logging.getLogger(__name__)

# Create a new FastAPI app that combines API and frontend
app = FastAPI(
    title="LeRobot Arena Transport Server with UI",
    description="Combined API and web interface for LeRobot Arena transport server",
    version="2.0.0",
)

# Add CORS middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


# Add the health endpoint BEFORE other routes to avoid conflicts
@app.get("/health")
async def health_check():
    return {
        "status": "healthy",
        "server_running": True,
        "frontend_enabled": os.getenv("SERVE_FRONTEND", "false").lower() == "true",
        "api_available": True,
    }


# Mount the API under /api prefix
app.mount("/api", api_app)

# Check if we should serve frontend
serve_frontend = os.getenv("SERVE_FRONTEND", "false").lower() == "true"

if serve_frontend:
    # Get the frontend static files path
    frontend_path = Path(__file__).parent.parent / "static-frontend"

    if frontend_path.exists():
        logger.info(f"Serving frontend from: {frontend_path}")

        # Mount static files (JS, CSS, etc.)
        app.mount("/static", StaticFiles(directory=frontend_path), name="static")

        # Serve the main app for all other routes (SPA)
        @app.get("/{full_path:path}")
        async def serve_frontend_app(full_path: str):
            """Serve the SvelteKit app for all non-API routes."""
            # Don't serve frontend for API routes
            if full_path.startswith("api/"):
                return {"error": "API route not found"}

            # Check if requesting a specific file
            file_path = frontend_path / full_path
            if file_path.is_file():
                return FileResponse(file_path)

            # For all other routes, serve the main index.html (SPA behavior)
            index_path = frontend_path / "index.html"
            if index_path.exists():
                return FileResponse(index_path)
            return {"error": "Frontend not available"}

    else:
        logger.warning(f"Frontend path not found: {frontend_path}")

        @app.get("/")
        async def no_frontend():
            return {
                "message": "LeRobot Arena Transport Server",
                "frontend": "not available",
                "api": "available at /api/",
                "docs": "available at /api/docs",
            }

else:

    @app.get("/")
    async def api_only():
        return {
            "message": "LeRobot Arena Transport Server - API Only",
            "api": "available at /api/",
            "docs": "available at /api/docs",
        }


if __name__ == "__main__":
    port = int(os.getenv("PORT", 7860))
    host = os.getenv("HOST", "0.0.0.0")

    logger.info("🤖 Starting LeRobot Arena Combined Server...")
    logger.info(f"   - API available at: http://{host}:{port}/api/")
    logger.info(f"   - API docs at: http://{host}:{port}/api/docs")

    if serve_frontend:
        logger.info(f"   - Frontend available at: http://{host}:{port}/")
    else:
        logger.info("   - Frontend disabled (set SERVE_FRONTEND=true to enable)")

    print(f"🤖 Starting LeRobot Arena Combined Server on {host}:{port}")

    uvicorn.run(
        "launch_with_ui:app",
        host=host,
        port=port,
        reload=False,
        log_level="info",
    )