"""AtoCore — FastAPI application entry point.""" from contextlib import asynccontextmanager from fastapi import FastAPI from atocore import __version__ from atocore.api.routes import router import atocore.config as _config from atocore.context.project_state import init_project_state_schema from atocore.engineering.service import init_engineering_schema from atocore.ingestion.pipeline import get_source_status from atocore.models.database import init_db from atocore.observability.logger import get_logger, setup_logging log = get_logger("main") @asynccontextmanager async def lifespan(app: FastAPI): """Run setup before the first request and teardown after shutdown. Replaces the deprecated ``@app.on_event("startup")`` hook with the modern ``lifespan`` context manager. Setup runs synchronously (the underlying calls are blocking I/O) so no await is needed; the function still must be async per the FastAPI contract. """ setup_logging() _config.ensure_runtime_dirs() init_db() init_project_state_schema() init_engineering_schema() log.info( "startup_ready", env=_config.settings.env, db_path=str(_config.settings.db_path), chroma_path=str(_config.settings.chroma_path), source_status=get_source_status(), ) yield # No teardown work needed today; SQLite connections are short-lived # and the Chroma client cleans itself up on process exit. app = FastAPI( title="AtoCore", description="Personal Context Engine for LLM interactions", version=__version__, lifespan=lifespan, ) app.include_router(router) if __name__ == "__main__": import uvicorn uvicorn.run( "atocore.main:app", host=_config.settings.host, port=_config.settings.port, reload=True, )