llm-budget-window 0.1.0

Time-windowed token + USD budget. Define multiple rolling windows (e.g. $5/minute, $100/day) and reject when any window's cap would be breached. Thread-safe, zero deps.
Documentation
//! # llm-budget-window
//!
//! Time-windowed token + USD budget for LLM calls.
//!
//! [`token-budget-pool`](https://crates.io/crates/token-budget-pool) caps
//! total spend across concurrent tasks. This crate adds a time axis:
//! cap spend per minute, per hour, per day, or any combination. Each
//! recorded call is timestamped; older entries fall out of the window
//! automatically.
//!
//! ## Quick example
//!
//! ```
//! use std::time::Duration;
//! use llm_budget_window::{BudgetWindows, Window, WindowBreached};
//!
//! let bw = BudgetWindows::new(vec![
//!     Window::new("per_minute", Duration::from_secs(60))
//!         .with_token_cap(50_000)
//!         .with_usd_cap(1.0),
//!     Window::new("per_hour", Duration::from_secs(3600))
//!         .with_usd_cap(10.0),
//! ]);
//!
//! // record consumption; raises if ANY window would breach
//! bw.record(tokens(1000), usd(0.05)).unwrap();
//!
//! // for very cheap calls, both windows have plenty of room
//! for _ in 0..50 {
//!     let _ = bw.record(tokens(100), usd(0.001));
//! }
//!
//! # fn tokens(n: u64) -> u64 { n }
//! # fn usd(v: f64) -> f64 { v }
//! ```
//!
//! ## Memory
//!
//! Each window keeps a `VecDeque` of (timestamp, tokens, usd) records.
//! Old records age out on every `record()` and `snapshot()`. For very
//! high call rates, set windows you actually need - a 1-day window
//! holds every call from the last 24h.

#![deny(missing_docs)]

mod error;
mod window;

pub use error::WindowBreached;
pub use window::{BudgetWindows, Window, WindowSnapshot};