@@ -17,34 +17,39 @@ import 'a2a_exception.dart';
1717import 'http_transport.dart' ;
1818import 'transport.dart' ;
1919
20- /// A client for interacting with an A2A server.
20+ /// A client for interacting with an A2A (Agent-to-Agent) server.
2121///
2222/// This class provides methods for all the RPC calls defined in the A2A
2323/// specification. It handles the JSON-RPC 2.0 protocol and uses a [Transport]
24- /// to communicate with the server.
24+ /// instance to communicate with the server, which defaults to [HttpTransport] .
2525class A2AClient {
26- /// The URL of the A2A server.
26+ /// The base URL of the A2A server.
2727 final String url;
2828
2929 final Transport _transport;
3030 final Logger ? _log;
3131
32- /// Creates an [A2AClient] .
32+ /// Creates an [A2AClient] instance .
3333 ///
34- /// The [url] is the base URL of the A2A server.
34+ /// The [url] parameter is required and specifies the base URL of the A2A
35+ /// server (e.g., `http://localhost:8000` ).
3536 ///
36- /// The [transport] is the transport to use for communication. If not
37- /// provided , an [HttpTransport] will be used .
37+ /// An optional [transport] can be provided to customize the communication
38+ /// layer. If omitted , an [HttpTransport] is created using the provided [url] .
3839 ///
39- /// The [log] is the logger to use for logging.
40+ /// An optional [log] instance can be provided for logging client activities .
4041 A2AClient ({required this .url, Transport ? transport, Logger ? log})
4142 : _transport = transport ?? HttpTransport (url: url, log: log),
4243 _log = log;
4344
44- /// Fetches the agent card from the server.
45+ /// Fetches the public agent card from the server.
4546 ///
46- /// The agent card contains metadata about the agent. This is typically
47- /// requested from the `/.well-known/agent-card.json` endpoint.
47+ /// The agent card contains metadata about the agent, such as its capabilities
48+ /// and security schemes. This method typically requests the card from the
49+ /// `/.well-known/agent-card.json` endpoint on the server.
50+ ///
51+ /// Returns an [AgentCard] object.
52+ /// Throws an [A2AException] if the request fails or the response is invalid.
4853 Future <AgentCard > getAgentCard () async {
4954 _log? .info ('Fetching agent card...' );
5055 final response = await _transport.get ('/.well-known/agent-card.json' );
@@ -54,9 +59,13 @@ class A2AClient {
5459
5560 /// Fetches the authenticated extended agent card from the server.
5661 ///
57- /// This method is used to get a more detailed agent card that may be
58- /// available to authenticated users. It sends an `Authorization` header
59- /// with the given [token] .
62+ /// This method retrieves a potentially more detailed [AgentCard] that is only
63+ /// available to authenticated users. It includes an `Authorization` header
64+ /// with the provided Bearer [token] in the request to
65+ /// `/.well-known/agent-card.json` .
66+ ///
67+ /// Returns an [AgentCard] object.
68+ /// Throws an [A2AException] if the request fails or the response is invalid.
6069 Future <AgentCard > getAuthenticatedExtendedCard (String token) async {
6170 _log? .info ('Fetching authenticated agent card...' );
6271 final response = await _transport.get (
@@ -67,13 +76,19 @@ class A2AClient {
6776 return AgentCard .fromJson (response);
6877 }
6978
70- /// Sends a message to the agent for a single-shot interaction.
79+ /// Sends a message to the agent for a single-shot interaction via
80+ /// `message/send` .
7181 ///
7282 /// This method is used for synchronous request/response interactions. The
73- /// returned [Task] contains the initial state of the task. For long-running
74- /// tasks, the client can poll the task status using [getTask] .
83+ /// server is expected to process the [message] and return a result relatively
84+ /// quickly. The returned [Task] contains the initial state of the task as
85+ /// reported by the server.
86+ ///
87+ /// For operations that are expected to take longer, consider using
88+ /// [messageStream] or polling the task status using [getTask] .
7589 ///
76- /// Throws an [A2AException] if the server returns an error.
90+ /// Returns the initial [Task] state. Throws an [A2AException] if the server
91+ /// returns a JSON-RPC error.
7792 Future <Task > messageSend (Message message) async {
7893 _log? .info ('Sending message: ${message .messageId }' );
7994 final response = await _transport.send ({
@@ -93,13 +108,17 @@ class A2AClient {
93108 return Task .fromJson (response['result' ] as Map <String , Object ?>);
94109 }
95110
96- /// Sends a message to the agent and subscribes to real-time updates.
111+ /// Sends a message to the agent and subscribes to real-time updates via
112+ /// `message/stream` .
97113 ///
98- /// This method is used for streaming interactions with the agent. The
99- /// returned stream will emit [Event] objects as they are received from the
100- /// server via Server-Sent Events (SSE).
114+ /// This method is used for streaming interactions. The agent can send
115+ /// multiple updates over time. The returned stream emits [Event] objects as
116+ /// they are received from the server, typically using Server-Sent Events
117+ /// (SSE).
101118 ///
102- /// Throws an [A2AException] if the server returns an error in the stream.
119+ /// Returns a [Stream] of [Event] objects. The stream will emit an
120+ /// [A2AException] if the server sends a JSON-RPC error within the event
121+ /// stream.
103122 Stream <Event > messageStream (Message message) {
104123 _log? .info ('Sending message for stream: ${message .messageId }' );
105124 final stream = _transport.sendStream ({
@@ -131,10 +150,13 @@ class A2AClient {
131150 );
132151 }
133152
134- /// Retrieves the current state of a task from the server.
153+ /// Retrieves the current state of a task from the server using `tasks/get` .
135154 ///
136- /// This is typically used for polling the status of a task that was initiated
137- /// with [messageSend] .
155+ /// This method is used to poll the status of a task, identified by [taskId] ,
156+ /// that was previously initiated (e.g., via [messageSend] ).
157+ ///
158+ /// Returns the current [Task] state. Throws an [A2AException] if the server
159+ /// returns a JSON-RPC error (e.g., task not found).
138160 Future <Task > getTask (String taskId) async {
139161 _log? .info ('Getting task: $taskId ' );
140162 final response = await _transport.send ({
@@ -144,12 +166,23 @@ class A2AClient {
144166 'id' : 0 ,
145167 });
146168 _log? .fine ('Received response from tasks/get: $response ' );
169+ if (response.containsKey ('error' )) {
170+ final error = response['error' ] as Map <String , Object ?>;
171+ throw A2AException .jsonRpc (
172+ code: error['code' ] as int ,
173+ message: error['message' ] as String ,
174+ );
175+ }
147176 return Task .fromJson (response['result' ] as Map <String , Object ?>);
148177 }
149178
150- /// Retrieves a list of tasks from the server.
179+ /// Retrieves a list of tasks from the server using `tasks/list` .
151180 ///
152- /// The optional [params] can be used to filter and paginate the results.
181+ /// The optional [params] of type [ListTasksParams] can be provided to filter,
182+ /// sort, and paginate the task list.
183+ ///
184+ /// Returns a [ListTasksResult] containing the list of tasks and pagination
185+ /// info. Throws an [A2AException] if the server returns a JSON-RPC error.
153186 Future <ListTasksResult > listTasks ([ListTasksParams ? params]) async {
154187 _log? .info ('Listing tasks...' );
155188 final response = await _transport.send ({
@@ -159,14 +192,24 @@ class A2AClient {
159192 'id' : 0 ,
160193 });
161194 _log? .fine ('Received response from tasks/list: $response ' );
195+ if (response.containsKey ('error' )) {
196+ final error = response['error' ] as Map <String , Object ?>;
197+ throw A2AException .jsonRpc (
198+ code: error['code' ] as int ,
199+ message: error['message' ] as String ,
200+ );
201+ }
162202 return ListTasksResult .fromJson (response['result' ] as Map <String , Object ?>);
163203 }
164204
165- /// Requests the cancellation of an ongoing task.
205+ /// Requests the cancellation of an ongoing task using `tasks/cancel` .
166206 ///
167- /// The server will attempt to cancel the task, but success is not guaranteed.
168- /// The returned [Task] will contain the state of the task after the
169- /// cancellation request.
207+ /// The server will attempt to cancel the task identified by [taskId] .
208+ /// Success is not guaranteed, as the task might have already completed or may
209+ /// not support cancellation.
210+ ///
211+ /// Returns the updated [Task] state after the cancellation request.
212+ /// Throws an [A2AException] if the server returns a JSON-RPC error.
170213 Future <Task > cancelTask (String taskId) async {
171214 _log? .info ('Canceling task: $taskId ' );
172215 final response = await _transport.send ({
@@ -176,13 +219,25 @@ class A2AClient {
176219 'id' : 0 ,
177220 });
178221 _log? .fine ('Received response from tasks/cancel: $response ' );
222+ if (response.containsKey ('error' )) {
223+ final error = response['error' ] as Map <String , Object ?>;
224+ throw A2AException .jsonRpc (
225+ code: error['code' ] as int ,
226+ message: error['message' ] as String ,
227+ );
228+ }
179229 return Task .fromJson (response['result' ] as Map <String , Object ?>);
180230 }
181231
182- /// Resubscribes to an SSE stream for an ongoing task.
232+ /// Resubscribes to an SSE stream for an ongoing task using
233+ /// `tasks/resubscribe` .
183234 ///
184- /// This can be used to reconnect to a stream after a disconnection. The
235+ /// This method allows a client to reconnect to the event stream of a task
236+ /// identified by [taskId] , for instance, after a network interruption. The
185237 /// returned stream will emit subsequent [Event] objects for the task.
238+ ///
239+ /// Returns a [Stream] of [Event] objects. The stream will emit an
240+ /// [A2AException] if the server returns a JSON-RPC error.
186241 Stream <Event > resubscribeToTask (String taskId) {
187242 _log? .info ('Resubscribing to task: $taskId ' );
188243 return _transport
@@ -193,16 +248,31 @@ class A2AClient {
193248 })
194249 .map ((data) {
195250 _log? .fine ('Received event from stream: $data ' );
251+ if (data.containsKey ('error' )) {
252+ final error = data['error' ] as Map <String , Object ?>;
253+ throw A2AException .jsonRpc (
254+ code: error['code' ] as int ,
255+ message: error['message' ] as String ,
256+ );
257+ }
196258 return Event .fromJson (data);
197259 });
198260 }
199261
200- /// Closes the underlying transport.
262+ /// Closes the underlying transport connection.
263+ ///
264+ /// This should be called when the client is no longer needed to release
265+ /// resources.
201266 void close () {
202267 _transport.close ();
203268 }
204269
205270 /// Sets or updates the push notification configuration for a task.
271+ ///
272+ /// Uses the `tasks/pushNotificationConfig/set` method.
273+ ///
274+ /// Returns the updated [TaskPushNotificationConfig] .
275+ /// Throws an [A2AException] if the server returns a JSON-RPC error.
206276 Future <TaskPushNotificationConfig > setPushNotificationConfig (
207277 TaskPushNotificationConfig params,
208278 ) async {
@@ -229,6 +299,12 @@ class A2AClient {
229299 }
230300
231301 /// Retrieves a specific push notification configuration for a task.
302+ ///
303+ /// Uses the `tasks/pushNotificationConfig/get` method, identified by [taskId]
304+ /// and [configId] .
305+ ///
306+ /// Returns the requested [TaskPushNotificationConfig] .
307+ /// Throws an [A2AException] if the server returns a JSON-RPC error.
232308 Future <TaskPushNotificationConfig > getPushNotificationConfig (
233309 String taskId,
234310 String configId,
@@ -255,7 +331,12 @@ class A2AClient {
255331 );
256332 }
257333
258- /// Lists all push notification configurations for a task.
334+ /// Lists all push notification configurations for a given task.
335+ ///
336+ /// Uses the `tasks/pushNotificationConfig/list` method, identified by [taskId] .
337+ ///
338+ /// Returns a List of [PushNotificationConfig] objects.
339+ /// Throws an [A2AException] if the server returns a JSON-RPC error.
259340 Future <List <PushNotificationConfig >> listPushNotificationConfigs (
260341 String taskId,
261342 ) async {
@@ -287,6 +368,11 @@ class A2AClient {
287368 }
288369
289370 /// Deletes a specific push notification configuration for a task.
371+ ///
372+ /// Uses the `tasks/pushNotificationConfig/delete` method, identified by [taskId]
373+ /// and [configId] .
374+ ///
375+ /// Throws an [A2AException] if the server returns a JSON-RPC error.
290376 Future <void > deletePushNotificationConfig (
291377 String taskId,
292378 String configId,
0 commit comments