systemprompt_agent/models/a2a/protocol/
requests.rs1use crate::models::a2a::jsonrpc::{JsonRpcResponse, RequestId};
12use crate::models::a2a::{AgentCard, Task, TaskState};
13use serde::{Deserialize, Serialize};
14use systemprompt_identifiers::TaskId;
15use systemprompt_models::a2a::methods;
16
17#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
18pub struct MessageSendParams {
19 pub message: crate::models::a2a::Message,
20 pub configuration: Option<MessageSendConfiguration>,
21 pub metadata: Option<serde_json::Map<String, serde_json::Value>>,
22}
23
24#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
25#[serde(rename_all = "camelCase")]
26pub struct MessageSendConfiguration {
27 pub accepted_output_modes: Option<Vec<String>>,
28 pub history_length: Option<u32>,
29 pub blocking: Option<bool>,
30}
31
32#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
33pub struct TaskQueryParams {
34 pub id: TaskId,
35 pub history_length: Option<u32>,
36}
37
38#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
39pub struct TaskIdParams {
40 pub id: TaskId,
41}
42
43#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
44pub struct A2aRequest {
45 pub method: String,
46 pub params: serde_json::Value,
47}
48
49#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
50#[serde(untagged)]
51pub enum A2aResponse {
52 SendMessage(SendMessageResponse),
53 GetTask(GetTaskResponse),
54 CancelTask(CancelTaskResponse),
55 GetAuthenticatedExtendedCard(GetAuthenticatedExtendedCardResponse),
56 SendStreamingMessage(SendStreamingMessageResponse),
57}
58
59pub type SendMessageResponse = JsonRpcResponse<Task>;
60pub type GetTaskResponse = JsonRpcResponse<Task>;
61pub type CancelTaskResponse = JsonRpcResponse<Task>;
62pub type GetAuthenticatedExtendedCardResponse = JsonRpcResponse<AgentCard>;
63pub type SendStreamingMessageResponse = JsonRpcResponse<Task>;
64
65#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
66pub struct A2aJsonRpcRequest {
67 pub jsonrpc: String,
68 pub method: String,
69 pub params: serde_json::Value,
70 pub id: RequestId,
71}
72
73impl A2aJsonRpcRequest {
74 pub fn parse_request(&self) -> Result<A2aRequestParams, A2aParseError> {
75 match self.method.as_str() {
76 methods::SEND_MESSAGE => Ok(A2aRequestParams::SendMessage(self.parse_params()?)),
77 methods::GET_TASK => Ok(A2aRequestParams::GetTask(self.parse_params()?)),
78 methods::CANCEL_TASK => Ok(A2aRequestParams::CancelTask(self.parse_params()?)),
79 methods::GET_EXTENDED_AGENT_CARD => Ok(A2aRequestParams::GetAuthenticatedExtendedCard(
80 self.parse_params()?,
81 )),
82 methods::SEND_STREAMING_MESSAGE => {
83 Ok(A2aRequestParams::SendStreamingMessage(self.parse_params()?))
84 },
85 methods::SUBSCRIBE_TO_TASK => {
86 Ok(A2aRequestParams::TaskResubscription(self.parse_params()?))
87 },
88 _ => Err(A2aParseError::UnsupportedMethod {
89 method: self.method.clone(),
90 }),
91 }
92 }
93
94 fn parse_params<T: serde::de::DeserializeOwned>(&self) -> Result<T, A2aParseError> {
95 serde_json::from_value(self.params.clone()).map_err(|e| A2aParseError::InvalidParams {
96 method: self.method.clone(),
97 error: e.to_string(),
98 })
99 }
100}
101
102#[derive(Debug, Clone, PartialEq)]
103pub enum A2aRequestParams {
104 SendMessage(MessageSendParams),
105 GetTask(TaskQueryParams),
106 CancelTask(TaskIdParams),
107 GetAuthenticatedExtendedCard(serde_json::Value),
108 SendStreamingMessage(MessageSendParams),
109 TaskResubscription(TaskResubscriptionRequest),
110}
111
112#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
113pub struct TaskResubscriptionRequest {
114 pub task_id: TaskId,
115}
116
117#[derive(Debug, thiserror::Error, Clone, PartialEq, Eq)]
118pub enum A2aParseError {
119 #[error("Unsupported method: {method}")]
120 UnsupportedMethod { method: String },
121
122 #[error("Invalid parameters for method '{method}': {error}")]
123 InvalidParams { method: String, error: String },
124}
125
126impl A2aResponse {
127 pub fn send_message(task: Task, id: RequestId) -> Self {
128 Self::SendMessage(JsonRpcResponse {
129 jsonrpc: "2.0".to_owned(),
130 id,
131 result: Some(task),
132 error: None,
133 })
134 }
135
136 pub fn get_task(task: Task, id: RequestId) -> Self {
137 Self::GetTask(JsonRpcResponse {
138 jsonrpc: "2.0".to_owned(),
139 id,
140 result: Some(task),
141 error: None,
142 })
143 }
144
145 pub fn cancel_task(task: Task, id: RequestId) -> Self {
146 Self::CancelTask(JsonRpcResponse {
147 jsonrpc: "2.0".to_owned(),
148 id,
149 result: Some(task),
150 error: None,
151 })
152 }
153}
154
155#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
156pub struct TaskNotFoundError {
157 pub task_id: TaskId,
158 pub message: String,
159 pub code: i32,
160 pub data: serde_json::Value,
161}
162
163#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
164pub struct TaskNotCancelableError {
165 pub task_id: TaskId,
166 pub state: TaskState,
167 pub message: String,
168 pub code: i32,
169 pub data: serde_json::Value,
170}
171
172#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
173pub struct UnsupportedOperationError {
174 pub operation: String,
175 pub message: String,
176 pub code: i32,
177 pub data: serde_json::Value,
178}