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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
//! # Open Agent SDK - Rust Implementation
//!
//! A production-ready, streaming-first Rust SDK for building AI agents over two wire
//! protocols: OpenAI chat completions and Anthropic messages.
//!
//! ## Overview
//!
//! The protocol is a property of the endpoint. Select it with
//! `AgentOptions::builder().protocol(..)`; it defaults to [`ApiProtocol::OpenAiChat`].
//!
//! [`ApiProtocol::OpenAiChat`] posts to `{base_url}/chat/completions` with bearer auth:
//! - LM Studio, Ollama, llama.cpp, vLLM, and other local servers
//! - OpenAI, OpenRouter, z.ai, and other hosted OpenAI-compatible endpoints
//!
//! [`ApiProtocol::Anthropic`] posts to `{base_url}/messages` with `x-api-key` and
//! `anthropic-version`:
//! - Anthropic
//! - Moonshot Kimi for Coding, MiniMax, and other Anthropic-shaped endpoints
//!
//! ## Key Features
//!
//! - **Two Wire Protocols**: OpenAI chat completions or Anthropic messages, per endpoint
//! - **Local or Hosted**: Zero-cost inference on your own hardware, or a vendor endpoint
//! - **High Performance**: Native async/await with Tokio runtime
//! - **Streaming Responses**: Text and reasoning reach the caller fragment by fragment,
//! while the stream is still open
//! - **Finish Reasons**: Every stream reports why generation stopped
//! - **Reasoning Channel**: Extended thinking and reasoning deltas kept out of content
//! - **Tool Calling**: Define and execute tools with automatic schema generation
//! - **Lifecycle Hooks**: Intercept and control execution at key points
//! - **Interrupts**: Gracefully cancel long-running operations
//! - **Context Management**: Manual token estimation and history truncation
//! - **Retry Logic**: Exponential backoff with jitter for reliability
//!
//! ## Two Interaction Modes
//!
//! ### 1. Simple Query Function (`query()`)
//! For single-turn interactions without conversation state:
//!
//! ```rust,no_run
//! use open_agent::{query, AgentOptions, ContentBlock, FinishReason, StreamEvent};
//! use futures::StreamExt;
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! // Configure the agent with required settings
//! let options = AgentOptions::builder()
//! .system_prompt("You are a helpful assistant")
//! .model("qwen2.5-32b-instruct")
//! .base_url("http://localhost:1234/v1")
//! .build()?;
//!
//! // Send a single query and stream the response
//! let mut stream = query("What's the capital of France?", &options).await?;
//!
//! // Process each event as it arrives; the stream always ends with one Finish
//! while let Some(event) = stream.next().await {
//! match event? {
//! StreamEvent::Block(ContentBlock::Text(text_block)) => {
//! print!("{}", text_block.text);
//! }
//! StreamEvent::Block(ContentBlock::ToolUse(tool_block)) => {
//! println!("Tool called: {}", tool_block.name());
//! }
//! StreamEvent::Finish(FinishReason::Length) => {
//! eprintln!("response was truncated at the token cap");
//! }
//! _ => {}
//! }
//! }
//!
//! Ok(())
//! }
//! ```
//!
//! ### 2. Client Object (`Client`)
//! For multi-turn conversations with persistent state:
//!
//! ```rust,no_run
//! use open_agent::{Client, AgentOptions, ContentBlock};
//! use futures::StreamExt;
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let options = AgentOptions::builder()
//! .system_prompt("You are a helpful assistant")
//! .model("qwen2.5-32b-instruct")
//! .base_url("http://localhost:1234/v1")
//! .build()?;
//!
//! // Create a stateful client that maintains conversation history
//! let mut client = Client::new(options)?;
//!
//! // First turn
//! client.send("What's 2+2?").await?;
//! while let Some(block) = client.receive().await? {
//! match block {
//! ContentBlock::Text(text) => print!("{}", text.text),
//! ContentBlock::ToolUse(_) | ContentBlock::ToolResult(_) | ContentBlock::Image(_) => {}
//! }
//! }
//!
//! // Second turn - client remembers previous context
//! client.send("What about if we multiply that by 3?").await?;
//! while let Some(block) = client.receive().await? {
//! match block {
//! ContentBlock::Text(text) => print!("{}", text.text),
//! ContentBlock::ToolUse(_) | ContentBlock::ToolResult(_) | ContentBlock::Image(_) => {}
//! }
//! }
//!
//! Ok(())
//! }
//! ```
//!
//! ## Architecture
//!
//! The SDK is organized into several modules, each with a specific responsibility:
//!
//! - **client**: Core streaming query engine and multi-turn client, and the transport
//! boundary where the protocol is applied
//! - **types**: Data structures for messages, content blocks, configuration, and the
//! OpenAI and Anthropic wire formats
//! - **tools**: Tool definition system with automatic JSON schema generation
//! - **hooks**: Lifecycle event system for intercepting execution
//! - **config**: Provider-specific configuration helpers
//! - **error**: Comprehensive error types and conversions
//! - **context**: Token estimation and message truncation utilities
//! - **retry**: Exponential backoff retry logic with jitter
//! - **utils**: Internal utilities for SSE parsing and tool aggregation
// ============================================================================
// MODULE DECLARATIONS
// ============================================================================
// These modules are private (internal implementation details) unless explicitly
// re-exported through `pub use` statements below.
/// Core client implementation providing streaming queries and stateful conversations.
/// Contains the `query()` function for single-turn queries and `Client` struct
/// for multi-turn conversations with automatic state management.
/// Provider configuration helpers for LM Studio, Ollama, llama.cpp, and vLLM.
/// Simplifies endpoint and model name resolution with environment variable support.
/// Context window management utilities for token estimation and history truncation.
/// Provides manual control over conversation memory to prevent context overflow.
/// Error types and conversions for comprehensive error handling throughout the SDK.
/// Defines the `Error` enum and `Result<T>` type alias used across all public APIs.
/// Lifecycle hooks system for intercepting and controlling execution at key points.
/// Enables security gates, audit logging, input/output modification, and compliance checks.
/// Tool definition and execution system with automatic JSON schema generation.
/// Allows LLMs to call Rust functions with type-safe parameter handling.
/// Core type definitions for messages, content blocks, and agent configuration.
/// Includes builder patterns for ergonomic configuration, the `ApiProtocol` selector, and
/// the OpenAI and Anthropic wire formats.
/// Internal utilities for Server-Sent Events (SSE) parsing and tool call aggregation.
/// Handles the low-level details of streaming response parsing for both protocols.
// ============================================================================
// PUBLIC EXPORTS
// ============================================================================
// These items form the public API of the SDK. Everything else is internal.
/// Retry utilities with exponential backoff and jitter.
/// Made public as a module so users can access retry configuration and functions
/// for their own operations that need retry logic.
// --- Core Client API ---
pub use ;
// --- Stream Assembly ---
//
// The counterpart to fragment-by-fragment delivery: the join the SDK applies before writing a
// turn to history, exported so a caller holding collected blocks can apply the same one.
pub use coalesce_text_blocks;
// --- Provider Configuration ---
pub use ;
// --- Context Management ---
pub use ;
// --- Error Handling ---
pub use ;
// --- Lifecycle Hooks ---
pub use ;
// --- Tool System ---
pub use ;
// --- Core Types ---
pub use ;
// --- Anthropic Wire Format ---
//
// Exported for the same reason the OpenAI wire types are: a caller building a gateway, a
// recording proxy, or a test double needs to name what goes over the wire.
pub use ;
// `AnthropicRequest::from_openai` takes an `OpenAIRequest`, so the request half of the
// OpenAI wire format has to be nameable for that constructor to be callable at all.
pub use ;
// ============================================================================
// CONVENIENCE PRELUDE
// ============================================================================
/// Convenience module containing the most commonly used types and functions.
/// Import with `use open_agent::prelude::*;` to get everything you need for typical usage.
///
/// This includes:
/// - Configuration: AgentOptions, AgentOptionsBuilder, ApiProtocol
/// - Client: Client, query()
/// - Content: ContentBlock, TextBlock, ToolUseBlock
/// - Streaming: StreamEvent, FinishReason
/// - Tools: Tool, tool()
/// - Hooks: Hooks, HookDecision, hook event types
/// - Errors: Error, Result