1use thiserror::Error;
8
9#[derive(Error, Debug)]
10pub enum MojenticError {
11 #[error("LLM gateway error: {0}")]
12 GatewayError(String),
13
14 #[error("API error: {0}")]
15 ApiError(String),
16
17 #[error("Serialization error: {0}")]
18 SerializationError(#[from] serde_json::Error),
19
20 #[error("HTTP error: {0}")]
21 HttpError(#[from] reqwest::Error),
22
23 #[error("Tool error: {0}")]
24 ToolError(String),
25
26 #[error("Model not supported: {0}")]
27 ModelNotSupported(String),
28
29 #[error("Invalid configuration: {0}")]
30 ConfigError(String),
31
32 #[error("IO error: {0}")]
33 IoError(#[from] std::io::Error),
34
35 #[error("Event processing error: {0}")]
36 EventError(String),
37
38 #[error("Agent error: {0}")]
39 AgentError(String),
40
41 #[error("Dispatcher error: {0}")]
42 DispatcherError(String),
43
44 #[error("Timeout error: {0}")]
45 TimeoutError(String),
46
47 #[error("Invalid argument: {0}")]
48 InvalidArgument(String),
49
50 #[error("Parse error: {0}")]
51 ParseError(String),
52
53 #[error("Tool execution error: {0}")]
54 ToolExecutionError(String),
55
56 #[error("Runtime error: {0}")]
57 RuntimeError(String),
58}
59
60pub type Result<T> = std::result::Result<T, MojenticError>;
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn test_gateway_error_display() {
68 let err = MojenticError::GatewayError("connection failed".to_string());
69 assert_eq!(err.to_string(), "LLM gateway error: connection failed");
70 }
71
72 #[test]
73 fn test_api_error_display() {
74 let err = MojenticError::ApiError("rate limit exceeded".to_string());
75 assert_eq!(err.to_string(), "API error: rate limit exceeded");
76 }
77
78 #[test]
79 fn test_tool_error_display() {
80 let err = MojenticError::ToolError("invalid parameters".to_string());
81 assert_eq!(err.to_string(), "Tool error: invalid parameters");
82 }
83
84 #[test]
85 fn test_model_not_supported_display() {
86 let err = MojenticError::ModelNotSupported("gpt-5".to_string());
87 assert_eq!(err.to_string(), "Model not supported: gpt-5");
88 }
89
90 #[test]
91 fn test_config_error_display() {
92 let err = MojenticError::ConfigError("missing API key".to_string());
93 assert_eq!(err.to_string(), "Invalid configuration: missing API key");
94 }
95
96 #[test]
97 fn test_serialization_error_conversion() {
98 let json_err = serde_json::from_str::<serde_json::Value>("invalid json").unwrap_err();
99 let err: MojenticError = json_err.into();
100
101 match err {
102 MojenticError::SerializationError(_) => {}
103 _ => panic!("Expected SerializationError"),
104 }
105 }
106
107 #[test]
108 fn test_http_error_conversion() {
109 let invalid_url = reqwest::Url::parse("http://").unwrap_err();
111 let err = MojenticError::ApiError(invalid_url.to_string());
113 assert!(err.to_string().contains("API error"));
114 }
115
116 #[test]
117 fn test_io_error_conversion() {
118 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
119 let err: MojenticError = io_err.into();
120
121 match err {
122 MojenticError::IoError(_) => {}
123 _ => panic!("Expected IoError"),
124 }
125 }
126
127 #[test]
128 fn test_error_debug() {
129 let err = MojenticError::ToolError("test".to_string());
130 let debug_str = format!("{:?}", err);
131 assert!(debug_str.contains("ToolError"));
132 }
133
134 #[test]
135 fn test_result_type() {
136 let ok_result: Result<i32> = Ok(42);
137 assert!(ok_result.is_ok());
138 if let Ok(value) = ok_result {
139 assert_eq!(value, 42);
140 }
141
142 let err_result: Result<i32> = Err(MojenticError::ToolError("test".to_string()));
143 assert!(err_result.is_err());
144 }
145}