1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
//! # runcycles
//!
//! Rust client for the [Cycles](https://runcycles.io) budget authority protocol.
//!
//! Cycles provides concurrency-safe spend and action control for autonomous
//! agent runtimes. This crate implements the reserve-execute-commit lifecycle
//! with an idiomatic Rust API built around RAII guards and ownership semantics.
//!
//! ## Quick Start
//!
//! ```rust,no_run
//! use runcycles::{CyclesClient, Error, models::*};
//!
//! # async fn example() -> Result<(), Error> {
//! // Create a client
//! let client = CyclesClient::builder("my-api-key", "http://localhost:7878")
//! .tenant("acme")
//! .build();
//!
//! // Reserve budget — returns an RAII guard
//! let guard = client.reserve(
//! ReservationCreateRequest::builder()
//! .subject(Subject { tenant: Some("acme".into()), ..Default::default() })
//! .action(Action::new("llm.completion", "gpt-4o"))
//! .estimate(Amount::usd_microcents(5000))
//! .build()
//! ).await?;
//!
//! // Check caps if decision is AllowWithCaps
//! if let Some(caps) = guard.caps() {
//! println!("max_tokens: {:?}", caps.max_tokens);
//! }
//!
//! // ... perform the guarded operation ...
//!
//! // Commit actual spend (consumes the guard)
//! guard.commit(
//! CommitRequest::builder()
//! .actual(Amount::usd_microcents(3200))
//! .build()
//! ).await?;
//! # Ok(())
//! # }
//! ```
//!
//! ## Automatic Lifecycle (like Python's `@cycles` or TypeScript's `withCycles`)
//!
//! ```rust,no_run
//! use runcycles::{CyclesClient, with_cycles, WithCyclesConfig, models::*};
//!
//! # async fn example() -> Result<(), runcycles::Error> {
//! # let client = CyclesClient::builder("key", "http://localhost:7878").tenant("acme").build();
//! let reply = with_cycles(
//! &client,
//! WithCyclesConfig::new(Amount::tokens(1000))
//! .action("llm.completion", "gpt-4o")
//! .subject(Subject { tenant: Some("acme".into()), ..Default::default() }),
//! |ctx| async move {
//! let result = "Hello from LLM".to_string();
//! Ok((result, Amount::tokens(42)))
//! },
//! ).await?;
//! # Ok(())
//! # }
//! ```
//!
//! ## Design Principles
//!
//! - **Ownership safety**: `commit(self)` and `release(self)` consume the guard,
//! making double-commit a compile error.
//! - **`#[must_use]`**: The compiler warns if a guard is ignored.
//! - **RAII cleanup**: Dropping a guard without commit/release triggers a
//! best-effort release via `tokio::spawn`.
//! - **Type safety**: Newtype IDs prevent mixing `ReservationId` with
//! `IdempotencyKey`. `#[non_exhaustive]` enums enable forward compatibility.
pub
pub
pub
// Re-export primary types at crate root for ergonomic imports.
pub use CyclesClient;
pub use CyclesConfig;
pub use Error;
pub use ReservationGuard;
pub use ;
pub use ApiResponse;
// Re-export BlockingCyclesClient when the blocking feature is enabled.
pub use BlockingCyclesClient;