1use crate::transport::TransportError;
2use crate::types::metadata::Metadata;
3use thiserror::Error;
4
5#[derive(Clone, Debug, Error)]
6pub enum ChatError {
7 #[error("network error: {0}")]
8 Network(String),
9
10 #[error("provider error: {0}")]
11 Provider(String),
12
13 #[error("rate limited")]
14 RateLimited,
15
16 #[error("exceeded maximum steps")]
17 MaxStepsExceeded,
18
19 #[error("invalid response: {0}")]
20 InvalidResponse(String),
21
22 #[error("error in callback function: {0}")]
23 Callback(String),
24
25 #[error("unknown error: {0}")]
26 Other(String),
27}
28
29impl ChatError {
30 pub fn is_retryable(&self) -> bool {
36 matches!(self, ChatError::RateLimited | ChatError::Network(_))
37 }
38}
39
40#[derive(Clone, Debug, Error)]
41#[error("Chat engine failed: {err}")]
42pub struct ChatFailure {
43 pub metadata: Option<Metadata>,
44 #[source]
45 pub err: ChatError,
46}
47
48impl From<TransportError> for ChatError {
49 fn from(err: TransportError) -> Self {
50 match err {
51 TransportError::Connection(msg) => ChatError::Network(msg),
52 TransportError::Stream(msg) => ChatError::Network(msg),
53 TransportError::Request { status, message } => match status {
54 Some(429 | 529) => ChatError::RateLimited,
55 _ => ChatError::Provider(message),
56 },
57 }
58 }
59}
60
61impl ChatFailure {
62 pub fn from_err<E: Into<ChatError>>(err: E) -> Self {
63 Self {
64 metadata: None,
65 err: err.into(),
66 }
67 }
68}