1use thiserror::Error;
4
5#[derive(Debug, Error)]
7pub enum LellmError {
8 #[error("LLM error: {0}")]
9 Llm(#[from] LlmError),
10 #[error("Tool error: {0}")]
11 Tool(#[from] ToolError),
12 #[error("Memory error: {0}")]
13 Memory(#[from] MemoryError),
14 #[error("Parse error: {0}")]
15 Parse(#[from] ParseError),
16}
17
18#[derive(Debug, Error)]
20pub enum LlmError {
21 #[error("api error: {provider} {status}")]
22 ApiError {
23 provider: String,
24 status: u16,
25 code: Option<String>,
26 message: String,
27 },
28
29 #[error("request timeout")]
30 Timeout,
31
32 #[error("response parse error")]
33 ParseError { detail: String },
34
35 #[error("network error")]
36 Network { detail: String },
37
38 #[error("model not found: {model}")]
39 ModelNotFound { model: String },
40
41 #[error("{message}")]
42 Other { message: String },
43}
44
45#[derive(Debug, Error)]
47pub enum ToolError {
48 #[error("tool not found: {0}")]
49 NotFound(String),
50
51 #[error("tool execution failed: {0}")]
52 ExecutionFailed(String),
53
54 #[error("tool execution timed out")]
55 Timeout,
56
57 #[error("tool call loop detected")]
58 LoopDetected,
59}
60
61#[derive(Debug, Error)]
63pub enum MemoryError {
64 #[error("memory IO error: {0}")]
65 IoError(String),
66
67 #[error("memory database error: {0}")]
68 DatabaseError(String),
69}
70
71#[derive(Debug, Error)]
73#[error("parse error: {detail}")]
74pub struct ParseError {
75 pub detail: String,
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn test_llm_error_display() {
84 let err = LlmError::Timeout;
85 assert_eq!(format!("{}", err), "request timeout");
86 }
87
88 #[test]
89 fn test_llm_error_api_error_display() {
90 let err = LlmError::ApiError {
91 provider: "openai".into(),
92 status: 429,
93 code: Some("rate_limit".into()),
94 message: "Too many requests".into(),
95 };
96 assert!(format!("{}", err).contains("openai"));
97 assert!(format!("{}", err).contains("429"));
98 }
99
100 #[test]
101 fn test_tool_error_display() {
102 let err = ToolError::NotFound("read_file".into());
103 assert_eq!(format!("{}", err), "tool not found: read_file");
104 }
105
106 #[test]
107 fn test_lellm_error_from_llm_error() {
108 let llm_err = LlmError::Timeout;
109 let top_err: LellmError = llm_err.into();
110 assert!(format!("{}", top_err).contains("LLM error"));
111 }
112}