1use thiserror::Error;
4
5pub type Result<T> = std::result::Result<T, ChatError>;
7
8#[derive(Debug, Error)]
10pub enum ChatError {
11 #[error("RAG retrieval failed: {0}")]
13 RagRetrievalError(String),
14
15 #[error("LLM generation failed: {0}")]
17 LlmGenerationError(String),
18
19 #[error("SPARQL generation failed: {0}")]
21 SparqlGenerationError(String),
22
23 #[error("SPARQL execution failed: {0}")]
25 SparqlExecutionError(String),
26
27 #[error("Session not found: {0}")]
29 SessionNotFound(String),
30
31 #[error("Session error: {0}")]
33 SessionError(String),
34
35 #[error("Configuration error: {0}")]
37 ConfigError(String),
38
39 #[error("Storage error: {0}")]
41 StorageError(String),
42
43 #[error("Network error: {0}")]
45 NetworkError(String),
46
47 #[error("Operation timed out: {0}")]
49 TimeoutError(String),
50
51 #[error("Validation error: {0}")]
53 ValidationError(String),
54
55 #[error("Serialization error: {0}")]
57 SerializationError(String),
58
59 #[error("Deserialization error: {0}")]
61 DeserializationError(String),
62
63 #[error("Internal error: {0}")]
65 InternalError(String),
66
67 #[error("Quantum processing error: {0}")]
69 QuantumProcessingError(String),
70
71 #[error("Consciousness processing error: {0}")]
73 ConsciousnessProcessingError(String),
74
75 #[error("Reasoning error: {0}")]
77 ReasoningError(String),
78
79 #[error("Schema introspection error: {0}")]
81 SchemaIntrospectionError(String),
82
83 #[error(transparent)]
85 Other(#[from] anyhow::Error),
86
87 #[error(transparent)]
89 JsonError(#[from] serde_json::Error),
90
91 #[error(transparent)]
93 IoError(#[from] std::io::Error),
94
95 #[error("OxiRS core error: {0}")]
97 CoreError(String),
98}
99
100impl From<String> for ChatError {
101 fn from(err: String) -> Self {
102 ChatError::CoreError(err)
103 }
104}
105
106impl ChatError {
107 pub fn is_recoverable(&self) -> bool {
109 matches!(
110 self,
111 ChatError::NetworkError(_)
112 | ChatError::TimeoutError(_)
113 | ChatError::LlmGenerationError(_)
114 )
115 }
116
117 pub fn category(&self) -> ErrorCategory {
119 match self {
120 ChatError::RagRetrievalError(_) => ErrorCategory::Retrieval,
121 ChatError::LlmGenerationError(_) => ErrorCategory::Generation,
122 ChatError::SparqlGenerationError(_) | ChatError::SparqlExecutionError(_) => {
123 ErrorCategory::Query
124 }
125 ChatError::SessionNotFound(_) | ChatError::SessionError(_) => ErrorCategory::Session,
126 ChatError::NetworkError(_) | ChatError::TimeoutError(_) => ErrorCategory::Network,
127 ChatError::ValidationError(_) => ErrorCategory::Validation,
128 _ => ErrorCategory::Internal,
129 }
130 }
131}
132
133#[derive(Debug, Clone, Copy, PartialEq, Eq)]
135pub enum ErrorCategory {
136 Retrieval,
137 Generation,
138 Query,
139 Session,
140 Network,
141 Validation,
142 Internal,
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148
149 #[test]
150 fn test_error_display() {
151 let error = ChatError::SessionNotFound("test-session".to_string());
152 assert_eq!(error.to_string(), "Session not found: test-session");
153 }
154
155 #[test]
156 fn test_error_recoverability() {
157 let recoverable = ChatError::TimeoutError("timeout".to_string());
158 assert!(recoverable.is_recoverable());
159
160 let not_recoverable = ChatError::ValidationError("invalid".to_string());
161 assert!(!not_recoverable.is_recoverable());
162 }
163
164 #[test]
165 fn test_error_category() {
166 let error = ChatError::LlmGenerationError("failed".to_string());
167 assert_eq!(error.category(), ErrorCategory::Generation);
168 }
169}