Source code for klea_utils.api.app
#!/usr/bin/env python3
"""
Shared FastAPI app factory for Klea packages.
File: klea_utils/api/app.py
Copyright 2026 Ankur Sinha
Author: Ankur Sinha <sanjay DOT ankur AT gmail DOT com>
"""
from collections.abc import Callable
from contextlib import asynccontextmanager
from fastapi import APIRouter, FastAPI
from klea_utils.api.sessions_db import SessionStore
from klea_utils.graph.base import BaseLangGraph
from klea_utils.paths import init_dir
[docs]
def make_app(
graph_factory: Callable[[], BaseLangGraph],
title: str = "Klea API",
version: str = "0.1.0",
routers: list[APIRouter] | None = None,
) -> FastAPI:
"""Create a FastAPI instance with a standard lifespan.
The lifespan:
1. Instantiates and sets up the graph via *graph_factory*
2. Opens a persistent :class:`SessionStore` at
``{graph.paths.user_data_dir}/sessions.db`` alongside the
graph's checkpoints.
3. Stores the graph and session store on ``app.state``
:param graph_factory: Callable that returns a configured
:class:`~klea_utils.graph.base.BaseLangGraph` instance
:param title: API title (appears in OpenAPI docs)
:param version: API version (appears in OpenAPI docs)
:param routers: List of APIRouters to include on the app
:returns: Configured FastAPI app
"""
@asynccontextmanager
async def lifespan(app: FastAPI):
app.state.is_ready = False
graph = graph_factory()
await graph.setup()
app.state.graph = graph
db_path = init_dir(graph.paths.user_data_dir) / "sessions.db"
app.state.chat_sessions = SessionStore(str(db_path))
app.state.is_ready = True
yield
app.state.is_ready = False
app.state.chat_sessions.close()
app = FastAPI(lifespan=lifespan, title=title, version=version)
for router in routers or []:
app.include_router(router)
return app