| from __future__ import annotations |
|
|
| import logging |
| from contextlib import asynccontextmanager |
| from pathlib import Path |
|
|
| from fastapi import FastAPI |
| from fastapi.middleware.cors import CORSMiddleware |
| from fastapi.staticfiles import StaticFiles |
| from starlette.responses import FileResponse |
|
|
| from app.config import settings |
| from app.clients.hana_client import hana_client |
| from app.api import models, compare, history |
|
|
| STATIC_DIR = Path(__file__).resolve().parent.parent / "static" |
|
|
| logging.basicConfig(level=logging.INFO) |
| LOG = logging.getLogger(__name__) |
|
|
|
|
| @asynccontextmanager |
| async def lifespan(app: FastAPI): |
| LOG.info("Starting up — authenticating with HANA...") |
| try: |
| await hana_client.authenticate() |
| await hana_client.get_models() |
| LOG.info("HANA auth complete, persona cache populated.") |
| except Exception as exc: |
| LOG.warning("HANA auth failed at startup (%s) — will retry on first request", exc) |
| yield |
| LOG.info("Shutting down — closing HTTP clients...") |
| await hana_client.close() |
|
|
|
|
| app = FastAPI(title="LLM Comparison Tool", version="0.1.0", lifespan=lifespan) |
|
|
| LOG.info("CORS origins: %s", settings.cors_origin_list) |
| app.add_middleware( |
| CORSMiddleware, |
| allow_origins=["*"], |
| allow_credentials=True, |
| allow_methods=["*"], |
| allow_headers=["*"], |
| ) |
|
|
| app.include_router(models.router, prefix="/api") |
| app.include_router(compare.router, prefix="/api") |
| app.include_router(history.router, prefix="/api") |
|
|
|
|
| @app.get("/api/health") |
| async def health(): |
| return {"status": "ok"} |
|
|
|
|
| if STATIC_DIR.is_dir(): |
| app.mount("/static", StaticFiles(directory=str(STATIC_DIR / "static")), name="static-assets") |
|
|
| @app.get("/{full_path:path}") |
| async def spa_fallback(full_path: str): |
| file_path = STATIC_DIR / full_path |
| if full_path and file_path.is_file(): |
| return FileResponse(file_path) |
| return FileResponse(STATIC_DIR / "index.html") |
|
|