1use serde::{Deserialize, Serialize};
4
5pub const JSON_PARSE_ERROR: i32 = -32700;
11pub const INVALID_REQUEST: i32 = -32600;
13pub const METHOD_NOT_FOUND: i32 = -32601;
15pub const INVALID_PARAMS: i32 = -32602;
17pub const INTERNAL_ERROR: i32 = -32603;
19pub const TASK_NOT_FOUND: i32 = -32001;
21pub const TASK_NOT_CANCELABLE: i32 = -32002;
23pub const PUSH_NOT_SUPPORTED: i32 = -32003;
25pub const UNSUPPORTED_OPERATION: i32 = -32004;
27pub const CONTENT_TYPE_NOT_SUPPORTED: i32 = -32005;
29pub const INVALID_AGENT_RESPONSE: i32 = -32006;
31pub const EXTENDED_CARD_NOT_CONFIGURED: i32 = -32007;
33pub const EXTENSION_SUPPORT_REQUIRED: i32 = -32008;
35pub const VERSION_NOT_SUPPORTED: i32 = -32009;
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
44pub struct A2aError {
45 pub code: i32,
47 pub message: String,
49 #[serde(skip_serializing_if = "Option::is_none")]
51 pub data: Option<serde_json::Value>,
52}
53
54impl A2aError {
55 pub fn new(code: i32, message: impl Into<String>) -> Self {
57 Self {
58 code,
59 message: message.into(),
60 data: None,
61 }
62 }
63
64 pub fn with_data(mut self, data: serde_json::Value) -> Self {
66 self.data = Some(data);
67 self
68 }
69
70 pub fn task_not_found(task_id: &str) -> Self {
72 Self::new(TASK_NOT_FOUND, format!("Task not found: {task_id}"))
73 }
74
75 pub fn task_not_cancelable(task_id: &str) -> Self {
77 Self::new(
78 TASK_NOT_CANCELABLE,
79 format!("Task cannot be canceled: {task_id}"),
80 )
81 }
82
83 pub fn push_not_supported() -> Self {
85 Self::new(PUSH_NOT_SUPPORTED, "Push notifications are not supported")
86 }
87
88 pub fn unsupported_operation(detail: &str) -> Self {
90 Self::new(
91 UNSUPPORTED_OPERATION,
92 format!("Unsupported operation: {detail}"),
93 )
94 }
95
96 pub fn content_type_not_supported(detail: &str) -> Self {
98 Self::new(
99 CONTENT_TYPE_NOT_SUPPORTED,
100 format!("Content type not supported: {detail}"),
101 )
102 }
103
104 pub fn invalid_request(detail: impl Into<String>) -> Self {
106 Self::new(INVALID_REQUEST, detail)
107 }
108
109 pub fn internal(message: impl Into<String>) -> Self {
111 Self::new(INTERNAL_ERROR, message)
112 }
113
114 pub fn method_not_found(method: &str) -> Self {
116 Self::new(METHOD_NOT_FOUND, format!("Method not found: {method}"))
117 }
118
119 pub fn invalid_params(detail: impl Into<String>) -> Self {
121 Self::new(INVALID_PARAMS, detail)
122 }
123
124 pub fn parse_error(detail: impl Into<String>) -> Self {
126 Self::new(JSON_PARSE_ERROR, detail)
127 }
128
129 pub fn extended_card_not_configured() -> Self {
131 Self::new(
132 EXTENDED_CARD_NOT_CONFIGURED,
133 "Authenticated Extended Card is not configured",
134 )
135 }
136
137 pub fn extension_support_required() -> Self {
139 Self::new(
140 EXTENSION_SUPPORT_REQUIRED,
141 "Extension support is required but not available",
142 )
143 }
144
145 pub fn version_not_supported() -> Self {
147 Self::new(
148 VERSION_NOT_SUPPORTED,
149 "Protocol version is not supported",
150 )
151 }
152}
153
154impl std::fmt::Display for A2aError {
155 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
156 write!(f, "A2A error {}: {}", self.code, self.message)
157 }
158}
159
160impl std::error::Error for A2aError {}
161
162impl From<serde_json::Error> for A2aError {
163 fn from(err: serde_json::Error) -> Self {
164 Self::parse_error(err.to_string())
165 }
166}
167
168impl From<anyhow::Error> for A2aError {
169 fn from(err: anyhow::Error) -> Self {
170 Self::internal(err.to_string())
171 }
172}