Skip to main content

cel_brief/
lib.rs

1//! cel-brief — Per-turn LLM briefing layer.
2//!
3//! cel-brief answers one question: **what should the model see this turn?** It
4//! sits between an agent's state and the LLM — every turn, sources contribute
5//! [`source::Contribution`]s that the builder budgets, prunes, governs, and
6//! assembles into a provider-agnostic [`types::Brief`] plus a
7//! [`receipt::BriefReceipt`] of what was included, dropped, and redacted.
8//!
9//! It is deliberately scoped. `cel-brief` does **not** discover live state
10//! itself — a `PerceptionSource` consumes a snapshot that some backend produced
11//! — and it does **not** store memory; a `MemorySource` reads from a
12//! `cel_memory::MemoryProvider`. `cel-brief` owns per-turn briefing assembly
13//! only.
14//!
15//! **Status (Phases 1 + 2 + 3 + 4):** all core types, traits, sources,
16//! governance, and builder are shipped.
17//!
18//! **Phase 1** — core types ([`types::Brief`], [`types::BriefMessage`],
19//! [`types::Role`], [`types::BriefContext`], [`types::TokenBudget`],
20//! [`types::Priority`], [`types::ToolSchema`], [`types::ImageData`],
21//! [`types::SourceId`]) and the [`source::Source`] trait + supporting
22//! types ([`source::Contribution`], [`source::ContributionContent`],
23//! [`source::SourceError`]).
24//!
25//! **Phase 2** — [`builder::BriefBuilder`], [`tokenizer::Tokenizer`]
26//! (default [`tokenizer::CharApproxTokenizer`]; opt-in
27//! `TiktokenCl100k` behind the `tiktoken` feature),
28//! [`budget::PruneStrategy`] + budget enforcement, full
29//! [`receipt::BriefReceipt`].
30//!
31//! **Phase 3** — built-in [`sources::SystemPromptSource`],
32//! [`sources::UserMessageSource`], [`sources::ToolCatalogSource`],
33//! [`sources::HistorySource`] + [`sources::HistoryStore`] under default
34//! features; `MemorySource` behind the `memory` feature;
35//! `PerceptionSource` + `PerceptionSnapshot` behind
36//! the `perception` feature.
37//!
38//! **Phase 4** — [`governance::Governance`] trait with
39//! [`governance::NoOpGovernance`] default, [`governance::GovernanceVerdict`]
40//! enum, and the [`receipt::RedactionRecord`] surface that
41//! [`governance::GovernanceVerdict::Redacted`] returns.
42//!
43//! ## Quick start
44//!
45//! ```no_run
46//! # use std::sync::Arc;
47//! # use cel_brief::{BriefBuilder, BriefContext, TokenBudget};
48//! # async fn example() -> Result<(), cel_brief::BriefError> {
49//! let builder = BriefBuilder::new()
50//!     .budget(TokenBudget::new(8000, 1024));
51//!     // .source(Arc::new(MySource)) ...
52//!
53//! let ctx = BriefContext::new(TokenBudget::default())
54//!     .with_user_message("hi");
55//! let brief = builder.build(&ctx).await?;
56//! println!("brief: {} messages, {} tokens",
57//!     brief.messages.len(), brief.receipt.total_tokens);
58//! # Ok(())
59//! # }
60//! ```
61
62#![deny(missing_docs)]
63#![warn(rust_2018_idioms)]
64
65pub mod budget;
66pub mod builder;
67pub mod error;
68pub mod governance;
69pub mod receipt;
70pub mod source;
71pub mod sources;
72pub mod tokenizer;
73pub mod types;
74
75pub use budget::{PruneStrategy, WeightedContribution};
76pub use builder::BriefBuilder;
77pub use error::{BriefError, Result};
78pub use governance::{Governance, GovernanceError, GovernanceVerdict, NoOpGovernance};
79pub use receipt::{
80    BriefReceipt, DropReason, DroppedContribution, RedactionRecord, SourceStats, Timings,
81};
82pub use source::{Contribution, ContributionContent, Source, SourceError};
83pub use sources::{
84    HistoryEntry, HistorySource, HistoryStore, ReceiptSource, SystemPromptSource,
85    ToolCatalogSource, UserMessageSource,
86};
87#[cfg(feature = "memory")]
88pub use sources::{MemoryQueryStrategy, MemorySource};
89#[cfg(feature = "perception")]
90pub use sources::{PerceptionError, PerceptionMode, PerceptionSnapshot, PerceptionSource};
91pub use tokenizer::{CharApproxTokenizer, Tokenizer};
92pub use types::{
93    Brief, BriefContext, BriefMessage, ImageData, Priority, Role, SourceId, TokenBudget, ToolSchema,
94};
95
96#[cfg(feature = "tiktoken")]
97pub use tokenizer::TiktokenCl100k;