from fastapi import FastAPI from fastapi.staticfiles import StaticFiles from fastapi.responses import FileResponse import uvicorn import os from pathlib import Path import mimetypes from utils import log from chat_handler import router as chat_router # ← start_session & chat from admin_routes import router as admin_router, start_cleanup_task from spark_startup import run_in_thread from session import session_store # ← Import session_store from config_provider import ConfigProvider # ===================== Environment Setup ===================== def setup_environment(): """Setup environment based on work_mode""" cfg = ConfigProvider.get() log("=" * 60) log(f"🚀 Flare Starting in {cfg.global_config.work_mode.upper()} mode") log("=" * 60) if cfg.global_config.is_cloud_mode(): log("☁️ Cloud Mode: Using HuggingFace Secrets") log("📌 Required secrets: JWT_SECRET, FLARE_TOKEN_KEY, SPARK_TOKEN") else: log("🏢 On-Premise Mode: Using .env file") if not Path(".env").exists(): log("⚠️ WARNING: .env file not found!") log("📌 Copy .env.example to .env and configure it") # Run setup setup_environment() # Fix MIME types for JavaScript files mimetypes.add_type("application/javascript", ".js") mimetypes.add_type("text/css", ".css") app = FastAPI( title="Flare Orchestration Service", version="0.1.0", description="LLM-driven intent & API flow engine (bootstrap)", ) run_in_thread() start_cleanup_task() # Activity log cleanup # ---------------- Core chat/session routes -------------------------- app.include_router(chat_router) # ---------------- Admin API routes ---------------------------------- app.include_router(admin_router) # ---------------- Health probe (HF Spaces watchdog) ----------------- @app.get("/") def health_check(): return {"status": "ok"} # ---------------- Serve Angular UI if exists ------------------------ static_path = Path("static") log(f"🔍 Checking for static directory at: {static_path.absolute()}") log(f"🔍 Static directory exists: {static_path.exists()}") if static_path.exists() and static_path.is_dir(): # List files in static directory files = list(static_path.iterdir()) log(f"📁 Files in static directory: {[f.name for f in files]}") # Check for index.html index_path = static_path / "index.html" log(f"🔍 index.html exists: {index_path.exists()}") # Mount entire static directory app.mount("/static", StaticFiles(directory="static"), name="static") # Serve static files (Angular assets) - only if assets directory exists assets_path = static_path / "assets" if assets_path.exists() and assets_path.is_dir(): app.mount("/assets", StaticFiles(directory=str(assets_path)), name="assets") # Root path - serve index.html @app.get("/") async def serve_root(): index_path = static_path / "index.html" if index_path.exists(): log("📄 Serving index.html") return FileResponse(str(index_path), media_type="text/html") log("⚠️ index.html not found, returning health check") return {"status": "ok", "sessions": len(session_store._sessions)} # Fallback to health check # Serve JS files with correct MIME type @app.get("/{filename:path}.js") async def serve_js(filename: str): js_path = static_path / f"{filename}.js" if js_path.exists(): return FileResponse(str(js_path), media_type="application/javascript") return {"error": "JS file not found"}, 404 # Serve CSS files with correct MIME type @app.get("/{filename:path}.css") async def serve_css(filename: str): css_path = static_path / f"{filename}.css" if css_path.exists(): return FileResponse(str(css_path), media_type="text/css") return {"error": "CSS file not found"}, 404 # Catch-all route for Angular routing (must be last!) @app.get("/{full_path:path}") async def serve_angular(full_path: str): # Don't catch API routes if full_path.startswith("api/") or full_path in ["start_session", "chat", "health"]: return {"error": "Not found"}, 404 # Return Angular index.html for all other routes index_path = static_path / "index.html" if index_path.exists(): return FileResponse(str(index_path), media_type="text/html") return {"error": "UI not found"}, 404 else: log("⚠️ Static directory not found") # No UI built, just health endpoint @app.get("/") def health_check(): return {"status": "ok", "message": "UI not found. Build Angular app first."} if __name__ == "__main__": log("🌐 Starting Flare backend …") uvicorn.run(app, host="0.0.0.0", port=7860)