Skip to main content

bamboo_infrastructure/llm/protocol/
errors.rs

1//! Error types for protocol conversion.
2
3use thiserror::Error;
4
5#[derive(Error, Debug)]
6pub enum ProtocolError {
7    #[error("Serialization error: {0}")]
8    Serialization(#[from] serde_json::Error),
9
10    #[error("Invalid role: {0}")]
11    InvalidRole(String),
12
13    #[error("Invalid content format: {0}")]
14    InvalidContent(String),
15
16    #[error("Missing required field: {0}")]
17    MissingField(String),
18
19    #[error("Unsupported feature '{feature}' for protocol '{protocol}'")]
20    UnsupportedFeature { feature: String, protocol: String },
21
22    #[error("Invalid tool call: {0}")]
23    InvalidToolCall(String),
24
25    #[error("Invalid stream chunk: {0}")]
26    InvalidStreamChunk(String),
27
28    #[error("Protocol conversion error: {0}")]
29    Conversion(String),
30}
31
32pub type ProtocolResult<T> = Result<T, ProtocolError>;
33
34#[cfg(test)]
35mod tests {
36    use super::*;
37
38    #[test]
39    fn test_protocol_error_serialization() {
40        let err = ProtocolError::InvalidRole("test".to_string());
41        let msg = err.to_string();
42        assert!(msg.contains("Invalid role"));
43        assert!(msg.contains("test"));
44    }
45
46    #[test]
47    fn test_protocol_error_invalid_content() {
48        let err = ProtocolError::InvalidContent("bad format".to_string());
49        let msg = err.to_string();
50        assert!(msg.contains("Invalid content format"));
51    }
52
53    #[test]
54    fn test_protocol_error_missing_field() {
55        let err = ProtocolError::MissingField("id".to_string());
56        let msg = err.to_string();
57        assert!(msg.contains("Missing required field"));
58        assert!(msg.contains("id"));
59    }
60
61    #[test]
62    fn test_protocol_error_unsupported_feature() {
63        let err = ProtocolError::UnsupportedFeature {
64            feature: "vision".to_string(),
65            protocol: "gemini".to_string(),
66        };
67        let msg = err.to_string();
68        assert!(msg.contains("Unsupported feature"));
69        assert!(msg.contains("vision"));
70        assert!(msg.contains("gemini"));
71    }
72
73    #[test]
74    fn test_protocol_error_invalid_tool_call() {
75        let err = ProtocolError::InvalidToolCall("missing name".to_string());
76        let msg = err.to_string();
77        assert!(msg.contains("Invalid tool call"));
78    }
79
80    #[test]
81    fn test_protocol_error_invalid_stream_chunk() {
82        let err = ProtocolError::InvalidStreamChunk("empty content".to_string());
83        let msg = err.to_string();
84        assert!(msg.contains("Invalid stream chunk"));
85    }
86
87    #[test]
88    fn test_protocol_error_conversion() {
89        let err = ProtocolError::Conversion("failed to convert".to_string());
90        let msg = err.to_string();
91        assert!(msg.contains("Protocol conversion error"));
92    }
93
94    #[test]
95    fn test_protocol_error_debug() {
96        let err = ProtocolError::InvalidRole("test".to_string());
97        let debug_str = format!("{:?}", err);
98        assert!(debug_str.contains("InvalidRole"));
99    }
100
101    #[test]
102    fn test_protocol_result_ok() {
103        let result: ProtocolResult<String> = Ok("success".to_string());
104        assert!(result.is_ok());
105    }
106
107    #[test]
108    fn test_protocol_result_err() {
109        let result: ProtocolResult<String> = Err(ProtocolError::MissingField("test".to_string()));
110        assert!(result.is_err());
111    }
112
113    #[test]
114    fn test_protocol_error_from_serde_json() {
115        let json_err = serde_json::from_str::<i32>("invalid");
116        assert!(json_err.is_err());
117        let protocol_err: ProtocolError = json_err.unwrap_err().into();
118        assert!(matches!(protocol_err, ProtocolError::Serialization(_)));
119    }
120}