Spaces:
Sleeping
Sleeping
| import os | |
| import asyncio | |
| import httpx | |
| from fastapi import FastAPI | |
| from fastapi.middleware.cors import CORSMiddleware | |
| import uvicorn | |
| import subprocess | |
| from config import settings | |
| from utils.logger import logger | |
| from utils.hardware import check_hardware | |
| from api.routes import openenv, websocket, config_routes, scenario_routes, model_routes | |
| app = FastAPI(title="NEXUS Backend API") | |
| # Setup CORS | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| app.include_router(openenv.router) | |
| app.include_router(websocket.router) | |
| app.include_router(config_routes.router) | |
| app.include_router(scenario_routes.router) | |
| app.include_router(model_routes.router) | |
| # ββ Health check (required by HF Space automated ping) βββββββββββββββββββββ | |
| async def health(): | |
| return {"status": "ok", "env": "nexus-incident-investigation"} | |
| async def root(): | |
| return {"name": "NEXUS", "version": "1.0.0", "status": "running"} | |
| # Serve frontend statically if available | |
| frontend_dist = os.path.join(os.path.dirname(os.path.dirname(__file__)), "frontend", "dist") | |
| if os.path.exists(frontend_dist): | |
| from fastapi.staticfiles import StaticFiles | |
| from fastapi.responses import FileResponse | |
| app.mount("/assets", StaticFiles(directory=os.path.join(frontend_dist, "assets")), name="assets") | |
| async def serve_frontend(catchall: str = ""): | |
| return FileResponse(os.path.join(frontend_dist, "index.html")) | |
| async def check_ollama(): | |
| try: | |
| async with httpx.AsyncClient() as client: | |
| resp = await client.get(settings.OLLAMA_BASE_URL.replace("/v1", ""), timeout=2.0) | |
| if resp.status_code == 200: | |
| logger.info(f"Ollama running at {settings.OLLAMA_BASE_URL}") | |
| return True | |
| except Exception: | |
| logger.error(f"Ollama is NOT reachable at {settings.OLLAMA_BASE_URL}.") | |
| logger.error("Please install from https://ollama.com and run it.") | |
| return False | |
| async def startup_event(): | |
| # Print endpoints list | |
| logger.info("Starting NEXUS Backend...") | |
| for route in app.routes: | |
| logger.info(f"Endpoint: {route.path} ({getattr(route, 'methods', 'WS')})") | |
| hw = check_hardware() | |
| logger.info(f"Hardware setup: VRAM available = {hw['vram_available_gb']} GB. GPU Mode enabled = {hw['use_gpu']}") | |
| ollama_ok = await check_ollama() | |
| if ollama_ok: | |
| # Just check models via httpx to Ollama's local tags | |
| async with httpx.AsyncClient() as client: | |
| try: | |
| resp = await client.get(settings.OLLAMA_BASE_URL.replace("/v1", "/api/tags")) | |
| models = [m["name"] for m in resp.json().get("models", [])] | |
| if settings.AGENT_A_MODEL not in models: | |
| logger.warning(f"Default Agent A model {settings.AGENT_A_MODEL} not found. Run: ollama pull {settings.AGENT_A_MODEL}") | |
| if settings.AGENT_B_MODEL not in models: | |
| logger.warning(f"Default Agent B model {settings.AGENT_B_MODEL} not found. Run: ollama pull {settings.AGENT_B_MODEL}") | |
| except Exception: | |
| pass | |
| # Run MCP server in bg | |
| def run_mcp(): | |
| base_dir = os.path.dirname(__file__) | |
| subprocess.Popen([os.sys.executable, "-m", "tools.tool_server"], cwd=base_dir) | |
| run_mcp() | |
| if __name__ == "__main__": | |
| try: | |
| uvicorn.run(app, host=settings.HOST, port=settings.PORT) | |
| except Exception as e: | |
| import traceback | |
| print(f"FATAL ERROR AT STARTUP: {str(e)}") | |
| traceback.print_exc() | |
| os._exit(1) | |