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
//! A unified Rust SDK for backend AI workflows across OpenAI, Anthropic, and
//! OpenRouter.
//!
//! `rai-sdk` wraps three provider APIs behind one typed client so switching
//! models does not mean rewriting request-building, streaming, or tool-calling
//! code.
//!
//! # Capabilities
//!
//! - **Typed providers and models** — construct models with [`Model::gpt4o_mini`],
//! [`Model::claude_sonnet_46`], or [`Model::openrouter_auto`], or pass any
//! provider model ID directly.
//! - **Typestate request builders** — [`RequestBuilder::generate`] only exists
//! once a prompt and a model are present, so incomplete requests fail to
//! compile rather than at runtime.
//! - **Structured output** — derive [`JsonSchema`] and call
//! [`RequestBuilder::generate_structured`] to validate the response against a
//! generated schema and deserialize it into your own type.
//! - **Tool calling** — register typed async tools with [`Tool`];
//! [`RequestBuilder::generate`] runs the tool loop, feeding results back until
//! the model produces a final answer.
//! - **Streaming** — consume raw provider events, or use
//! [`RequestBuilder::stream_accumulated`] to stream internally and return a
//! complete [`Response`].
//! - **Proxyable streams** — [`RequestBuilder::stream_wire_events`] yields
//! serializable [`WireStreamEvent`]s so a server can re-emit a generation to
//! its own clients over SSE, and [`StreamAccumulator`] reassembles them on the
//! far end. See the [`wire`] module.
//! - **Retries** — transient rate-limit, timeout, and HTTP failures are retried
//! with configurable exponential backoff and jitter via [`RetryConfig`].
//! - **Multimodal prompts** — build prompts from text, image, audio, video, and
//! file [`ContentBlock`]s. Provider support varies.
//! - **Local and self-hosted models** — point a client at any endpoint speaking
//! the OpenAI Chat Completions format with
//! [`ClientBuilder::openai_compatible_base_url`] (or
//! [`ClientBuilder::ollama`]) and name models with
//! [`Model::openai_compatible`]. See the `provider::openai_compatible`
//! module, which the `openai` feature gates.
//!
//! # Quickstart
//!
//! ```no_run
//! use rai_sdk::{ClientBuilder, Model};
//!
//! # async fn run() -> Result<(), Box<dyn std::error::Error>> {
//! let client = ClientBuilder::new()
//! .from_env()
//! .model(Model::gpt4o_mini())
//! .build()?;
//!
//! let response = client
//! .request()
//! .prompt("Explain Rust ownership in two sentences.")
//! .generate()
//! .await?;
//!
//! println!("{}", response.text());
//! # Ok(())
//! # }
//! ```
//!
//! # Configuration
//!
//! [`ClientBuilder::from_env`] reads `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, and
//! `OPENROUTER_API_KEY`, along with optional base-URL, timeout, and retry
//! overrides. Everything can also be set explicitly on [`ClientBuilder`] or
//! [`Config`], and explicit values take precedence over the environment.
//!
//! # Cargo features
//!
//! The `openai`, `anthropic`, and `openrouter` features are all enabled by
//! default and gate the corresponding provider support. Disable the defaults to
//! compile against only the providers you use.
//!
//! `openai` additionally gates the OpenAI-compatible provider, which reuses
//! that module's request builder and stream parser rather than duplicating
//! them. A build that talks only to local models therefore enables `openai`
//! and nothing else.
//!
//! Enabling a provider also requires at least one TLS backend:
//!
//! - `rustls-tls` (default) needs no system OpenSSL, but builds `aws-lc-rs`,
//! which requires cmake and a C compiler.
//! - `native-tls` uses the platform TLS stack instead, avoiding that build
//! requirement.
//!
//! Because a TLS backend is part of the default feature set, disabling default
//! features means re-enabling one explicitly:
//!
//! ```toml
//! rai-sdk = { version = "0.1", default-features = false, features = ["anthropic", "native-tls"] }
//! ```
//!
//! Cargo features are additive, so dependency feature unification can enable
//! both backends. That configuration is supported and uses rustls; select only
//! `native-tls` as shown above to avoid compiling `aws-lc-rs`.
//!
//! # Further reading
//!
//! The [guide](https://rmagatti.github.io/rai-sdk/) covers each capability in
//! task-oriented chapters. Its examples are compile-checked against this crate,
//! so they stay in sync with the API you see here.
// Catch a provider without a TLS backend at compile time. A featureless build
// is valid because it cannot make provider requests and is still useful to
// consumers that only need the crate's shared data types.
compile_error!;
// Compile-check every Rust snippet in the mdBook guide as a doctest, so the
// published guide cannot drift away from the real API. This module only exists
// while rustdoc is collecting doctests, so it adds nothing to the built crate or
// to the rendered documentation.