Skip to content

Commit 17267ed

Browse files
committed
refactor(client): take request ownership in A2AClient methods; fix config fallback and async file I/O
- A2AClient methods now take request structs by value (mut req) and assign req.tenant in place, eliminating the struct-spread clone on every call - find_config_file() falls back to checking the home directory directly when CWD is outside the home directory tree (e.g. /tmp) - resolve_agent_card uses tokio::fs::read_to_string instead of the blocking std::fs variant - Remove the forward slimrpc stub from parse_binding_str; it will be re-added in the follow-up slimrpc PR Signed-off-by: Sam Betts <1769706+Tehsmash@users.noreply.github.com>
1 parent 25db168 commit 17267ed

3 files changed

Lines changed: 67 additions & 98 deletions

File tree

a2a-client/src/client.rs

Lines changed: 50 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -79,141 +79,108 @@ impl<T: Transport> A2AClient<T> {
7979

8080
pub async fn send_message(
8181
&self,
82-
req: &SendMessageRequest,
82+
mut req: SendMessageRequest,
8383
) -> Result<SendMessageResponse, A2AError> {
8484
let params = self.apply_before(methods::SEND_MESSAGE).await?;
85-
let patched = SendMessageRequest {
86-
tenant: self.tenant.clone(),
87-
..req.clone()
88-
};
89-
let result = self.transport.send_message(&params, &patched).await;
85+
req.tenant = self.tenant.clone();
86+
let result = self.transport.send_message(&params, &req).await;
9087
self.finish_call(methods::SEND_MESSAGE, result).await
9188
}
9289

9390
pub async fn send_streaming_message(
9491
&self,
95-
req: &SendMessageRequest,
92+
mut req: SendMessageRequest,
9693
) -> Result<BoxStream<'static, Result<StreamResponse, A2AError>>, A2AError> {
9794
let params = self.apply_before(methods::SEND_STREAMING_MESSAGE).await?;
98-
let patched = SendMessageRequest {
99-
tenant: self.tenant.clone(),
100-
..req.clone()
101-
};
102-
let result = self
103-
.transport
104-
.send_streaming_message(&params, &patched)
105-
.await;
95+
req.tenant = self.tenant.clone();
96+
let result = self.transport.send_streaming_message(&params, &req).await;
10697
self.finish_call(methods::SEND_STREAMING_MESSAGE, result)
10798
.await
10899
}
109100

