ai_lib/types/
error.rs

1use crate::transport::TransportError;
2use thiserror::Error;
3
4#[derive(Error, Debug)]
5pub enum AiLibError {
6    #[error("Provider error: {0}")]
7    ProviderError(String),
8
9    #[error("Transport error: {0}")]
10    TransportError(#[from] TransportError),
11
12    #[error("Invalid request: {0}")]
13    InvalidRequest(String),
14
15    #[error("Rate limit exceeded: {0}")]
16    RateLimitExceeded(String),
17
18    #[error("Authentication failed: {0}")]
19    AuthenticationError(String),
20
21    #[error("Configuration error: {0}")]
22    ConfigurationError(String),
23
24    #[error("Network error: {0}")]
25    NetworkError(String),
26
27    #[error("Timeout error: {0}")]
28    TimeoutError(String),
29
30    #[error("Retry exhausted: {0}")]
31    RetryExhausted(String),
32
33    #[error("Serialization error: {0}")]
34    SerializationError(String),
35
36    #[error("Deserialization error: {0}")]
37    DeserializationError(String),
38
39    #[error("File operation error: {0}")]
40    FileError(String),
41
42    #[error("Unsupported feature: {0}")]
43    UnsupportedFeature(String),
44
45    #[error("Model not found: {0}")]
46    ModelNotFound(String),
47
48    #[error("Invalid model response: {0}")]
49    InvalidModelResponse(String),
50
51    #[error("Context length exceeded: {0}")]
52    ContextLengthExceeded(String),
53}
54
55impl AiLibError {
56    /// Determine if the error is retryable
57    pub fn is_retryable(&self) -> bool {
58        match self {
59            AiLibError::NetworkError(_) => true,
60            AiLibError::TimeoutError(_) => true,
61            AiLibError::RateLimitExceeded(_) => true,
62            AiLibError::TransportError(transport_err) => {
63                // Check if it's a temporary network error
64                transport_err.to_string().contains("timeout")
65                    || transport_err.to_string().contains("connection")
66                    || transport_err.to_string().contains("temporary")
67            }
68            _ => false,
69        }
70    }
71
72    /// Get suggested retry delay (milliseconds)
73    pub fn retry_delay_ms(&self) -> u64 {
74        match self {
75            AiLibError::RateLimitExceeded(_) => 60000, // 1 minute
76            AiLibError::NetworkError(_) => 1000,       // 1 second
77            AiLibError::TimeoutError(_) => 2000,       // 2 seconds
78            _ => 1000,
79        }
80    }
81
82    /// Get error context for debugging
83    pub fn context(&self) -> &str {
84        match self {
85            AiLibError::ProviderError(_) => "Provider API call failed",
86            AiLibError::TransportError(_) => "Network transport layer error",
87            AiLibError::InvalidRequest(_) => "Invalid request parameters",
88            AiLibError::RateLimitExceeded(_) => "API rate limit exceeded",
89            AiLibError::AuthenticationError(_) => "Authentication failed",
90            AiLibError::ConfigurationError(_) => "Configuration validation failed",
91            AiLibError::NetworkError(_) => "Network connectivity issue",
92            AiLibError::TimeoutError(_) => "Request timed out",
93            AiLibError::RetryExhausted(_) => "All retry attempts failed",
94            AiLibError::SerializationError(_) => "Request serialization failed",
95            AiLibError::DeserializationError(_) => "Response deserialization failed",
96            AiLibError::FileError(_) => "File operation failed",
97            AiLibError::UnsupportedFeature(_) => "Feature not supported by provider",
98            AiLibError::ModelNotFound(_) => "Specified model not found",
99            AiLibError::InvalidModelResponse(_) => "Invalid response from model",
100            AiLibError::ContextLengthExceeded(_) => "Context length limit exceeded",
101        }
102    }
103
104    /// Check if error is related to authentication
105    pub fn is_auth_error(&self) -> bool {
106        match self {
107            AiLibError::AuthenticationError(_) => true,
108            AiLibError::TransportError(TransportError::AuthenticationError(_)) => true,
109            AiLibError::TransportError(TransportError::ClientError { status, .. }) => {
110                *status == 401 || *status == 403
111            }
112            _ => false,
113        }
114    }
115
116    /// Check if error is related to configuration
117    pub fn is_config_error(&self) -> bool {
118        matches!(self, AiLibError::ConfigurationError(_))
119    }
120
121    /// Check if error is related to request validation
122    pub fn is_request_error(&self) -> bool {
123        matches!(
124            self,
125            AiLibError::InvalidRequest(_)
126                | AiLibError::ContextLengthExceeded(_)
127                | AiLibError::UnsupportedFeature(_)
128        )
129    }
130}