1use thiserror::Error;
7
8pub type Result<T> = std::result::Result<T, Error>;
10
11#[derive(Error, Debug)]
13pub enum Error {
14 #[error("Inference error: {0}")]
16 Inference(String),
17
18 #[error("Context length exceeded: {0}")]
20 ContextLengthExceeded(String),
21
22 #[error("Retries exceeded: {0}")]
24 RetriesExceeded(String),
25
26 #[error("Non-retryable error: {0}")]
28 NonRetryable(String),
29
30 #[error("Parse error: {0}")]
32 Parse(String),
33
34 #[error("Validation error: {0}")]
36 Validation(String),
37
38 #[error("Tool not found: {0}")]
40 ToolNotFound(String),
41
42 #[error("Network error: {0}")]
44 Network(#[from] reqwest::Error),
45
46 #[error("JSON error: {0}")]
48 Json(#[from] serde_json::Error),
49
50 #[error("UTF-8 error: {0}")]
52 Utf8(#[from] std::str::Utf8Error),
53
54 #[error("UTF-8 conversion error: {0}")]
56 FromUtf8(#[from] std::string::FromUtf8Error),
57
58 #[error("IO error: {0}")]
60 Io(#[from] std::io::Error),
61
62 #[error("Invalid provider: {0}")]
64 InvalidProvider(String),
65
66 #[error("Missing API key: {0}")]
68 MissingApiKey(String),
69
70 #[error("Runtime was not used in agentic function")]
72 RuntimeNotUsed,
73}
74
75impl Error {
76 pub fn is_retryable(&self) -> bool {
78 matches!(self, Error::Inference(_) | Error::Network(_) | Error::Io(_))
79 }
80
81 pub fn is_retries_exceeded(&self) -> bool {
83 matches!(self, Error::RetriesExceeded(_))
84 }
85
86 pub fn is_incomplete(&self) -> bool {
88 matches!(self, Error::Parse(msg) if msg.contains("incomplete"))
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn test_error_display() {
98 let err = Error::Inference("rate limit".to_string());
99 assert_eq!(err.to_string(), "Inference error: rate limit");
100 }
101
102 #[test]
103 fn test_is_retryable() {
104 assert!(Error::Inference("test".to_string()).is_retryable());
105 assert!(Error::Io(std::io::Error::other("test")).is_retryable());
106 assert!(!Error::NonRetryable("test".to_string()).is_retryable());
107 assert!(!Error::Validation("test".to_string()).is_retryable());
108 }
109
110 #[test]
111 fn test_is_retries_exceeded() {
112 assert!(Error::RetriesExceeded("test".to_string()).is_retries_exceeded());
113 assert!(!Error::Inference("test".to_string()).is_retries_exceeded());
114 }
115
116 #[test]
117 fn test_is_incomplete() {
118 assert!(Error::Parse("incomplete data".to_string()).is_incomplete());
119 assert!(!Error::Parse("malformed json".to_string()).is_incomplete());
120 }
121
122 #[test]
123 fn test_from_conversions() {
124 let json_err: Error = serde_json::from_str::<i32>("invalid").unwrap_err().into();
125 assert!(matches!(json_err, Error::Json(_)));
126
127 let io_err: Error = std::io::Error::other("test").into();
128 assert!(matches!(io_err, Error::Io(_)));
129 }
130}