from contextlib import asynccontextmanager from collections.abc import AsyncIterator from typing import cast from fastapi import FastAPI from app.api.v1.entities import router as entities_router from app.api.v1.automations import router as automations_router from app.automations.store import AutomationStore from app.config import load_settings from app.core.exception_handlers import register_exception_handlers from app.ha.client import HaClient, HaClientSettings from app.ha.reader import HaReader from app.ml.registry.model_registry import ModelRegistry from backend.routes.ml import init_ml_routes @asynccontextmanager async def lifespan(app: FastAPI) -> AsyncIterator[None]: settings = app.state.settings client: HaClient | None = None app.state.registry = ModelRegistry(settings.model_store) app.state.automation_store = AutomationStore(settings.automation_store) if hasattr(app.state, "ha_reader"): del app.state.ha_reader if settings.ha_configured: client = HaClient( settings=HaClientSettings( url=cast(str, settings.ha_url), token=cast(str, settings.ha_token), ) ) app.state.ha_reader = HaReader(client=client) try: yield finally: if client is not None: client.close() app = FastAPI( title="SillyHome Next API", description="Lokales Smart-Home-Intelligenzsystem für Home Assistant.", version="0.2.0", lifespan=lifespan, ) app.state.settings = load_settings() register_exception_handlers(app) app.include_router(entities_router) app.include_router(automations_router) init_ml_routes(app, model_store=app.state.settings.model_store) @app.get("/health") def health() -> dict[str, str]: return {"status": "ok"} @app.get("/") def root() -> dict[str, str]: return {"service": "sillyhome-next", "docs": "/docs"}