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
//! Provider integrations included in `rig-core`.
//!
//! - Anthropic
//! - Azure OpenAI
//! - ChatGPT and GitHub Copilot auth-backed clients
//! - Cohere
//! - DeepSeek
//! - Gemini
//! - Groq
//! - Hugging Face
//! - Hyperbolic
//! - Llamafile
//! - MiniMax
//! - Mira
//! - Mistral
//! - Moonshot
//! - Ollama
//! - OpenAI
//! - OpenRouter
//! - Perplexity
//! - Together
//! - Venice
//! - Voyage AI
//! - xAI
//! - Xiaomi MiMo
//! - Z.ai
//!
//! Each provider module defines a `Client` type and model types for the
//! capabilities it supports. Capability traits such as
//! [`CompletionClient`](crate::client::CompletionClient) and
//! [`EmbeddingsClient`](crate::client::EmbeddingsClient) are implemented only
//! when the provider declares that capability.
//!
//! # Provider implementation checklist
//!
//! When adding or changing a provider, verify that the integration includes:
//!
//! - for OpenAI-chat-compatible APIs: completions driven by
//! [`GenericCompletionModel`](crate::providers::openai::completion::GenericCompletionModel)
//! via an
//! [`OpenAICompatibleProvider`](crate::providers::openai::completion::OpenAICompatibleProvider)
//! impl on the provider extension (never a hand-rolled completion model,
//! request struct, or message conversion — dialect differences go in the
//! trait's hooks);
//! - public `Client` and `ClientBuilder` aliases with the correct generics,
//! including a `ClientBuilder` API-key generic matching `ProviderBuilder::ApiKey`;
//! - the `Provider`, `ProviderBuilder`, `Capabilities`, and `ProviderClient`
//! implementations;
//! - explicit API-key marker/auth types with redacted debug behavior for
//! credential-bearing values;
//! - model constants where they are useful and current;
//! - request conversion from Rig request types, such as
//! [`CompletionRequest`](crate::completion::CompletionRequest), without
//! inventing unsupported provider API fields;
//! - response conversion into Rig response types, including usage and tool or
//! multimodal content where applicable, built through the
//! [`CompletionResponse`](crate::completion::CompletionResponse) `new`/`with_*`
//! builders rather than a struct literal — the `with_*_finish_reason` setters
//! are what apply
//! [`FinishReason::reconcile_with_output`](crate::completion::FinishReason::reconcile_with_output);
//! - a finish-reason mapping covering every value the provider can report,
//! with anything unrecognized preserved verbatim in
//! [`FinishReason::Other`](crate::completion::FinishReason::Other) rather
//! than guessed at;
//! - a shared conversion (one used by several OpenAI-compatible providers)
//! that takes the provider descriptor name as an input instead of hardcoding
//! one, so a reused wire type cannot mislabel its provider;
//! - `raw_completion` and `raw_stream` inherent methods returning the
//! provider's own wire types, with the normalized
//! [`CompletionModel`](crate::completion::CompletionModel) methods delegating
//! to them so there is exactly one request path either way;
//! - streaming support when the provider supports streaming;
//! - provider-response error preservation plus `ProviderResponseExt` and
//! telemetry fields consistent with nearby providers where applicable;
//! - unit, cassette, or live-test coverage appropriate to the changed behavior;
//! - root facade feature/docs updates for companion provider crates; and
//! - examples and documentation that match the actual API, feature flags, and
//! credential requirements.
//!
//! # Example
//! ```no_run
//! use rig_core::{
//! client::{CompletionClient, ProviderClient},
//! completion::{AssistantContent, CompletionModel},
//! providers::openai,
//! };
//!
//! # async fn run() -> Result<(), Box<dyn std::error::Error>> {
//! // Initialize the OpenAI client
//! let openai = openai::Client::from_env()?;
//!
//! // Create a model and send a low-level completion request.
//! let model = openai.completion_model(openai::GPT_5_2);
//! let request = model
//! .completion_request("Discuss the fate of Middle Earth.")
//! .preamble("\
//! You are Gandalf the white and you will be conversing with other \
//! powerful beings to discuss the fate of Middle Earth.\
//! ".to_string())
//! .build();
//! let response = model.completion(request).await?;
//! for item in response.choice {
//! if let AssistantContent::Text(text) = item {
//! println!("{}", text.text);
//! }
//! }
//! # Ok(())
//! # }
//! ```