1use thiserror::Error;
4
5pub type Result<T> = std::result::Result<T, RealtimeError>;
7
8#[derive(Error, Debug)]
10pub enum RealtimeError {
11 #[error("WebSocket connection error: {0}")]
13 ConnectionError(String),
14
15 #[error("WebSocket message error: {0}")]
17 MessageError(String),
18
19 #[error("Authentication error: {0}")]
21 AuthError(String),
22
23 #[error("Session not connected")]
25 NotConnected,
26
27 #[error("Session already closed")]
29 SessionClosed,
30
31 #[error("Invalid configuration: {0}")]
33 ConfigError(String),
34
35 #[error("Audio format error: {0}")]
37 AudioFormatError(String),
38
39 #[error("Tool execution error: {0}")]
41 ToolError(String),
42
43 #[error("Server error: {code} - {message}")]
45 ServerError {
46 code: String,
48 message: String,
50 },
51
52 #[error("Timeout: {0}")]
54 Timeout(String),
55
56 #[error("Serialization error: {0}")]
58 SerializationError(#[from] serde_json::Error),
59
60 #[error("Provider error: {0}")]
62 ProviderError(String),
63
64 #[error("IO error: {0}")]
66 IoError(#[from] std::io::Error),
67
68 #[error("Opus codec error: {0}")]
70 OpusCodecError(String),
71
72 #[error("WebRTC error: {0}")]
74 WebRTCError(String),
75
76 #[error("LiveKit error: {0}")]
78 LiveKitError(String),
79
80 #[cfg(feature = "livekit")]
82 #[error(transparent)]
83 LiveKitNativeError(Box<crate::livekit::LiveKitError>),
84}
85
86#[cfg(feature = "livekit")]
87impl From<crate::livekit::LiveKitError> for RealtimeError {
89 fn from(err: crate::livekit::LiveKitError) -> Self {
90 RealtimeError::LiveKitNativeError(Box::new(err))
91 }
92}
93
94impl RealtimeError {
95 pub fn connection<S: Into<String>>(msg: S) -> Self {
97 Self::ConnectionError(msg.into())
98 }
99
100 pub fn server<S: Into<String>>(code: S, message: S) -> Self {
102 Self::ServerError { code: code.into(), message: message.into() }
103 }
104
105 pub fn provider<S: Into<String>>(msg: S) -> Self {
107 Self::ProviderError(msg.into())
108 }
109
110 pub fn config<S: Into<String>>(msg: S) -> Self {
112 Self::ConfigError(msg.into())
113 }
114
115 pub fn protocol<S: Into<String>>(msg: S) -> Self {
117 Self::MessageError(msg.into())
118 }
119
120 pub fn audio<S: Into<String>>(msg: S) -> Self {
122 Self::AudioFormatError(msg.into())
123 }
124
125 pub fn opus(msg: impl Into<String>) -> Self {
127 Self::OpusCodecError(msg.into())
128 }
129
130 pub fn webrtc(msg: impl Into<String>) -> Self {
132 Self::WebRTCError(msg.into())
133 }
134
135 pub fn livekit(msg: impl Into<String>) -> Self {
137 Self::LiveKitError(msg.into())
138 }
139}
140
141#[cfg(test)]
142mod tests {
143
144 #[cfg(feature = "livekit")]
145 #[test]
146 fn test_livekit_native_error_conversion() {
147 let inner = crate::livekit::LiveKitError::ConfigError("test config error".to_string());
149
150 let realtime_err: crate::error::RealtimeError = inner.into();
152
153 match realtime_err {
155 crate::error::RealtimeError::LiveKitNativeError(boxed_err) => {
156 assert!(matches!(*boxed_err, crate::livekit::LiveKitError::ConfigError(_)));
157 assert_eq!(
158 format!("{}", boxed_err),
159 "LiveKit configuration error: test config error"
160 );
161 }
162 _ => panic!("Expected LiveKitNativeError variant"),
163 }
164 }
165}