110-
pub async fn get_task(&self, req: &GetTaskRequest) -> Result<Task, A2AError> {
101+
pub async fn get_task(&self, mut req: GetTaskRequest) -> Result<Task, A2AError> {
111102
let params = self.apply_before(methods::GET_TASK).await?;
112-
let patched = GetTaskRequest {
113-
tenant: self.tenant.clone(),
114-
..req.clone()
115-
};
116-
let result = self.transport.get_task(&params, &patched).await;
103+
req.tenant = self.tenant.clone();
104+
let result = self.transport.get_task(&params, &req).await;
117105
self.finish_call(methods::GET_TASK, result).await
118106
}
119107

120-
pub async fn list_tasks(&self, req: &ListTasksRequest) -> Result<ListTasksResponse, A2AError> {
108+
pub async fn list_tasks(
109+
&self,
110+
mut req: ListTasksRequest,
111+
) -> Result<ListTasksResponse, A2AError> {
121112
let params = self.apply_before(methods::LIST_TASKS).await?;
122-
let patched = ListTasksRequest {
123-
tenant: self.tenant.clone(),
124-
..req.clone()
125-
};
126-
let result = self.transport.list_tasks(&params, &patched).await;
113+
req.tenant = self.tenant.clone();
114+
let result = self.transport.list_tasks(&params, &req).await;
127115
self.finish_call(methods::LIST_TASKS, result).await
128116
}
129117

130-
pub async fn cancel_task(&self, req: &CancelTaskRequest) -> Result<Task, A2AError> {
118+
pub async fn cancel_task(&self, mut req: CancelTaskRequest) -> Result<Task, A2AError> {
131119
let params = self.apply_before(methods::CANCEL_TASK).await?;
132-
let patched = CancelTaskRequest {
133-
tenant: self.tenant.clone(),
134-
..req.clone()
135-
};
136-
let result = self.transport.cancel_task(&params, &patched).await;
120+
req.tenant = self.tenant.clone();
121+
let result = self.transport.cancel_task(&params, &req).await;
137122
self.finish_call(methods::CANCEL_TASK, result).await
138123
}
139124

140125
pub async fn subscribe_to_task(
141126
&self,
142-
req: &SubscribeToTaskRequest,
127+
mut req: SubscribeToTaskRequest,
143128
) -> Result<BoxStream<'static, Result<StreamResponse, A2AError>>, A2AError> {
144129
let params = self.apply_before(methods::SUBSCRIBE_TO_TASK).await?;
145-
let patched = SubscribeToTaskRequest {
146-
tenant: self.tenant.clone(),
147-
..req.clone()
148-
};
149-
let result = self.transport.subscribe_to_task(&params, &patched).await;
130+
req.tenant = self.tenant.clone();
131+
let result = self.transport.subscribe_to_task(&params, &req).await;
150132
self.finish_call(methods::SUBSCRIBE_TO_TASK, result).await
151133
}
152134

153135
pub async fn create_push_config(
154136
&self,
155-
req: &TaskPushNotificationConfig,
137+
mut req: TaskPushNotificationConfig,
156138
) -> Result<TaskPushNotificationConfig, A2AError> {
157139
let params = self.apply_before(methods::CREATE_PUSH_CONFIG).await?;
158-
let patched = TaskPushNotificationConfig {
159-
tenant: self.tenant.clone(),
160-
..req.clone()
161-
};
162-
let result = self.transport.create_push_config(&params, &patched).await;
140+
req.tenant = self.tenant.clone();
141+
let result = self.transport.create_push_config(&params, &req).await;
163142
self.finish_call(methods::CREATE_PUSH_CONFIG, result).await
164143
}
165144

166145
pub async fn get_push_config(
167146
&self,
168-
req: &GetTaskPushNotificationConfigRequest,
147+
mut req: GetTaskPushNotificationConfigRequest,
169148
) -> Result<TaskPushNotificationConfig, A2AError> {
170149
let params = self.apply_before(methods::GET_PUSH_CONFIG).await?;
171-
let patched = GetTaskPushNotificationConfigRequest {
172-
tenant: self.tenant.clone(),
173-
..req.clone()
174-
};
175-
let result = self.transport.get_push_config(&params, &patched).await;
150+
req.tenant = self.tenant.clone();
151+
let result = self.transport.get_push_config(&params, &req).await;
176152
self.finish_call(methods::GET_PUSH_CONFIG, result).await
177153
}
178154

179155
pub async fn list_push_configs(
180156
&self,
181-
req: &ListTaskPushNotificationConfigsRequest,
157+
mut req: ListTaskPushNotificationConfigsRequest,
182158
) -> Result<ListTaskPushNotificationConfigsResponse, A2AError> {
183159
let params = self.apply_before(methods::LIST_PUSH_CONFIGS).await?;
184-
let patched = ListTaskPushNotificationConfigsRequest {
185-
tenant: self.tenant.clone(),
186-
..req.clone()
187-
};
188-
let result = self.transport.list_push_configs(&params, &patched).await;
160+
req.tenant = self.tenant.clone();
161+
let result = self.transport.list_push_configs(&params, &req).await;
189162
self.finish_call(methods::LIST_PUSH_CONFIGS, result).await
190163
}
191164

192165
pub async fn delete_push_config(
193166
&self,
194-
req: &DeleteTaskPushNotificationConfigRequest,
167+
mut req: DeleteTaskPushNotificationConfigRequest,
195168
) -> Result<(), A2AError> {
196169
let params = self.apply_before(methods::DELETE_PUSH_CONFIG).await?;
197-
let patched = DeleteTaskPushNotificationConfigRequest {
198-
tenant: self.tenant.clone(),
199-
..req.clone()
200-
};
201-
let result = self.transport.delete_push_config(&params, &patched).await;
170+
req.tenant = self.tenant.clone();
171+
let result = self.transport.delete_push_config(&params, &req).await;
202172
self.finish_call(methods::DELETE_PUSH_CONFIG, result).await
203173
}
204174

205175
pub async fn get_extended_agent_card(
206176
&self,
207-
req: &GetExtendedAgentCardRequest,
177+
mut req: GetExtendedAgentCardRequest,
208178
) -> Result<AgentCard, A2AError> {
209179
let params = self.apply_before(methods::GET_EXTENDED_AGENT_CARD).await?;
210-
let patched = GetExtendedAgentCardRequest {
211-
tenant: self.tenant.clone(),
212-
..req.clone()
213-
};
180+
req.tenant = self.tenant.clone();
214181
let result = self
215182
.transport
216-
.get_extended_agent_card(&params, &patched)
183+
.get_extended_agent_card(&params, &req)
217184
.await;
218185
self.finish_call(methods::GET_EXTENDED_AGENT_CARD, result)
219186
.await
@@ -246,7 +213,7 @@ impl<T: Transport> SendMessageExt for A2AClient<T> {
246213
metadata: None,
247214
tenant: None,
248215
};
249-
self.send_message(&req).await
216+
self.send_message(req).await
250217
}
251218
}
252219

@@ -533,7 +500,7 @@ mod tests {
533500
metadata: None,
534501
tenant: None,
535502
};
536-
let resp = client.send_message(&req).await.unwrap();
503+
let resp = client.send_message(req).await.unwrap();
537504
assert!(matches!(resp, SendMessageResponse::Task(_)));
538505
}
539506

@@ -559,7 +526,7 @@ mod tests {
559526
tenant: None,
560527
};
561528

