1use thiserror::Error;
4
5#[derive(Error, Debug)]
7pub enum SDKError {
8 #[error("Provider not found: {0}")]
10 ProviderNotFound(String),
11
12 #[error("No default provider configured")]
14 NoDefaultProvider,
15
16 #[error("Provider error: {0}")]
18 ProviderError(String),
19
20 #[error("Configuration error: {0}")]
22 ConfigError(String),
23
24 #[error("Network error: {0}")]
26 NetworkError(String),
27
28 #[error("Authentication error: {0}")]
30 AuthError(String),
31
32 #[error("Rate limit exceeded: {0}")]
34 RateLimitError(String),
35
36 #[error("Model not found: {0}")]
38 ModelNotFound(String),
39
40 #[error("Feature not supported: {0}")]
42 NotSupported(String),
43
44 #[error("Unsupported provider: {0}")]
46 UnsupportedProvider(String),
47
48 #[error("Serialization error: {0}")]
50 SerializationError(#[from] serde_json::Error),
51
52 #[error("HTTP error: {0}")]
54 HttpError(#[from] reqwest::Error),
55
56 #[error("Invalid request: {0}")]
58 InvalidRequest(String),
59
60 #[error("Internal error: {0}")]
62 Internal(String),
63
64 #[error("API error: {0}")]
66 ApiError(String),
67
68 #[error("Parse error: {0}")]
70 ParseError(String),
71}
72
73impl From<crate::utils::error::gateway_error::GatewayError> for SDKError {
75 fn from(error: crate::utils::error::gateway_error::GatewayError) -> Self {
76 match error {
77 crate::utils::error::gateway_error::GatewayError::Auth(msg) => SDKError::AuthError(msg),
78 crate::utils::error::gateway_error::GatewayError::NotFound(msg) => {
79 SDKError::ModelNotFound(msg)
80 }
81 crate::utils::error::gateway_error::GatewayError::BadRequest(msg) => {
82 SDKError::InvalidRequest(msg)
83 }
84 crate::utils::error::gateway_error::GatewayError::RateLimit { message, .. } => {
85 SDKError::RateLimitError(message)
86 }
87 crate::utils::error::gateway_error::GatewayError::Unavailable(msg) => {
88 SDKError::ProviderError(msg)
89 }
90 crate::utils::error::gateway_error::GatewayError::Internal(msg) => {
91 SDKError::Internal(msg)
92 }
93 crate::utils::error::gateway_error::GatewayError::Network(msg) => {
94 SDKError::NetworkError(msg)
95 }
96 crate::utils::error::gateway_error::GatewayError::Validation(msg) => {
97 SDKError::InvalidRequest(msg)
98 }
99 _ => SDKError::Internal(error.to_string()),
101 }
102 }
103}
104
105pub type Result<T> = std::result::Result<T, SDKError>;
134
135impl SDKError {
136 pub fn is_retryable(&self) -> bool {
138 matches!(
139 self,
140 SDKError::NetworkError(_) | SDKError::RateLimitError(_) | SDKError::ProviderError(_)
141 )
142 }
143
144 pub fn is_auth_error(&self) -> bool {
146 matches!(self, SDKError::AuthError(_))
147 }
148
149 pub fn is_config_error(&self) -> bool {
151 matches!(
152 self,
153 SDKError::ConfigError(_) | SDKError::ProviderNotFound(_) | SDKError::NoDefaultProvider
154 )
155 }
156}
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161 use crate::utils::error::gateway_error::GatewayError;
162
163 #[test]
166 fn test_sdk_error_provider_not_found() {
167 let error = SDKError::ProviderNotFound("openai".to_string());
168 assert_eq!(error.to_string(), "Provider not found: openai");
169 }
170
171 #[test]
172 fn test_sdk_error_no_default_provider() {
173 let error = SDKError::NoDefaultProvider;
174 assert_eq!(error.to_string(), "No default provider configured");
175 }
176
177 #[test]
178 fn test_sdk_error_provider_error() {
179 let error = SDKError::ProviderError("API unavailable".to_string());
180 assert_eq!(error.to_string(), "Provider error: API unavailable");
181 }
182
183 #[test]
184 fn test_sdk_error_config_error() {
185 let error = SDKError::ConfigError("Missing API key".to_string());
186 assert_eq!(error.to_string(), "Configuration error: Missing API key");
187 }
188
189 #[test]
190 fn test_sdk_error_network_error() {
191 let error = SDKError::NetworkError("Connection refused".to_string());
192 assert_eq!(error.to_string(), "Network error: Connection refused");
193 }
194
195 #[test]
196 fn test_sdk_error_auth_error() {
197 let error = SDKError::AuthError("Invalid API key".to_string());
198 assert_eq!(error.to_string(), "Authentication error: Invalid API key");
199 }
200
201 #[test]
202 fn test_sdk_error_rate_limit_error() {
203 let error = SDKError::RateLimitError("Too many requests".to_string());
204 assert_eq!(error.to_string(), "Rate limit exceeded: Too many requests");
205 }
206
207 #[test]
208 fn test_sdk_error_model_not_found() {
209 let error = SDKError::ModelNotFound("gpt-5".to_string());
210 assert_eq!(error.to_string(), "Model not found: gpt-5");
211 }
212
213 #[test]
214 fn test_sdk_error_not_supported() {
215 let error = SDKError::NotSupported("streaming".to_string());
216 assert_eq!(error.to_string(), "Feature not supported: streaming");
217 }
218
219 #[test]
220 fn test_sdk_error_unsupported_provider() {
221 let error = SDKError::UnsupportedProvider("custom-provider".to_string());
222 assert_eq!(error.to_string(), "Unsupported provider: custom-provider");
223 }
224
225 #[test]
226 fn test_sdk_error_invalid_request() {
227 let error = SDKError::InvalidRequest("Missing messages".to_string());
228 assert_eq!(error.to_string(), "Invalid request: Missing messages");
229 }
230
231 #[test]
232 fn test_sdk_error_internal() {
233 let error = SDKError::Internal("Unexpected state".to_string());
234 assert_eq!(error.to_string(), "Internal error: Unexpected state");
235 }
236
237 #[test]
238 fn test_sdk_error_api_error() {
239 let error = SDKError::ApiError("Server returned 500".to_string());
240 assert_eq!(error.to_string(), "API error: Server returned 500");
241 }
242
243 #[test]
244 fn test_sdk_error_parse_error() {
245 let error = SDKError::ParseError("Invalid JSON".to_string());
246 assert_eq!(error.to_string(), "Parse error: Invalid JSON");
247 }
248
249 #[test]
252 fn test_is_retryable_network_error() {
253 let error = SDKError::NetworkError("timeout".to_string());
254 assert!(error.is_retryable());
255 }
256
257 #[test]
258 fn test_is_retryable_rate_limit_error() {
259 let error = SDKError::RateLimitError("limit exceeded".to_string());
260 assert!(error.is_retryable());
261 }
262
263 #[test]
264 fn test_is_retryable_provider_error() {
265 let error = SDKError::ProviderError("unavailable".to_string());
266 assert!(error.is_retryable());
267 }
268
269 #[test]
270 fn test_is_not_retryable_auth_error() {
271 let error = SDKError::AuthError("invalid key".to_string());
272 assert!(!error.is_retryable());
273 }
274
275 #[test]
276 fn test_is_not_retryable_config_error() {
277 let error = SDKError::ConfigError("bad config".to_string());
278 assert!(!error.is_retryable());
279 }
280
281 #[test]
282 fn test_is_not_retryable_invalid_request() {
283 let error = SDKError::InvalidRequest("bad request".to_string());
284 assert!(!error.is_retryable());
285 }
286
287 #[test]
288 fn test_is_not_retryable_internal() {
289 let error = SDKError::Internal("bug".to_string());
290 assert!(!error.is_retryable());
291 }
292
293 #[test]
296 fn test_is_auth_error_true() {
297 let error = SDKError::AuthError("unauthorized".to_string());
298 assert!(error.is_auth_error());
299 }
300
301 #[test]
302 fn test_is_auth_error_false_for_others() {
303 let errors = vec![
304 SDKError::NetworkError("net".to_string()),
305 SDKError::ConfigError("cfg".to_string()),
306 SDKError::RateLimitError("rate".to_string()),
307 SDKError::Internal("int".to_string()),
308 ];
309
310 for error in errors {
311 assert!(!error.is_auth_error());
312 }
313 }
314
315 #[test]
318 fn test_is_config_error_config_error() {
319 let error = SDKError::ConfigError("bad config".to_string());
320 assert!(error.is_config_error());
321 }
322
323 #[test]
324 fn test_is_config_error_provider_not_found() {
325 let error = SDKError::ProviderNotFound("xyz".to_string());
326 assert!(error.is_config_error());
327 }
328
329 #[test]
330 fn test_is_config_error_no_default_provider() {
331 let error = SDKError::NoDefaultProvider;
332 assert!(error.is_config_error());
333 }
334
335 #[test]
336 fn test_is_not_config_error_for_others() {
337 let errors = vec![
338 SDKError::NetworkError("net".to_string()),
339 SDKError::AuthError("auth".to_string()),
340 SDKError::RateLimitError("rate".to_string()),
341 ];
342
343 for error in errors {
344 assert!(!error.is_config_error());
345 }
346 }
347
348 #[test]
351 fn test_from_gateway_error_unauthorized() {
352 let gateway_error = GatewayError::Auth("Invalid token".to_string());
353 let sdk_error: SDKError = gateway_error.into();
354 assert!(matches!(sdk_error, SDKError::AuthError(_)));
355 assert!(sdk_error.is_auth_error());
356 }
357
358 #[test]
359 fn test_from_gateway_error_not_found() {
360 let gateway_error = GatewayError::NotFound("Resource not found".to_string());
361 let sdk_error: SDKError = gateway_error.into();
362 assert!(matches!(sdk_error, SDKError::ModelNotFound(_)));
363 }
364
365 #[test]
366 fn test_from_gateway_error_bad_request() {
367 let gateway_error = GatewayError::BadRequest("Invalid params".to_string());
368 let sdk_error: SDKError = gateway_error.into();
369 assert!(matches!(sdk_error, SDKError::InvalidRequest(_)));
370 }
371
372 #[test]
373 fn test_from_gateway_error_rate_limit() {
374 let gateway_error = GatewayError::RateLimit {
375 message: "Too many requests".to_string(),
376 retry_after: None,
377 rpm_limit: None,
378 tpm_limit: None,
379 };
380 let sdk_error: SDKError = gateway_error.into();
381 assert!(matches!(sdk_error, SDKError::RateLimitError(_)));
382 assert!(sdk_error.is_retryable());
383 }
384
385 #[test]
386 fn test_from_gateway_error_provider_unavailable() {
387 let gateway_error = GatewayError::Unavailable("OpenAI down".to_string());
388 let sdk_error: SDKError = gateway_error.into();
389 assert!(matches!(sdk_error, SDKError::ProviderError(_)));
390 }
391
392 #[test]
393 fn test_from_gateway_error_internal() {
394 let gateway_error = GatewayError::Internal("Unexpected error".to_string());
395 let sdk_error: SDKError = gateway_error.into();
396 assert!(matches!(sdk_error, SDKError::Internal(_)));
397 }
398
399 #[test]
400 fn test_from_gateway_error_network() {
401 let gateway_error = GatewayError::Network("Connection refused".to_string());
402 let sdk_error: SDKError = gateway_error.into();
403 assert!(matches!(sdk_error, SDKError::NetworkError(_)));
404 assert!(sdk_error.is_retryable());
405 }
406
407 #[test]
408 fn test_from_gateway_error_validation() {
409 let gateway_error = GatewayError::Validation("Invalid model".to_string());
410 let sdk_error: SDKError = gateway_error.into();
411 assert!(matches!(sdk_error, SDKError::InvalidRequest(_)));
412 }
413
414 #[test]
415 fn test_from_gateway_error_parsing() {
416 let gateway_error = GatewayError::Validation("Invalid JSON".to_string());
417 let sdk_error: SDKError = gateway_error.into();
418 assert!(matches!(sdk_error, SDKError::InvalidRequest(_)));
419 }
420
421 #[test]
424 fn test_sdk_error_debug() {
425 let error = SDKError::AuthError("test".to_string());
426 let debug_str = format!("{:?}", error);
427 assert!(debug_str.contains("AuthError"));
428 }
429
430 #[test]
431 fn test_sdk_error_is_std_error() {
432 let error = SDKError::Internal("test".to_string());
433 let _: &dyn std::error::Error = &error;
434 }
435
436 #[test]
439 fn test_sdk_error_empty_message() {
440 let error = SDKError::ProviderError("".to_string());
441 assert_eq!(error.to_string(), "Provider error: ");
442 }
443
444 #[test]
445 fn test_sdk_error_unicode() {
446 let error = SDKError::ApiError("错误信息 🚨".to_string());
447 assert!(error.to_string().contains("错误信息"));
448 }
449
450 #[test]
451 fn test_sdk_error_long_message() {
452 let long_msg = "a".repeat(1000);
453 let error = SDKError::Internal(long_msg.clone());
454 assert!(error.to_string().contains(&long_msg));
455 }
456}