Metadata-Version: 2.1
Name: ooai-persistence
Version: 0.2.0
Summary: Typed persistence utilities for LangGraph-based OOAI applications.
Keywords: ai,langchain,langgraph,langsmith,persistence,postgres
Author: William R. Astley
License: MIT
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: Pydantic
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Database
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Project-URL: Homepage, https://github.com/pr1m8/ooai-persistence
Project-URL: Documentation, https://ooai-persistence.readthedocs.io/
Project-URL: Repository, https://github.com/pr1m8/ooai-persistence
Project-URL: Issues, https://github.com/pr1m8/ooai-persistence/issues
Project-URL: Releases, https://github.com/pr1m8/ooai-persistence/releases
Project-URL: CI, https://github.com/pr1m8/ooai-persistence/actions/workflows/ci.yml
Project-URL: Release Workflow, https://github.com/pr1m8/ooai-persistence/actions/workflows/release.yml
Requires-Python: <3.14,>=3.13
Requires-Dist: langgraph>=0.6.0
Requires-Dist: pydantic>=2.11.0
Requires-Dist: pydantic-settings>=2.8.0
Requires-Dist: typing-extensions>=4.12.0
Provides-Extra: postgres
Requires-Dist: langgraph-checkpoint-postgres>=2.0.0; extra == "postgres"
Requires-Dist: psycopg[binary,pool]>=3.2.0; extra == "postgres"
Provides-Extra: sqlite
Requires-Dist: langgraph-checkpoint-sqlite>=2.0.0; extra == "sqlite"
Requires-Dist: aiosqlite>=0.20.0; extra == "sqlite"
Provides-Extra: redis
Requires-Dist: langgraph-checkpoint-redis>=0.0.8; extra == "redis"
Requires-Dist: redis>=5.0.0; extra == "redis"
Provides-Extra: mongodb
Requires-Dist: langgraph-checkpoint-mongodb>=0.1.0; extra == "mongodb"
Requires-Dist: pymongo>=4.10.0; extra == "mongodb"
Provides-Extra: langsmith
Requires-Dist: langsmith>=0.3.0; extra == "langsmith"
Provides-Extra: docs
Requires-Dist: furo>=2024.8.6; extra == "docs"
Requires-Dist: myst-parser>=4.0.0; extra == "docs"
Requires-Dist: sphinx>=8.0.0; extra == "docs"
Requires-Dist: sphinx-copybutton>=0.5.2; extra == "docs"
Provides-Extra: all
Requires-Dist: ooai-persistence[docs,langsmith,mongodb,postgres,redis,sqlite]; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=8.3.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.25.0; extra == "dev"
Requires-Dist: pytest-cov>=6.0.0; extra == "dev"
Requires-Dist: pytest-sugar>=1.0.0; extra == "dev"
Requires-Dist: rich>=14.0.0; extra == "dev"
Requires-Dist: ruff>=0.12.0; extra == "dev"
Requires-Dist: pyright>=1.1.390; extra == "dev"
Description-Content-Type: text/markdown

# ooai-persistence

[![CI](https://github.com/pr1m8/ooai-persistence/actions/workflows/ci.yml/badge.svg)](https://github.com/pr1m8/ooai-persistence/actions/workflows/ci.yml)
[![Release](https://github.com/pr1m8/ooai-persistence/actions/workflows/release.yml/badge.svg)](https://github.com/pr1m8/ooai-persistence/actions/workflows/release.yml)
![Python](https://img.shields.io/badge/python-3.13-blue)
![PDM](https://img.shields.io/badge/package%20manager-pdm-blue)
![Coverage](https://img.shields.io/badge/coverage-89%25-brightgreen)
![Async Postgres](https://img.shields.io/badge/e2e-async%20postgres%20store%20%2B%20checkpointer-brightgreen)

`ooai-persistence` provides typed persistence helpers for LangGraph-based OOAI applications.

## Responsibilities

- checkpointer configuration and backend resolution
- store configuration and backend resolution
- graph cache configuration
- strict serializer allowlist support
- sync and async persistence contexts
- local infrastructure defaults for Postgres, optional Redis, and optional MongoDB

## Quick start

```bash
pdm install -G :all
pdm run pytest
pdm run ooai-persistence smoke --backend memory
```

For a no-infrastructure memory bundle:

```python
from ooai_persistence import AppSettings, open_sync_persistence

settings = AppSettings.memory()

with open_sync_persistence(settings) as persistence:
    persistence.store.put(("users", "will"), "profile", {"name": "Will"})
    profile = persistence.store.get(("users", "will"), "profile")
```

For async usage:

```python
from ooai_persistence import AppSettings, open_persistence

settings = AppSettings.local_sqlite(".ooai/persistence/dev.sqlite3")

async with open_persistence(settings) as persistence:
    ...
```

## CLI

The package ships a small diagnostics and smoke-test CLI:

```bash
ooai-persistence doctor --backend postgres --json
ooai-persistence smoke --backend memory
ooai-persistence smoke --backend sqlite --sqlite-path .ooai/persistence/smoke.sqlite3
ooai-persistence smoke --backend postgres --async
ooai-persistence env --output .env
ooai-persistence ensure-postgres
```

The async Postgres smoke command exercises both the LangGraph checkpointer and
store through the public context API.

## Local Postgres

```bash
make bootstrap
make infra-up
make infra-test-postgres
make infra-down
```

`make bootstrap` creates `.env` from `.env.example` when needed and installs all
PDM extras. See `infra/README.md` for Compose details.

`make infra-test-postgres` runs the real async Postgres E2E path and the CLI
smoke path against Docker Compose Postgres.

If Docker is not installed but `.env` points at a reachable Postgres server,
`make infra-up` falls back to `ooai-persistence ensure-postgres` and creates the
configured database if needed.

## Default backend behavior

By default, checkpointer and store use `backend="auto"`.

`auto` resolves in this order:
1. async Postgres when configured
2. async SQLite when configured
3. async MongoDB when configured
4. async Redis when configured
5. in-memory fallback

## Serializer allowlist registry

The package includes a reusable strict-msgpack registry:

```python
from ooai_persistence.serde.registry import MsgpackAllowlistRegistry

registry = MsgpackAllowlistRegistry()
registry.register_symbol("my_app.models", "WorkflowState")
registry.register_type(MyPersistedModel)
registry.register_import_string("my_app.models:AnotherPersistedModel")
```

That registry can be passed into the persistence context:

```python
from ooai_persistence import AppSettings, open_persistence

settings = AppSettings()

async with open_persistence(settings, registry=registry) as bundle:
    ...
```

## Documentation and release checks

```bash
pdm run sphinx-build -W -b html docs docs/_build/html
pdm build
```

CI runs formatting, linting, typing, tests with coverage, and the Sphinx build.

## Releasing

Releases are tag-driven:

```bash
pdm lock --check
make check
git tag v0.2.0
git push origin v0.2.0
```

The release workflow verifies that the tag matches `pyproject.toml`, runs the
async Postgres E2E checks, builds the wheel/sdist, publishes through PyPI
Trusted Publishing, and creates a GitHub Release with artifacts attached.
