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