1use thiserror::Error;
4
5#[derive(Debug, Error)]
7pub enum ZoeyError {
8 #[error("Database error: {0}")]
10 DatabaseSqlx(#[from] sqlx::Error),
11
12 #[error("Database error: {0}")]
14 Database(String),
15
16 #[error("Plugin error: {0}")]
18 Plugin(String),
19
20 #[error("Runtime error: {0}")]
22 Runtime(String),
23
24 #[error("Model error: {0}")]
26 Model(String),
27
28 #[error("Memory error: {0}")]
30 Memory(String),
31
32 #[error("Serialization error: {0}")]
34 Serialization(#[from] serde_json::Error),
35
36 #[error("IO error: {0}")]
38 Io(#[from] std::io::Error),
39
40 #[error("Configuration error: {0}")]
42 Config(String),
43
44 #[error("Validation error: {0}")]
46 Validation(String),
47
48 #[error("Network error: {0}")]
50 Network(#[from] reqwest::Error),
51
52 #[error("Template error: {0}")]
54 Template(String),
55
56 #[error("Service error: {0}")]
58 Service(String),
59
60 #[error("Event error: {0}")]
62 Event(String),
63
64 #[error("Action error: {0}")]
66 Action(String),
67
68 #[error("Provider error: {0}")]
70 Provider(String),
71
72 #[error("Evaluator error: {0}")]
74 Evaluator(String),
75
76 #[error("Not found: {0}")]
78 NotFound(String),
79
80 #[error("Auth error: {0}")]
82 Auth(String),
83
84 #[error("Rate limit exceeded: {0}")]
86 RateLimit(String),
87
88 #[error("Timeout: {0}")]
90 Timeout(String),
91
92 #[error("{0}")]
94 Other(String),
95
96 #[error(
98 "Database constraint violation in table '{table}': {constraint} = '{value}'. {suggestion}"
99 )]
100 DatabaseConstraintViolation {
101 table: String,
103 constraint: String,
105 value: String,
107 suggestion: String,
109 },
110
111 #[error(
113 "Vector search error: {message}. Dimension: {dimension}, Expected: {expected_dimension}"
114 )]
115 VectorSearch {
116 message: String,
118 dimension: usize,
120 expected_dimension: usize,
122 },
123
124 #[error("Missing required field '{field}' in {context}. {suggestion}")]
126 MissingField {
127 field: String,
129 context: String,
131 suggestion: String,
133 },
134
135 #[error("Resource '{resource}' exhausted: {message}. Current: {current}, Limit: {limit}")]
137 ResourceExhausted {
138 resource: String,
140 message: String,
142 current: usize,
144 limit: usize,
146 },
147}
148
149pub type Result<T> = std::result::Result<T, ZoeyError>;
151
152impl ZoeyError {
153 pub fn database(msg: impl Into<String>) -> Self {
155 ZoeyError::Database(msg.into())
156 }
157
158 pub fn plugin(msg: impl Into<String>) -> Self {
160 ZoeyError::Plugin(msg.into())
161 }
162
163 pub fn runtime(msg: impl Into<String>) -> Self {
165 ZoeyError::Runtime(msg.into())
166 }
167
168 pub fn model(msg: impl Into<String>) -> Self {
170 ZoeyError::Model(msg.into())
171 }
172
173 pub fn memory(msg: impl Into<String>) -> Self {
175 ZoeyError::Memory(msg.into())
176 }
177
178 pub fn config(msg: impl Into<String>) -> Self {
180 ZoeyError::Config(msg.into())
181 }
182
183 pub fn validation(msg: impl Into<String>) -> Self {
185 ZoeyError::Validation(msg.into())
186 }
187
188 pub fn service(msg: impl Into<String>) -> Self {
190 ZoeyError::Service(msg.into())
191 }
192
193 pub fn event(msg: impl Into<String>) -> Self {
195 ZoeyError::Event(msg.into())
196 }
197
198 pub fn action(msg: impl Into<String>) -> Self {
200 ZoeyError::Action(msg.into())
201 }
202
203 pub fn provider(msg: impl Into<String>) -> Self {
205 ZoeyError::Provider(msg.into())
206 }
207
208 pub fn evaluator(msg: impl Into<String>) -> Self {
210 ZoeyError::Evaluator(msg.into())
211 }
212
213 pub fn not_found(msg: impl Into<String>) -> Self {
215 ZoeyError::NotFound(msg.into())
216 }
217
218 pub fn auth(msg: impl Into<String>) -> Self {
220 ZoeyError::Auth(msg.into())
221 }
222
223 pub fn rate_limit(msg: impl Into<String>) -> Self {
225 ZoeyError::RateLimit(msg.into())
226 }
227
228 pub fn timeout(msg: impl Into<String>) -> Self {
230 ZoeyError::Timeout(msg.into())
231 }
232
233 pub fn other(msg: impl Into<String>) -> Self {
235 ZoeyError::Other(msg.into())
236 }
237
238 pub fn template(msg: impl Into<String>) -> Self {
240 ZoeyError::Template(msg.into())
241 }
242
243 pub fn constraint_violation(
245 table: impl Into<String>,
246 constraint: impl Into<String>,
247 value: impl Into<String>,
248 suggestion: impl Into<String>,
249 ) -> Self {
250 ZoeyError::DatabaseConstraintViolation {
251 table: table.into(),
252 constraint: constraint.into(),
253 value: value.into(),
254 suggestion: suggestion.into(),
255 }
256 }
257
258 pub fn vector_search(
260 message: impl Into<String>,
261 dimension: usize,
262 expected_dimension: usize,
263 ) -> Self {
264 ZoeyError::VectorSearch {
265 message: message.into(),
266 dimension,
267 expected_dimension,
268 }
269 }
270
271 pub fn missing_field(
273 field: impl Into<String>,
274 context: impl Into<String>,
275 suggestion: impl Into<String>,
276 ) -> Self {
277 ZoeyError::MissingField {
278 field: field.into(),
279 context: context.into(),
280 suggestion: suggestion.into(),
281 }
282 }
283
284 pub fn resource_exhausted(
286 resource: impl Into<String>,
287 message: impl Into<String>,
288 current: usize,
289 limit: usize,
290 ) -> Self {
291 ZoeyError::ResourceExhausted {
292 resource: resource.into(),
293 message: message.into(),
294 current,
295 limit,
296 }
297 }
298}
299
300#[cfg(test)]
301mod tests {
302 use super::*;
303
304 #[test]
305 fn test_error_creation() {
306 let err = ZoeyError::plugin("test plugin error");
307 assert_eq!(err.to_string(), "Plugin error: test plugin error");
308
309 let err = ZoeyError::runtime("test runtime error");
310 assert_eq!(err.to_string(), "Runtime error: test runtime error");
311 }
312
313 #[test]
314 fn test_result_type() {
315 fn returns_result() -> Result<i32> {
316 Ok(42)
317 }
318
319 assert_eq!(returns_result().unwrap(), 42);
320 }
321}