Skip to main content

agent_store/
lib.rs

1//! # agent-store
2//!
3//! A causal-ordered, backend-pluggable **store substrate** for the agent
4//! fleet. It is not a database and not an agent — it is the thin layer that
5//! gives every consumer (newt-agent's conversation store, modulex-mcp's
6//! routine board) the same three things:
7//!
8//! - a pluggable [`Backend`] — [`SqliteBackend`] today (bundled rusqlite,
9//!   zero system deps, the laptop default); a synchronous Postgres backend
10//!   behind the `pg` feature in Phase 2, for where an operator already runs a
11//!   server (your own box, or airship's "Meat Locker").
12//! - two causal primitives — a monotonic [`Generation`] counter (modulex's
13//!   report clock) and a per-writer, BLAKE3-chained [`WriterLog`] with
14//!   tamper-evident [`WriterLog::verify`] (newt's §6 ordering contract).
15//! - a commit [`Doorbell`] — the seam co-located agents use to wake each
16//!   other over agent-mesh instead of polling a file.
17//!
18//! Everything here is **synchronous**, so consumers drop it into their
19//! existing call sites without an async refactor. The substrate never touches
20//! the mesh and never reads the wall clock: ordering is `(writer, seq)` and
21//! generation counters, never timestamps.
22//!
23//! ## Usage
24//!
25//! ```
26//! use agent_store::{Doorbell, CommitEvent, Generation, SqliteBackend, WriterLog};
27//!
28//! // Open an ephemeral store and lay down the substrate tables.
29//! let db = SqliteBackend::in_memory().unwrap();
30//! Generation::ensure_schema(&db).unwrap();
31//! WriterLog::ensure_schema(&db).unwrap();
32//!
33//! // A monotonic generation counter (modulex's report clock).
34//! let report = Generation::new("report");
35//! assert_eq!(report.bump(&db).unwrap(), 1);
36//! assert_eq!(report.bump(&db).unwrap(), 2);
37//!
38//! // A per-writer chained log (newt's conversation turns), with a doorbell
39//! // that a session loop would bridge onto the mesh.
40//! let bell = Doorbell::new();
41//! bell.subscribe(|e: &CommitEvent| {
42//!     // a real consumer publishes (writer, seq) on a mesh topic here
43//!     let _ = e.seq;
44//! });
45//!
46//! let turn = WriterLog::append(&db, "conv:demo", "alice", b"hello world").unwrap();
47//! bell.ring(&CommitEvent {
48//!     stream: turn.stream.clone(),
49//!     writer: turn.writer.clone(),
50//!     seq: turn.seq,
51//!     content_hash: turn.content_hash,
52//! });
53//!
54//! // The chain is tamper-evident.
55//! WriterLog::verify(&db, "conv:demo", "alice").unwrap();
56//! ```
57
58mod backend;
59mod doorbell;
60mod error;
61mod fingerprint;
62mod generation;
63mod policy;
64mod writer_log;
65
66pub use backend::{Backend, Dialect, Row, SqliteBackend, Value};
67pub use doorbell::{CommitEvent, Doorbell};
68pub use error::{Result, StoreError};
69pub use fingerprint::Fingerprint;
70pub use generation::Generation;
71pub use policy::{BackendKind, StorePolicy};
72pub use writer_log::{Entry, WriterLog};