Skip to main content

adk_realtime/
error.rs

1//! Error types for the realtime module.
2
3use thiserror::Error;
4
5/// Result type for realtime operations.
6pub type Result<T> = std::result::Result<T, RealtimeError>;
7
8/// Errors that can occur during realtime operations.
9#[derive(Error, Debug)]
10pub enum RealtimeError {
11    /// WebSocket connection error.
12    #[error("WebSocket connection error: {0}")]
13    ConnectionError(String),
14
15    /// WebSocket message error.
16    #[error("WebSocket message error: {0}")]
17    MessageError(String),
18
19    /// Authentication error.
20    #[error("Authentication error: {0}")]
21    AuthError(String),
22
23    /// Session not connected.
24    #[error("Session not connected")]
25    NotConnected,
26
27    /// Session already closed.
28    #[error("Session already closed")]
29    SessionClosed,
30
31    /// Invalid configuration.
32    #[error("Invalid configuration: {0}")]
33    ConfigError(String),
34
35    /// Audio format error.
36    #[error("Audio format error: {0}")]
37    AudioFormatError(String),
38
39    /// Tool execution error.
40    #[error("Tool execution error: {0}")]
41    ToolError(String),
42
43    /// Server returned an error.
44    #[error("Server error: {code} - {message}")]
45    ServerError {
46        /// Error code from the server.
47        code: String,
48        /// Error message from the server.
49        message: String,
50    },
51
52    /// Timeout waiting for response.
53    #[error("Timeout: {0}")]
54    Timeout(String),
55
56    /// Serialization/deserialization error.
57    #[error("Serialization error: {0}")]
58    SerializationError(#[from] serde_json::Error),
59
60    /// Provider-specific error.
61    #[error("Provider error: {0}")]
62    ProviderError(String),
63
64    /// Generic IO error.
65    #[error("IO error: {0}")]
66    IoError(#[from] std::io::Error),
67
68    /// Opus codec error.
69    #[error("Opus codec error: {0}")]
70    OpusCodecError(String),
71
72    /// WebRTC error.
73    #[error("WebRTC error: {0}")]
74    WebRTCError(String),
75
76    /// LiveKit bridge error (legacy string format).
77    #[error("LiveKit error: {0}")]
78    LiveKitError(String),
79
80    /// Native LiveKit component error.
81    #[cfg(feature = "livekit")]
82    #[error(transparent)]
83    LiveKitNativeError(Box<crate::livekit::LiveKitError>),
84}
85
86#[cfg(feature = "livekit")]
87/// Manually implemented to box the inner error, keeping `Result` small on the happy path.
88impl 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    /// Create a new connection error.
96    pub fn connection<S: Into<String>>(msg: S) -> Self {
97        Self::ConnectionError(msg.into())
98    }
99
100    /// Create a new server error.
101    pub fn server<S: Into<String>>(code: S, message: S) -> Self {
102        Self::ServerError { code: code.into(), message: message.into() }
103    }
104
105    /// Create a new provider error.
106    pub fn provider<S: Into<String>>(msg: S) -> Self {
107        Self::ProviderError(msg.into())
108    }
109
110    /// Create a new configuration error.
111    pub fn config<S: Into<String>>(msg: S) -> Self {
112        Self::ConfigError(msg.into())
113    }
114
115    /// Create a new protocol error.
116    pub fn protocol<S: Into<String>>(msg: S) -> Self {
117        Self::MessageError(msg.into())
118    }
119
120    /// Create a new audio format error.
121    pub fn audio<S: Into<String>>(msg: S) -> Self {
122        Self::AudioFormatError(msg.into())
123    }
124
125    /// Create a new Opus codec error.
126    pub fn opus(msg: impl Into<String>) -> Self {
127        Self::OpusCodecError(msg.into())
128    }
129
130    /// Create a new WebRTC error.
131    pub fn webrtc(msg: impl Into<String>) -> Self {
132        Self::WebRTCError(msg.into())
133    }
134
135    /// Create a new LiveKit error.
136    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        // Construct a simple LiveKitError variant
148        let inner = crate::livekit::LiveKitError::ConfigError("test config error".to_string());
149
150        // Convert into RealtimeError
151        let realtime_err: crate::error::RealtimeError = inner.into();
152
153        // Verify it matches the Boxed variant and formats correctly
154        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}