562-
client.send_message(&req).await.unwrap();
529+
client.send_message(req).await.unwrap();
563530

564531
let calls = state.calls.lock().unwrap();
565532
let params = &calls[0].1;
@@ -598,7 +565,7 @@ mod tests {
598565
tenant: None,
599566
};
600567

601-
let err = client.send_message(&req).await.unwrap_err();
568+
let err = client.send_message(req).await.unwrap_err();
602569
assert_eq!(err.message, "boom");
603570

604571
let events = events.lock().unwrap().clone();
@@ -618,7 +585,7 @@ mod tests {
618585
metadata: None,
619586
tenant: None,
620587
};
621-
let mut stream = client.send_streaming_message(&req).await.unwrap();
588+
let mut stream = client.send_streaming_message(req).await.unwrap();
622589
let item = stream.next().await.unwrap().unwrap();
623590
assert!(matches!(item, StreamResponse::StatusUpdate(_)));
624591
}
@@ -631,7 +598,7 @@ mod tests {
631598
history_length: None,
632599
tenant: None,
633600
};
634-
let task = client.get_task(&req).await.unwrap();
601+
let task = client.get_task(req).await.unwrap();
635602
assert_eq!(task.id, "t1");
636603
}
637604

@@ -648,7 +615,7 @@ mod tests {
648615
include_artifacts: None,
649616
tenant: None,
650617
};
651-
let resp = client.list_tasks(&req).await.unwrap();
618+
let resp = client.list_tasks(req).await.unwrap();
652619
assert!(resp.tasks.is_empty());
653620
}
654621

@@ -660,7 +627,7 @@ mod tests {
660627
metadata: None,
661628
tenant: None,
662629
};
663-
let task = client.cancel_task(&req).await.unwrap();
630+
let task = client.cancel_task(req).await.unwrap();
664631
assert_eq!(task.status.state, TaskState::Canceled);
665632
}
666633

@@ -671,7 +638,7 @@ mod tests {
671638
id: "t1".into(),
672639
tenant: None,
673640
};
674-
let _stream = client.subscribe_to_task(&req).await.unwrap();
641+
let _stream = client.subscribe_to_task(req).await.unwrap();
675642
}
676643

677644
#[tokio::test]
@@ -685,7 +652,7 @@ mod tests {
685652
authentication: None,
686653
tenant: None,
687654
};
688-
let resp = client.create_push_config(&req).await.unwrap();
655+
let resp = client.create_push_config(req).await.unwrap();
689656
assert_eq!(resp.task_id, "t1");
690657
}
691658

@@ -697,7 +664,7 @@ mod tests {
697664
id: "cfg1".into(),
698665
tenant: None,
699666
};
700-
let resp = client.get_push_config(&req).await.unwrap();
667+
let resp = client.get_push_config(req).await.unwrap();
701668
assert_eq!(resp.id, Some("cfg1".into()));
702669
}
703670

@@ -710,7 +677,7 @@ mod tests {
710677
page_token: None,
711678
tenant: None,
712679
};
713-
let resp = client.list_push_configs(&req).await.unwrap();
680+
let resp = client.list_push_configs(req).await.unwrap();
714681
assert!(resp.configs.is_empty());
715682
}
716683

@@ -722,14 +689,14 @@ mod tests {
722689
id: "cfg1".into(),
723690
tenant: None,
724691
};
725-
client.delete_push_config(&req).await.unwrap();
692+
client.delete_push_config(req).await.unwrap();
726693
}
727694

728695
#[tokio::test]
729696
async fn test_get_extended_agent_card() {
730697
let client = make_client();
731698
let req = GetExtendedAgentCardRequest { tenant: None };
732-
let card = client.get_extended_agent_card(&req).await.unwrap();
699+
let card = client.get_extended_agent_card(req).await.unwrap();
733700
assert_eq!(card.name, "Test");
734701
}
735702

a2acli/src/config.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ const CONFIG_FILENAME: &str = ".a2a.yaml";
3737
pub fn find_config_file() -> Option<PathBuf> {
3838
let cwd = std::env::current_dir().ok()?;
3939
let home = home_dir();
40-
find_config_file_from(&cwd, home.as_deref())
40+
find_config_file_from(&cwd, home.as_deref()).or_else(|| {
41+
home.as_ref()
42+
.map(|h| h.join(CONFIG_FILENAME))
43+
.filter(|p| p.is_file())
44+
})
4145
}
4246

4347
fn home_dir() -> Option<PathBuf> {
@@ -129,8 +133,6 @@ fn parse_binding_str(s: &str) -> Option<Binding> {
129133
match s {
130134
"jsonrpc" => Some(Binding::Jsonrpc),
131135
"http-json" => Some(Binding::HttpJson),
132-
#[cfg(feature = "slimrpc")]
133-
"slimrpc" => Some(Binding::Slimrpc),
134136
_ => None,
135137
}
136138
}

0 commit comments

Comments
 (0)