Skip to main content

ai_agent/services/api/
error_utils.rs

1//! API error utilities - translated from errorUtils.ts
2
3use serde::{Deserialize, Serialize};
4
5/// Extract connection error details from an error
6#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7pub struct ConnectionErrorDetails {
8    pub is_ssl_error: bool,
9    pub is_timeout: bool,
10    pub is_connection_refused: bool,
11    pub errno: Option<String>,
12}
13
14/// Extract connection error details from an error message
15pub fn extract_connection_error_details(error: &str) -> Option<ConnectionErrorDetails> {
16    let lower = error.to_lowercase();
17
18    Some(ConnectionErrorDetails {
19        is_ssl_error: lower.contains("ssl")
20            || lower.contains("tls")
21            || lower.contains("certificate"),
22        is_timeout: lower.contains("timeout") || lower.contains("timed out"),
23        is_connection_refused: lower.contains("connection refused")
24            || lower.contains("econnrefused"),
25        errno: None, // Would need more context to extract
26    })
27}
28
29/// Format an API error for display
30pub fn format_api_error(error: &str) -> String {
31    let lower = error.to_lowercase();
32
33    if lower.contains("timeout") || lower.contains("timed out") {
34        return "Connection timeout. Please check your network and try again.".to_string();
35    }
36
37    if lower.contains("certificate") || lower.contains("ssl") || lower.contains("tls") {
38        return "SSL/TLS certificate error. Please check your system date and network.".to_string();
39    }
40
41    if lower.contains("connection refused") || lower.contains("econnrefused") {
42        return "Connection refused. The server may be down or unreachable.".to_string();
43    }
44
45    if lower.contains("dns")
46        || lower.contains("getaddrinfo")
47        || lower.contains("ename or service not known")
48    {
49        return "DNS error. Please check your internet connection.".to_string();
50    }
51
52    // Generic fallback
53    "Connection error. Please check your network and try again.".to_string()
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59
60    #[test]
61    fn test_extract_connection_error_details_timeout() {
62        let details = extract_connection_error_details("Connection timeout").unwrap();
63        assert!(details.is_timeout);
64        assert!(!details.is_ssl_error);
65    }
66
67    #[test]
68    fn test_extract_connection_error_details_ssl() {
69        let details = extract_connection_error_details("SSL certificate error").unwrap();
70        assert!(details.is_ssl_error);
71        assert!(!details.is_timeout);
72    }
73
74    #[test]
75    fn test_format_api_error_timeout() {
76        let msg = format_api_error("Connection timed out");
77        assert!(msg.contains("timeout"));
78    }
79
80    #[test]
81    fn test_format_api_error_ssl() {
82        let msg = format_api_error("SSL certificate problem");
83        assert!(msg.contains("SSL") || msg.contains("certificate"));
84    }
85}