1use crate::jsonrpc::JsonRpcError;
2
3#[derive(Debug, thiserror::Error)]
4pub enum A2aError {
5 #[error("HTTP request failed: {0}")]
6 Http(#[from] reqwest::Error),
7
8 #[error("JSON serialization/deserialization failed: {0}")]
9 Json(#[from] serde_json::Error),
10
11 #[error("JSON-RPC error {code}: {message}")]
12 JsonRpc { code: i32, message: String },
13
14 #[error("agent discovery failed for {url}: {reason}")]
15 Discovery { url: String, reason: String },
16
17 #[error("SSE stream error: {0}")]
18 Stream(String),
19
20 #[error("server error: {0}")]
21 Server(String),
22
23 #[error("security policy violation: {0}")]
24 Security(String),
25}
26
27impl From<JsonRpcError> for A2aError {
28 fn from(e: JsonRpcError) -> Self {
29 Self::JsonRpc {
30 code: e.code,
31 message: e.message,
32 }
33 }
34}
35
36#[cfg(test)]
37mod tests {
38 use super::*;
39
40 #[test]
41 fn from_jsonrpc_error() {
42 let rpc_err = JsonRpcError {
43 code: -32001,
44 message: "task not found".into(),
45 data: None,
46 };
47 let err: A2aError = rpc_err.into();
48 match err {
49 A2aError::JsonRpc { code, message } => {
50 assert_eq!(code, -32001);
51 assert_eq!(message, "task not found");
52 }
53 _ => panic!("expected JsonRpc variant"),
54 }
55 }
56
57 #[test]
58 fn error_display() {
59 let err = A2aError::Discovery {
60 url: "http://example.com".into(),
61 reason: "connection refused".into(),
62 };
63 assert_eq!(
64 err.to_string(),
65 "agent discovery failed for http://example.com: connection refused"
66 );
67
68 let err = A2aError::Stream("unexpected EOF".into());
69 assert_eq!(err.to_string(), "SSE stream error: unexpected EOF");
70 }
71
72 #[test]
73 fn security_error_display() {
74 let err = A2aError::Security("TLS required but endpoint uses HTTP".into());
75 assert_eq!(
76 err.to_string(),
77 "security policy violation: TLS required but endpoint uses HTTP"
78 );
79 }
80
81 #[test]
82 fn from_serde_json_error() {
83 let json_err = serde_json::from_str::<serde_json::Value>("invalid").unwrap_err();
84 let err: A2aError = json_err.into();
85 assert!(matches!(err, A2aError::Json(_)));
86 }
87}