"""FastAPI application for HF Agent web interface.""" import logging import os from contextlib import asynccontextmanager from pathlib import Path from dotenv import load_dotenv load_dotenv() # Ensure HF_TOKEN is set — fall back to HF_ADMIN_TOKEN if available (HF Spaces) if not os.environ.get("HF_TOKEN") and os.environ.get("HF_ADMIN_TOKEN"): os.environ["HF_TOKEN"] = os.environ["HF_ADMIN_TOKEN"] from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from routes.agent import router as agent_router from routes.auth import router as auth_router # Configure logging logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", ) logger = logging.getLogger(__name__) @asynccontextmanager async def lifespan(app: FastAPI): """Application lifespan handler.""" logger.info("Starting HF Agent backend...") yield logger.info("Shutting down HF Agent backend...") app = FastAPI( title="HF Agent", description="ML Engineering Assistant API", version="1.0.0", lifespan=lifespan, ) # CORS middleware for development app.add_middleware( CORSMiddleware, allow_origins=[ "http://localhost:5173", # Vite dev server "http://localhost:3000", "http://127.0.0.1:5173", "http://127.0.0.1:3000", ], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Include routers app.include_router(agent_router) app.include_router(auth_router) # Serve static files (frontend build) in production static_path = Path(__file__).parent.parent / "static" if static_path.exists(): app.mount("/", StaticFiles(directory=str(static_path), html=True), name="static") logger.info(f"Serving static files from {static_path}") else: logger.info("No static directory found, running in API-only mode") @app.get("/api") async def api_root(): """API root endpoint.""" return { "name": "HF Agent API", "version": "1.0.0", "docs": "/docs", } if __name__ == "__main__": import uvicorn port = int(os.environ.get("PORT", 7860)) uvicorn.run(app, host="0.0.0.0", port=port)