1#![deny(missing_docs)]
49#![deny(unsafe_code)]
50
51pub mod cache;
53pub mod coercion;
54pub mod config;
55pub mod error;
56pub mod message;
57pub mod provider;
58pub mod request;
59pub mod response;
60pub mod router;
61pub mod tool;
62pub mod validation;
63
64pub use error::{HealingError, ProviderError, Result, SimpleAgentsError, ValidationError};
66
67pub mod prelude {
81 pub use crate::message::{Message, Role};
83
84 pub use crate::request::{CompletionRequest, CompletionRequestBuilder};
86 pub use crate::response::{
87 ChoiceDelta, CompletionChoice, CompletionChunk, CompletionResponse, FinishReason,
88 MessageDelta, Usage,
89 };
90
91 pub use crate::error::{
93 HealingError, ProviderError, Result, SimpleAgentsError, ValidationError,
94 };
95
96 pub use crate::validation::ApiKey;
98
99 pub use crate::config::{Capabilities, HealingConfig, ProviderConfig, RetryConfig};
101
102 pub use crate::coercion::{CoercionFlag, CoercionResult};
104
105 pub use crate::tool::{
107 ToolCall, ToolCallFunction, ToolChoice, ToolChoiceFunction, ToolChoiceMode, ToolChoiceTool,
108 ToolDefinition, ToolFunction, ToolType,
109 };
110
111 pub use crate::cache::Cache;
113 pub use crate::provider::Provider;
114 pub use crate::router::RoutingStrategy;
115
116 pub use crate::provider::{ProviderRequest, ProviderResponse};
118
119 pub use crate::router::{ProviderHealth, ProviderMetrics, RoutingMode};
121}
122
123#[cfg(test)]
124mod tests {
125 use super::prelude::*;
126
127 #[test]
128 fn test_prelude_imports() {
129 let _msg = Message::user("test");
131 let _request = CompletionRequest::builder()
132 .model("test")
133 .message(Message::user("test"))
134 .build()
135 .unwrap();
136 }
137
138 #[test]
139 fn test_error_conversion() {
140 let validation_err = ValidationError::new("test");
141 let _agents_err: SimpleAgentsError = validation_err.into();
142 }
143
144 #[test]
145 fn test_api_key_security() {
146 let key = ApiKey::new("sk-1234567890abcdef1234567890").unwrap();
147 let debug = format!("{:?}", key);
148 assert!(debug.contains("REDACTED"));
149 }
150
151 #[test]
152 fn test_coercion_transparency() {
153 let result = CoercionResult::new(42).with_flag(CoercionFlag::StrippedMarkdown);
154 assert!(result.was_coerced());
155 assert_eq!(result.flags.len(), 1);
156 }
157
158 #[test]
159 fn test_builder_pattern() {
160 let request = CompletionRequest::builder()
161 .model("gpt-4")
162 .message(Message::user("Hello"))
163 .temperature(0.7)
164 .build()
165 .unwrap();
166
167 assert_eq!(request.model, "gpt-4");
168 assert_eq!(request.temperature, Some(0.7));
169 }
170
171 #[test]
172 fn test_response_helper() {
173 let response = CompletionResponse {
174 id: "resp_123".to_string(),
175 model: "gpt-4".to_string(),
176 choices: vec![CompletionChoice {
177 index: 0,
178 message: Message::assistant("Hello!"),
179 finish_reason: FinishReason::Stop,
180 logprobs: None,
181 }],
182 usage: Usage::new(10, 5),
183 created: None,
184 provider: None,
185 healing_metadata: None,
186 };
187
188 assert_eq!(response.content(), Some("Hello!"));
189 }
190
191 #[test]
192 fn test_all_types_send_sync() {
193 fn assert_send_sync<T: Send + Sync>() {}
194
195 assert_send_sync::<Message>();
197 assert_send_sync::<CompletionRequest>();
198 assert_send_sync::<CompletionResponse>();
199
200 assert_send_sync::<RetryConfig>();
202 assert_send_sync::<HealingConfig>();
203 assert_send_sync::<Capabilities>();
204
205 assert_send_sync::<CoercionFlag>();
207 assert_send_sync::<CoercionResult<String>>();
208
209 assert_send_sync::<ProviderRequest>();
211 assert_send_sync::<ProviderResponse>();
212 }
213}