import logging from collections.abc import AsyncGenerator from contextlib import asynccontextmanager from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from src.gateway.config import get_gateway_config from src.gateway.routers import artifacts, models, proxy logger = logging.getLogger(__name__) @asynccontextmanager async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: """Application lifespan handler.""" config = get_gateway_config() logger.info(f"Starting API Gateway on {config.host}:{config.port}") logger.info(f"Proxying to LangGraph server at {config.langgraph_url}") yield logger.info("Shutting down API Gateway") # Close the shared HTTP client await proxy.close_http_client() def create_app() -> FastAPI: """Create and configure the FastAPI application. Returns: Configured FastAPI application instance. """ app = FastAPI( title="DeerFlow API Gateway", description="API Gateway for DeerFlow - proxies to LangGraph Server and provides custom endpoints", version="0.1.0", lifespan=lifespan, ) # Add CORS middleware app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Include routers # Models API is mounted at /api/models app.include_router(models.router) # Artifacts API is mounted at /api/threads/{thread_id}/artifacts app.include_router(artifacts.router) # Proxy router handles all LangGraph paths (must be last due to catch-all) app.include_router(proxy.router) @app.get("/health") async def health_check() -> dict: """Health check endpoint.""" return {"status": "healthy", "service": "deer-flow-gateway"} return app # Create app instance for uvicorn app = create_app()