"""Shared clients that live for the lifetime of the FastAPI process. We keep one AtomicClient, one EmbeddingClient, and one TagResolver in module state. FastAPI dependencies pull them out so handlers stay clean. Initialized from app.py's lifespan context manager at startup; closed on shutdown. """ from __future__ import annotations from dataclasses import dataclass from shared.atomic_api import AtomicClient from shared.embedding_client import EmbeddingClient from shared.llm_client import LlmClient from shared.taxonomy import TagResolver @dataclass(slots=True) class AppState: atomic: AtomicClient embed: EmbeddingClient llm: LlmClient resolver: TagResolver # Module-level singleton, populated by the lifespan handler. _state: AppState | None = None def set_state(state: AppState) -> None: global _state _state = state def get_state() -> AppState: if _state is None: raise RuntimeError( "brain_api state not initialized — FastAPI lifespan must run first" ) return _state