""" Flare – Main Application (Refactored) ===================================== """ from fastapi import FastAPI, WebSocket from fastapi.staticfiles import StaticFiles from fastapi.responses import FileResponse from fastapi.middleware.cors import CORSMiddleware import uvicorn import os from pathlib import Path import mimetypes from websocket_handler import websocket_endpoint 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 llm_startup import run_in_thread # Changed from spark_startup from session import session_store, start_session_cleanup from config_provider import ConfigProvider # ===================== Environment Setup ===================== def setup_environment(): """Setup environment based on deployment mode""" cfg = ConfigProvider.get() log("=" * 60) log(f"🚀 Flare Starting") log(f"🔌 LLM Provider: {cfg.global_config.llm_provider.name}") log(f"🎤 TTS Provider: {cfg.global_config.tts_provider.name}") log(f"🎧 STT Provider: {cfg.global_config.stt_provider.name}") log("=" * 60) if cfg.global_config.is_cloud_mode(): log("☁️ Cloud Mode: Using HuggingFace Secrets") log("📌 Required secrets: JWT_SECRET, FLARE_TOKEN_KEY") # Check for provider-specific tokens llm_config = cfg.global_config.get_provider_config("llm", cfg.global_config.llm_provider.name) if llm_config and llm_config.requires_repo_info: log("📌 LLM requires SPARK_TOKEN for repository operations") 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="2.0.0", description="LLM-driven intent & API flow engine with multi-provider support", ) # CORS for development if os.getenv("ENVIRONMENT") == "development": app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:4200"], # Angular dev server allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) log("🔧 CORS enabled for development") run_in_thread() # Start LLM startup notifier if needed start_cleanup_task() # Activity log cleanup start_session_cleanup() # Session cleanup # ---------------- Health probe (HF Spaces watchdog) ----------------- @app.get("/") def health_check(): return {"status": "ok", "version": "2.0.0"} # ---------------- Core chat/session routes -------------------------- app.include_router(chat_router, prefix="/api") # ---------------- Admin API routes ---------------------------------- app.include_router(admin_router) # ---------------- WebSocket route for real-time STT ------------------ @app.websocket("/ws/conversation/{session_id}") async def conversation_websocket(websocket: WebSocket, session_id: str): await websocket_endpoint(websocket, session_id) # ---------------- Serve Angular UI if exists ------------------------ static_dir = Path(__file__).parent / "static" if static_dir.exists(): log("🎨 Serving Angular UI from /static directory") # Mount static files with custom handler for Angular routing @app.get("/{path:path}") async def serve_angular(path: str): # API routes should not be handled here if path.startswith("api/"): return {"error": "Not found"}, 404 # Try to serve the exact file first file_path = static_dir / path if file_path.is_file(): return FileResponse(file_path) # For Angular routes, always serve index.html index_path = static_dir / "index.html" if index_path.exists(): return FileResponse(index_path) return {"error": "Not found"}, 404 # Mount static files for assets app.mount("/", StaticFiles(directory=str(static_dir), html=True), name="static") else: log("⚠️ No UI found. Run 'cd flare-ui && npm run build' to build the UI.") if __name__ == "__main__": log("🌐 Starting Flare backend on port 7860...") uvicorn.run(app, host="0.0.0.0", port=7860)