1use super::push_notification::{
9 DeleteTaskPushNotificationConfigRequest, GetTaskPushNotificationConfigRequest,
10 ListTaskPushNotificationConfigRequest, PushNotificationConfig,
11 SetTaskPushNotificationConfigRequest, TaskResubscriptionRequest,
12};
13use crate::models::a2a::jsonrpc::{JsonRpcResponse, RequestId};
14use crate::models::a2a::{AgentCard, Task, TaskState};
15use serde::{Deserialize, Serialize};
16use systemprompt_identifiers::TaskId;
17use systemprompt_models::a2a::methods;
18
19#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
20pub struct MessageSendParams {
21 pub message: crate::models::a2a::Message,
22 pub configuration: Option<MessageSendConfiguration>,
23 pub metadata: Option<serde_json::Map<String, serde_json::Value>>,
24}
25
26#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
27#[serde(rename_all = "camelCase")]
28pub struct MessageSendConfiguration {
29 pub accepted_output_modes: Option<Vec<String>>,
30 pub history_length: Option<u32>,
31 pub push_notification_config: Option<PushNotificationConfig>,
32 pub blocking: Option<bool>,
33}
34
35#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
36pub struct TaskQueryParams {
37 pub id: TaskId,
38 pub history_length: Option<u32>,
39}
40
41#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
42pub struct TaskIdParams {
43 pub id: TaskId,
44}
45
46#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
47pub struct A2aRequest {
48 pub method: String,
49 pub params: serde_json::Value,
50}
51
52#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
53#[serde(untagged)]
54pub enum A2aResponse {
55 SendMessage(SendMessageResponse),
56 GetTask(GetTaskResponse),
57 CancelTask(CancelTaskResponse),
58 GetAuthenticatedExtendedCard(GetAuthenticatedExtendedCardResponse),
59 SendStreamingMessage(SendStreamingMessageResponse),
60}
61
62pub type SendMessageResponse = JsonRpcResponse<Task>;
63pub type GetTaskResponse = JsonRpcResponse<Task>;
64pub type CancelTaskResponse = JsonRpcResponse<Task>;
65pub type GetAuthenticatedExtendedCardResponse = JsonRpcResponse<AgentCard>;
66pub type SendStreamingMessageResponse = JsonRpcResponse<Task>;
67
68#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
69pub struct A2aJsonRpcRequest {
70 pub jsonrpc: String,
71 pub method: String,
72 pub params: serde_json::Value,
73 pub id: RequestId,
74}
75
76impl A2aJsonRpcRequest {
77 pub fn parse_request(&self) -> Result<A2aRequestParams, A2aParseError> {
78 match self.method.as_str() {
79 methods::SEND_MESSAGE => {
80 let params: MessageSendParams = serde_json::from_value(self.params.clone())
81 .map_err(|e| A2aParseError::InvalidParams {
82 method: self.method.clone(),
83 error: e.to_string(),
84 })?;
85 Ok(A2aRequestParams::SendMessage(params))
86 },
87 methods::GET_TASK => {
88 let params: TaskQueryParams =
89 serde_json::from_value(self.params.clone()).map_err(|e| {
90 A2aParseError::InvalidParams {
91 method: self.method.clone(),
92 error: e.to_string(),
93 }
94 })?;
95 Ok(A2aRequestParams::GetTask(params))
96 },
97 methods::CANCEL_TASK => {
98 let params: TaskIdParams =
99 serde_json::from_value(self.params.clone()).map_err(|e| {
100 A2aParseError::InvalidParams {
101 method: self.method.clone(),
102 error: e.to_string(),
103 }
104 })?;
105 Ok(A2aRequestParams::CancelTask(params))
106 },
107 methods::GET_EXTENDED_AGENT_CARD => {
108 let params: serde_json::Value = serde_json::from_value(self.params.clone())
109 .map_err(|e| A2aParseError::InvalidParams {
110 method: self.method.clone(),
111 error: e.to_string(),
112 })?;
113 Ok(A2aRequestParams::GetAuthenticatedExtendedCard(params))
114 },
115 methods::SEND_STREAMING_MESSAGE => {
116 let params: MessageSendParams = serde_json::from_value(self.params.clone())
117 .map_err(|e| A2aParseError::InvalidParams {
118 method: self.method.clone(),
119 error: e.to_string(),
120 })?;
121 Ok(A2aRequestParams::SendStreamingMessage(params))
122 },
123 methods::SUBSCRIBE_TO_TASK => {
124 let params: TaskResubscriptionRequest = serde_json::from_value(self.params.clone())
125 .map_err(|e| A2aParseError::InvalidParams {
126 method: self.method.clone(),
127 error: e.to_string(),
128 })?;
129 Ok(A2aRequestParams::TaskResubscription(params))
130 },
131 methods::CREATE_TASK_PUSH_NOTIFICATION_CONFIG => {
132 let params: SetTaskPushNotificationConfigRequest =
133 serde_json::from_value(self.params.clone()).map_err(|e| {
134 A2aParseError::InvalidParams {
135 method: self.method.clone(),
136 error: e.to_string(),
137 }
138 })?;
139 Ok(A2aRequestParams::SetTaskPushNotificationConfig(params))
140 },
141 methods::GET_TASK_PUSH_NOTIFICATION_CONFIG => {
142 let params: GetTaskPushNotificationConfigRequest =
143 serde_json::from_value(self.params.clone()).map_err(|e| {
144 A2aParseError::InvalidParams {
145 method: self.method.clone(),
146 error: e.to_string(),
147 }
148 })?;
149 Ok(A2aRequestParams::GetTaskPushNotificationConfig(params))
150 },
151 methods::LIST_TASK_PUSH_NOTIFICATION_CONFIGS => {
152 let params: ListTaskPushNotificationConfigRequest =
153 serde_json::from_value(self.params.clone()).map_err(|e| {
154 A2aParseError::InvalidParams {
155 method: self.method.clone(),
156 error: e.to_string(),
157 }
158 })?;
159 Ok(A2aRequestParams::ListTaskPushNotificationConfig(params))
160 },
161 methods::DELETE_TASK_PUSH_NOTIFICATION_CONFIG => {
162 let params: DeleteTaskPushNotificationConfigRequest =
163 serde_json::from_value(self.params.clone()).map_err(|e| {
164 A2aParseError::InvalidParams {
165 method: self.method.clone(),
166 error: e.to_string(),
167 }
168 })?;
169 Ok(A2aRequestParams::DeleteTaskPushNotificationConfig(params))
170 },
171 _ => Err(A2aParseError::UnsupportedMethod {
172 method: self.method.clone(),
173 }),
174 }
175 }
176}
177
178#[derive(Debug, Clone, PartialEq)]
179pub enum A2aRequestParams {
180 SendMessage(MessageSendParams),
181 GetTask(TaskQueryParams),
182 CancelTask(TaskIdParams),
183 GetAuthenticatedExtendedCard(serde_json::Value),
184 SendStreamingMessage(MessageSendParams),
185 TaskResubscription(TaskResubscriptionRequest),
186 SetTaskPushNotificationConfig(SetTaskPushNotificationConfigRequest),
187 GetTaskPushNotificationConfig(GetTaskPushNotificationConfigRequest),
188 ListTaskPushNotificationConfig(ListTaskPushNotificationConfigRequest),
189 DeleteTaskPushNotificationConfig(DeleteTaskPushNotificationConfigRequest),
190}
191
192#[derive(Debug, thiserror::Error, Clone, PartialEq, Eq)]
193pub enum A2aParseError {
194 #[error("Unsupported method: {method}")]
195 UnsupportedMethod { method: String },
196
197 #[error("Invalid parameters for method '{method}': {error}")]
198 InvalidParams { method: String, error: String },
199}
200
201impl A2aResponse {
202 pub fn send_message(task: Task, id: RequestId) -> Self {
203 Self::SendMessage(JsonRpcResponse {
204 jsonrpc: "2.0".to_owned(),
205 id,
206 result: Some(task),
207 error: None,
208 })
209 }
210
211 pub fn get_task(task: Task, id: RequestId) -> Self {
212 Self::GetTask(JsonRpcResponse {
213 jsonrpc: "2.0".to_owned(),
214 id,
215 result: Some(task),
216 error: None,
217 })
218 }
219
220 pub fn cancel_task(task: Task, id: RequestId) -> Self {
221 Self::CancelTask(JsonRpcResponse {
222 jsonrpc: "2.0".to_owned(),
223 id,
224 result: Some(task),
225 error: None,
226 })
227 }
228}
229
230#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
231pub struct TaskNotFoundError {
232 pub task_id: TaskId,
233 pub message: String,
234 pub code: i32,
235 pub data: serde_json::Value,
236}
237
238#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
239pub struct TaskNotCancelableError {
240 pub task_id: TaskId,
241 pub state: TaskState,
242 pub message: String,
243 pub code: i32,
244 pub data: serde_json::Value,
245}
246
247#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
248pub struct UnsupportedOperationError {
249 pub operation: String,
250 pub message: String,
251 pub code: i32,
252 pub data: serde_json::Value,
253}