1use thiserror::Error;
4
5#[derive(Error, Debug)]
7pub enum ClientError {
8 #[error("A2A protocol error: {0}")]
10 A2AError(#[from] a2a_rs::A2AError),
11
12 #[error(
14 "WebSocket client not configured. Actionable Suggestion: Ensure that a WebSocket interface is defined in preferred_transport or additional_interfaces on the agent card, or manually configure a WebSocket URL using WebA2AClientBuilder::ws_url."
15 )]
16 WebSocketNotConfigured,
17
18 #[error(
20 "Failed to auto-detect available transports: {0}. Actionable Suggestion: Make sure the agent server is running, the host is reachable, and the `/agent-card` endpoint is accessible."
21 )]
22 AutoDetectionFailed(String),
23
24 #[error(
26 "Invalid configuration: {0}. Actionable Suggestion: Verify that builder configuration parameters, such as base URLs, are correctly specified."
27 )]
28 InvalidConfiguration(String),
29
30 #[error(
32 "Invalid URL format: '{url}'. Reason: {reason}. Actionable Suggestion: Double check that the URL scheme and address are valid and formatted correctly."
33 )]
34 InvalidUrl { url: String, reason: String },
35
36 #[error(
38 "Data serialization error: {0}. Actionable Suggestion: Check that payloads adhere to the expected format and structure."
39 )]
40 SerializationError(String),
41}
42
43pub type Result<T> = std::result::Result<T, ClientError>;
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49
50 #[test]
51 fn test_client_error_formatting() {
52 let err = ClientError::WebSocketNotConfigured;
53 let msg = err.to_string();
54 assert!(msg.contains("WebSocket client not configured."));
55 assert!(msg.contains("Actionable Suggestion:"));
56
57 let err = ClientError::AutoDetectionFailed("No matching transport".to_string());
58 let msg = err.to_string();
59 assert!(msg.contains("No matching transport"));
60 assert!(msg.contains("Failed to auto-detect"));
61 assert!(msg.contains("Actionable Suggestion:"));
62
63 let err = ClientError::InvalidConfiguration("Missing field".to_string());
64 let msg = err.to_string();
65 assert!(msg.contains("Missing field"));
66 assert!(msg.contains("Actionable Suggestion:"));
67
68 let err = ClientError::InvalidUrl {
69 url: "http://invalid".to_string(),
70 reason: "Bad format".to_string(),
71 };
72 let msg = err.to_string();
73 assert!(msg.contains("http://invalid"));
74 assert!(msg.contains("Bad format"));
75 assert!(msg.contains("Actionable Suggestion:"));
76
77 let err = ClientError::SerializationError("JSON error".to_string());
78 let msg = err.to_string();
79 assert!(msg.contains("JSON error"));
80 assert!(msg.contains("Actionable Suggestion:"));
81 }
82}