"""HSBG AI Assistant — Application FastAPI principale.""" from contextlib import asynccontextmanager from pathlib import Path import structlog import uvicorn from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from backend.api.routes.advice import router as advice_router from backend.api.routes.database_routes import router as db_router from backend.api.routes.game import router as game_router from backend.api.routes.learning import router as learning_router from backend.api.routes.settings_routes import router as settings_router from backend.api.routes.websocket_routes import router as ws_router from backend.config.settings import get_settings from backend.database.db import init_db from backend.services.ai_service import AIService from backend.services.vision_service import VisionService log = structlog.get_logger() cfg = get_settings() @asynccontextmanager async def lifespan(app: FastAPI): """Cycle de vie: démarrage → running → arrêt.""" log.info("hsbg_ai.starting", version="1.0.0") # Initialiser la base de données await init_db() log.info("database.ready") # Initialiser le service IA ai = AIService(cfg) await ai.initialize() app.state.ai_service = ai # Initialiser le service Vision vis = VisionService(cfg) if cfg.vision_enabled: await vis.start() app.state.vision_service = vis log.info("hsbg_ai.ready", port=cfg.backend_port, llm=cfg.llm_model) yield # Application en cours d'exécution # Arrêt propre log.info("hsbg_ai.stopping") await vis.stop() await ai.shutdown() log.info("hsbg_ai.stopped") def create_app() -> FastAPI: app = FastAPI( title="HSBG AI Assistant", description="IA d'assistance temps réel pour Hearthstone Battlegrounds", version="1.0.0", lifespan=lifespan, docs_url="/docs", redoc_url="/redoc", ) # CORS pour le frontend React app.add_middleware( CORSMiddleware, allow_origins=cfg.cors_origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Routes API REST app.include_router(game_router, prefix="/api/game", tags=["Partie"]) app.include_router(advice_router, prefix="/api/advice", tags=["Conseils IA"]) app.include_router(learning_router, prefix="/api/learning", tags=["Apprentissage"]) app.include_router(db_router, prefix="/api/database", tags=["Base HSBG"]) app.include_router(settings_router, prefix="/api/settings", tags=["Paramètres"]) app.include_router(ws_router, prefix="/ws", tags=["WebSocket"]) # Servir le frontend buildé si disponible frontend_dist = Path("frontend/dist") if frontend_dist.exists(): app.mount("/", StaticFiles(directory=str(frontend_dist), html=True), name="static") @app.get("/health", tags=["Système"]) async def health(): return { "status": "ok", "version": "1.0.0", "llm_model": cfg.llm_model, "patch": cfg.current_patch, } return app app = create_app() if __name__ == "__main__": uvicorn.run( "backend.main:app", host=cfg.backend_host, port=cfg.backend_port, reload=cfg.debug, log_config=None, )