""" MOXIE - Fake Local LLM Orchestrator Main FastAPI Application Entry Point """ import sys from pathlib import Path # Add project root to path sys.path.insert(0, str(Path(__file__).parent)) from contextlib import asynccontextmanager from fastapi import FastAPI, Request from fastapi.responses import HTMLResponse, FileResponse from fastapi.staticfiles import StaticFiles from fastapi.middleware.cors import CORSMiddleware from loguru import logger from config import settings, get_data_dir, get_workflows_dir from api.routes import router as api_router from api.admin import router as admin_router from core.orchestrator import Orchestrator from rag.store import RAGStore # Configure logging logger.remove() logger.add( sys.stderr, format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}", level="DEBUG" if settings.debug else "INFO" ) @asynccontextmanager async def lifespan(app: FastAPI): """Application lifespan manager.""" logger.info("Starting MOXIE Orchestrator...") # Initialize data directories get_data_dir() get_workflows_dir() # Initialize RAG store app.state.rag_store = RAGStore() logger.info("RAG Store initialized") # Initialize orchestrator app.state.orchestrator = Orchestrator(app.state.rag_store) logger.info("Orchestrator initialized") logger.success(f"MOXIE ready on http://{settings.host}:{settings.port}") logger.info(f"Admin UI: http://{settings.host}:{settings.port}/{settings.admin_path}") yield # Cleanup logger.info("Shutting down MOXIE...") # Create FastAPI app app = FastAPI( title="MOXIE", description="OpenAI-compatible API that orchestrates multiple AI services", version="1.0.0", lifespan=lifespan, docs_url=None, # Hide docs redoc_url=None, # Hide redoc ) # CORS middleware for open-webui app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Static files for admin UI admin_static_path = Path(__file__).parent / "admin" / "static" if admin_static_path.exists(): app.mount( f"/{settings.admin_path}/static", StaticFiles(directory=str(admin_static_path)), name="admin-static" ) # Include routers app.include_router(api_router, prefix="/v1") app.include_router(admin_router, prefix=f"/{settings.admin_path}", tags=["admin"]) @app.get("/health") async def health_check(): """Health check endpoint.""" return {"status": "healthy", "service": "moxie"} # Serve favicon to avoid 404s @app.get("/favicon.ico") async def favicon(): return {"status": "not found"} if __name__ == "__main__": import uvicorn uvicorn.run( "main:app", host=settings.host, port=settings.port, reload=settings.debug, )