Skip to content

Commit 7389ebe

Browse files
committed
fix(client): serialize create-push requests for go interop
Signed-off-by: Luca Muscariello <muscariello@ieee.org>
1 parent 8421acb commit 7389ebe

File tree

2 files changed

+68
-13
lines changed

2 files changed

+68
-13
lines changed

a2a-client/src/jsonrpc.rs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use reqwest::Client;
99
use crate::push_config_compat::{
1010
deserialize_list_task_push_notification_configs_response,
1111
deserialize_task_push_notification_config,
12+
serialize_create_task_push_notification_config_request,
1213
};
1314
use crate::transport::{ServiceParams, Transport, TransportFactory};
1415

@@ -26,19 +27,13 @@ impl JsonRpcTransport {
2627
JsonRpcTransport { client, endpoint }
2728
}
2829

29-
async fn call_value<Req>(
30+
async fn call_value_with_payload(
3031
&self,
3132
params: &ServiceParams,
3233
method: &str,
33-
request_params: &Req,
34-
) -> Result<serde_json::Value, A2AError>
35-
where
36-
Req: ProtoJsonPayload,
37-
{
34+
payload: serde_json::Value,
35+
) -> Result<serde_json::Value, A2AError> {
3836
let id = JsonRpcId::String(uuid::Uuid::now_v7().to_string());
39-
let payload = protojson_conv::to_value(request_params).map_err(|e| {
40-
A2AError::internal(format!("failed to serialize request as ProtoJSON: {e}"))
41-
})?;
4237
let rpc_request = JsonRpcRequest::new(id, method, Some(payload));
4338

4439
let mut builder = self.client.post(&self.endpoint);
@@ -63,11 +58,25 @@ impl JsonRpcTransport {
6358
return Err(A2AError::new(err.code, err.message));
6459
}
6560

66-
let result = rpc_response
61+
rpc_response
6762
.result
68-
.ok_or_else(|| A2AError::internal("JSON-RPC response missing result"))?;
63+
.ok_or_else(|| A2AError::internal("JSON-RPC response missing result"))
64+
}
65+
66+
async fn call_value<Req>(
67+
&self,
68+
params: &ServiceParams,
69+
method: &str,
70+
request_params: &Req,
71+
) -> Result<serde_json::Value, A2AError>
72+
where
73+
Req: ProtoJsonPayload,
74+
{
75+
let payload = protojson_conv::to_value(request_params).map_err(|e| {
76+
A2AError::internal(format!("failed to serialize request as ProtoJSON: {e}"))
77+
})?;
6978

70-
Ok(result)
79+
self.call_value_with_payload(params, method, payload).await
7180
}
7281

7382
async fn call<Req, Resp>(
@@ -341,8 +350,9 @@ impl Transport for JsonRpcTransport {
341350
params: &ServiceParams,
342351
req: &CreateTaskPushNotificationConfigRequest,
343352
) -> Result<TaskPushNotificationConfig, A2AError> {
353+
let payload = serialize_create_task_push_notification_config_request(req)?;
344354
let result = self
345-
.call_value(params, methods::CREATE_PUSH_CONFIG, req)
355+
.call_value_with_payload(params, methods::CREATE_PUSH_CONFIG, payload)
346356
.await?;
347357
deserialize_task_push_notification_config(result)
348358
}

a2a-client/src/push_config_compat.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ use a2a::*;
44
use a2a_pb::protojson_conv;
55
use serde_json::Value;
66

7+
pub(crate) fn serialize_create_task_push_notification_config_request(
8+
request: &CreateTaskPushNotificationConfigRequest,
9+
) -> Result<Value, A2AError> {
10+
serde_json::to_value(request).map_err(|error| {
11+
A2AError::internal(format!(
12+
"failed to serialize create-push-config request: {error}"
13+
))
14+
})
15+
}
16+
717
pub(crate) fn deserialize_task_push_notification_config(
818
payload: Value,
919
) -> Result<TaskPushNotificationConfig, A2AError> {
@@ -40,6 +50,7 @@ pub(crate) fn deserialize_list_task_push_notification_configs_response(
4050
#[cfg(test)]
4151
mod tests {
4252
use super::*;
53+
use serde_json::json;
4354

4455
fn sample_task_push_config() -> TaskPushNotificationConfig {
4556
TaskPushNotificationConfig {
@@ -57,6 +68,40 @@ mod tests {
5768
}
5869
}
5970

71+
fn sample_create_task_push_config_request() -> CreateTaskPushNotificationConfigRequest {
72+
let config = sample_task_push_config();
73+
CreateTaskPushNotificationConfigRequest {
74+
task_id: config.task_id.clone(),
75+
config: config.config,
76+
tenant: config.tenant,
77+
}
78+
}
79+
80+
#[test]
81+
fn serializes_nested_create_task_push_config_request_shape() {
82+
let payload = serialize_create_task_push_notification_config_request(
83+
&sample_create_task_push_config_request(),
84+
)
85+
.unwrap();
86+
87+
assert_eq!(
88+
payload,
89+
json!({
90+
"taskId": "t1",
91+
"config": {
92+
"id": "cfg1",
93+
"url": "https://example.invalid/webhook",
94+
"token": "token-1",
95+
"authentication": {
96+
"scheme": "Bearer",
97+
"credentials": "secret"
98+
}
99+
},
100+
"tenant": "tenant-1"
101+
})
102+
);
103+
}
104+
60105
#[test]
61106
fn parses_nested_task_push_config_shape() {
62107
let payload = serde_json::to_value(sample_task_push_config()).unwrap();

0 commit comments

Comments
 (0)