headless_lms_chatbot/
chatbot_error.rs1use std::fmt::Display;
6
7use backtrace::Backtrace;
8use headless_lms_models::ModelError;
9use tracing_error::SpanTrace;
10
11use headless_lms_utils::error::backend_error::BackendError;
12
13pub type ChatbotResult<T> = Result<T, ChatbotError>;
17
18#[derive(Debug)]
20pub enum ChatbotErrorType {
21 InvalidMessageShape,
22 InvalidToolName,
23 InvalidToolArguments,
24 ChatbotModelError,
25 ChatbotMessageSuggestError,
26 UrlParse,
27 TokioIo,
28 SerdeJson,
29 Other,
30 DeserializationError,
31}
32
33#[derive(Debug)]
85pub struct ChatbotError {
86 error_type: <ChatbotError as BackendError>::ErrorType,
87 message: String,
88 source: Option<anyhow::Error>,
90 span_trace: Box<SpanTrace>,
92 backtrace: Box<Backtrace>,
94}
95
96impl std::error::Error for ChatbotError {
97 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
98 self.source.as_ref().and_then(|o| o.source())
99 }
100
101 fn cause(&self) -> Option<&dyn std::error::Error> {
102 self.source()
103 }
104}
105
106impl Display for ChatbotError {
107 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108 write!(f, "ChatbotError {:?} {:?}", self.error_type, self.message)
109 }
110}
111
112impl BackendError for ChatbotError {
113 type ErrorType = ChatbotErrorType;
114
115 fn new<M: Into<String>, S: Into<Option<anyhow::Error>>>(
116 error_type: Self::ErrorType,
117 message: M,
118 source_error: S,
119 ) -> Self {
120 Self::new_with_traces(
121 error_type,
122 message,
123 source_error,
124 Backtrace::new(),
125 SpanTrace::capture(),
126 )
127 }
128
129 fn backtrace(&self) -> Option<&Backtrace> {
130 Some(&self.backtrace)
131 }
132
133 fn error_type(&self) -> &Self::ErrorType {
134 &self.error_type
135 }
136
137 fn message(&self) -> &str {
138 &self.message
139 }
140
141 fn span_trace(&self) -> &SpanTrace {
142 &self.span_trace
143 }
144
145 fn new_with_traces<M: Into<String>, S: Into<Option<anyhow::Error>>>(
146 error_type: Self::ErrorType,
147 message: M,
148 source_error: S,
149 backtrace: Backtrace,
150 span_trace: SpanTrace,
151 ) -> Self {
152 Self {
153 error_type,
154 message: message.into(),
155 source: source_error.into(),
156 span_trace: Box::new(span_trace),
157 backtrace: Box::new(backtrace),
158 }
159 }
160}
161
162impl From<url::ParseError> for ChatbotError {
163 fn from(source: url::ParseError) -> Self {
164 ChatbotError::new(
165 ChatbotErrorType::UrlParse,
166 source.to_string(),
167 Some(source.into()),
168 )
169 }
170}
171
172impl From<tokio::io::Error> for ChatbotError {
173 fn from(source: tokio::io::Error) -> Self {
174 ChatbotError::new(
175 ChatbotErrorType::TokioIo,
176 source.to_string(),
177 Some(source.into()),
178 )
179 }
180}
181
182impl From<serde_json::Error> for ChatbotError {
183 fn from(source: serde_json::Error) -> Self {
184 ChatbotError::new(
185 ChatbotErrorType::SerdeJson,
186 source.to_string(),
187 Some(source.into()),
188 )
189 }
190}
191
192impl From<anyhow::Error> for ChatbotError {
193 fn from(err: anyhow::Error) -> ChatbotError {
194 Self::new(ChatbotErrorType::Other, err.to_string(), Some(err))
195 }
196}
197
198impl From<ModelError> for ChatbotError {
199 fn from(err: ModelError) -> ChatbotError {
200 Self::new(
201 ChatbotErrorType::ChatbotModelError,
202 err.to_string(),
203 Some(err.into()),
204 )
205 }
206}