1#![deny(missing_docs)]
48#![deny(unsafe_code)]
49
50pub mod coercion;
52pub mod error;
53pub mod message;
54pub mod provider;
55pub mod request;
56pub mod response;
57pub mod telemetry;
59pub mod tool;
60pub mod validation;
61
62pub use error::{HealingError, ProviderError, Result, SimpleAgentsError, ValidationError};
64pub use telemetry::{ApiFormat, OtelProtocol, TelemetryConfig, TraceContext};
65
66pub mod prelude {
80 pub use crate::message::{
82 mime, ContentPart, ImageUrlContent, MediaContent, Message, MessageContent, Role,
83 };
84
85 pub use crate::request::{CompletionRequest, CompletionRequestBuilder};
87 pub use crate::response::{
88 ChoiceDelta, CompletionChoice, CompletionChunk, CompletionResponse, FinishReason,
89 MessageDelta, Usage,
90 };
91
92 pub use crate::error::{
94 HealingError, ProviderError, Result, SimpleAgentsError, ValidationError,
95 };
96
97 pub use crate::validation::ApiKey;
99
100 pub use crate::coercion::{CoercionFlag, CoercionResult};
102
103 pub use crate::tool::{
105 ToolCall, ToolCallFunction, ToolChoice, ToolChoiceFunction, ToolChoiceMode, ToolChoiceTool,
106 ToolDefinition, ToolFunction, ToolType,
107 };
108
109 pub use crate::provider::Provider;
111
112 pub use crate::provider::{ProviderRequest, ProviderResponse};
114}
115
116#[cfg(test)]
117mod tests {
118 use super::prelude::*;
119
120 #[test]
121 fn test_prelude_imports() {
122 let _msg = Message::user("test");
123 let _request = CompletionRequest::builder()
124 .model("test")
125 .message(Message::user("test"))
126 .build()
127 .unwrap();
128 }
129
130 #[test]
131 fn test_error_conversion() {
132 let validation_err = ValidationError::new("test");
133 let _agents_err: SimpleAgentsError = validation_err.into();
134 }
135
136 #[test]
137 fn test_api_key_security() {
138 let key = ApiKey::new("sk-1234567890abcdef1234567890").unwrap();
139 let debug = format!("{:?}", key);
140 assert!(debug.contains("REDACTED"));
141 }
142
143 #[test]
144 fn test_coercion_transparency() {
145 let result = CoercionResult::new(42).with_flag(CoercionFlag::StrippedMarkdown);
146 assert!(result.was_coerced());
147 assert_eq!(result.flags.len(), 1);
148 }
149
150 #[test]
151 fn test_builder_pattern() {
152 let request = CompletionRequest::builder()
153 .model("gpt-4")
154 .message(Message::user("Hello"))
155 .temperature(0.7)
156 .build()
157 .unwrap();
158
159 assert_eq!(request.model, "gpt-4");
160 assert_eq!(request.temperature, Some(0.7));
161 }
162
163 #[test]
164 fn test_response_helper() {
165 let response = CompletionResponse {
166 id: "resp_123".to_string(),
167 model: "gpt-4".to_string(),
168 choices: vec![CompletionChoice {
169 index: 0,
170 message: Message::assistant("Hello!"),
171 finish_reason: FinishReason::Stop,
172 logprobs: None,
173 }],
174 usage: Usage::new(10, 5),
175 created: None,
176 provider: None,
177 healing_metadata: None,
178 };
179
180 assert_eq!(response.content(), Some("Hello!"));
181 }
182
183 #[test]
184 fn test_all_types_send_sync() {
185 fn assert_send_sync<T: Send + Sync>() {}
186
187 assert_send_sync::<Message>();
189 assert_send_sync::<CompletionRequest>();
190 assert_send_sync::<CompletionResponse>();
191
192 assert_send_sync::<CoercionFlag>();
194 assert_send_sync::<CoercionResult<String>>();
195
196 assert_send_sync::<ProviderRequest>();
198 assert_send_sync::<ProviderResponse>();
199 }
200}