Skip to content

Commit a886b1a

Browse files
feat(api)!: Update codebase to use only Proto based types (#337)
# Description Updated the codebase to only use Proto based types and remove the old JSON types.ts completely. This change unifies the usage of types with other SDKs and is part of the 1.0.0 scope. Equivalent PR on the Python SDK: a2aproject/a2a-python#572. # Important This is a breaking change and therefore it is going to be merged into an epic `v1.0` branch instead of `main`. Later 1.0 release will introduce this in the `main` branch. --------- Co-authored-by: Bartek Gralewicz <bgralewicz@google.com> Co-authored-by: Ivan Shymko <ishymko@google.com>
1 parent d4c261a commit a886b1a

68 files changed

Lines changed: 3468 additions & 6281 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.betterer.results

Lines changed: 17 additions & 70 deletions
Large diffs are not rendered by default.

.github/workflows/build-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ name: Run Build Tests
44

55
on:
66
push:
7-
branches: [ "main" ]
7+
branches: [ "main", "epic/**" ]
88
pull_request:
9-
branches: [ "main" ]
9+
branches: [ "main", "epic/**" ]
1010
paths-ignore:
1111
- '**.md'
1212
- 'LICENSE'

.github/workflows/lint.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ name: Run Linter & Formatter
22

33
on:
44
push:
5-
branches: [ "main" ]
5+
branches: [ "main", "epic/**" ]
66
pull_request:
7-
branches: [ "main" ]
7+
branches: [ "main", "epic/**" ]
88
paths-ignore:
99
- '**.md'
1010
- 'LICENSE'

.github/workflows/unit-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ name: Run Unit Tests
55

66
on:
77
push:
8-
branches: [ "main" ]
8+
branches: [ "main", "epic/**" ]
99
pull_request:
10-
branches: [ "main" ]
10+
branches: [ "main", "epic/**" ]
1111
paths-ignore:
1212
- '**.md'
1313
- 'LICENSE'

src/a2a_response.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import {
55
CancelTaskResponse,
66
SetTaskPushNotificationConfigResponse,
77
GetTaskPushNotificationConfigResponse,
8-
JSONRPCErrorResponse,
98
ListTaskPushNotificationConfigSuccessResponse,
109
DeleteTaskPushNotificationConfigSuccessResponse,
1110
GetAuthenticatedExtendedCardSuccessResponse,
12-
} from './types.js';
11+
JSONRPCErrorResponse,
12+
} from './json_rpc_types.js';
1313

1414
/**
1515
* Represents any valid JSON-RPC response defined in the A2A protocol.

src/client/card-resolver.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { AGENT_CARD_PATH } from '../constants.js';
2-
import { AgentCard } from '../types.js';
2+
import { AgentCard } from '../index.js';
33

44
export interface AgentCardResolverOptions {
55
path?: string;

src/client/client.ts

Lines changed: 61 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,19 @@
11
import {
22
AgentCard,
3-
JSONRPCResponse,
4-
MessageSendParams,
5-
SendMessageResponse,
6-
TaskQueryParams,
7-
GetTaskResponse,
8-
TaskIdParams,
9-
CancelTaskResponse,
103
TaskPushNotificationConfig, // Renamed from PushNotificationConfigParams for direct schema alignment
11-
SetTaskPushNotificationConfigResponse,
12-
GetTaskPushNotificationConfigResponse,
13-
ListTaskPushNotificationConfigParams,
14-
ListTaskPushNotificationConfigResponse,
15-
DeleteTaskPushNotificationConfigResponse,
16-
DeleteTaskPushNotificationConfigParams,
174
Message,
185
Task,
196
TaskArtifactUpdateEvent,
207
TaskStatusUpdateEvent,
21-
A2ARequest,
22-
JSONRPCErrorResponse,
23-
} from '../types.js'; // Assuming schema.ts is in the same directory or appropriately pathed
8+
CancelTaskRequest,
9+
CreateTaskPushNotificationConfigRequest,
10+
DeleteTaskPushNotificationConfigRequest,
11+
GetTaskPushNotificationConfigRequest,
12+
GetTaskRequest,
13+
ListTaskPushNotificationConfigRequest,
14+
SendMessageRequest,
15+
TaskSubscriptionRequest,
16+
} from '../index.js';
2417
import { AGENT_CARD_PATH } from '../constants.js';
2518
import { JsonRpcTransport } from './transports/json_rpc_transport.js';
2619
import { RequestOptions } from './multitransport-client.js';
@@ -152,11 +145,9 @@ export class A2AClient {
152145
* @param params The parameters for sending the message, including the message content and configuration.
153146
* @returns A Promise resolving to SendMessageResponse, which can be a Message, Task, or an error.
154147
*/
155-
public async sendMessage(params: MessageSendParams): Promise<SendMessageResponse> {
156-
return await this.invokeJsonRpc<MessageSendParams, SendMessageResponse>(
157-
(t, p, id) => t.sendMessage(p, A2AClient.emptyOptions, id),
158-
params
159-
);
148+
public async sendMessage(params: SendMessageRequest): Promise<SendMessageResult> {
149+
const transport = await this._getOrCreateTransport();
150+
return transport.sendMessage(params, A2AClient.emptyOptions, this.requestIdCounter++);
160151
}
161152

162153
/**
@@ -169,7 +160,7 @@ export class A2AClient {
169160
* The generator throws an error if streaming is not supported or if an HTTP/SSE error occurs.
170161
*/
171162
public async *sendMessageStream(
172-
params: MessageSendParams
163+
params: SendMessageRequest
173164
): AsyncGenerator<A2AStreamEventData, void, undefined> {
174165
const agentCard = await this.agentCardPromise; // Ensure agent card is fetched
175166
if (!agentCard.capabilities?.streaming) {
@@ -189,18 +180,24 @@ export class A2AClient {
189180
* @returns A Promise resolving to SetTaskPushNotificationConfigResponse.
190181
*/
191182
public async setTaskPushNotificationConfig(
192-
params: TaskPushNotificationConfig
193-
): Promise<SetTaskPushNotificationConfigResponse> {
183+
params: CreateTaskPushNotificationConfigRequest
184+
): Promise<TaskPushNotificationConfig> {
194185
const agentCard = await this.agentCardPromise;
195186
if (!agentCard.capabilities?.pushNotifications) {
196187
throw new Error(
197188
'Agent does not support push notifications (AgentCard.capabilities.pushNotifications is not true).'
198189
);
199190
}
200-
return await this.invokeJsonRpc<
201-
TaskPushNotificationConfig,
202-
SetTaskPushNotificationConfigResponse
203-
>((t, p, id) => t.setTaskPushNotificationConfig(p, A2AClient.emptyOptions, id), params);
191+
if (!params.config?.pushNotificationConfig) {
192+
throw new Error('Push notification configuration is required.');
193+
}
194+
195+
const transport = await this._getOrCreateTransport();
196+
return transport.setTaskPushNotificationConfig(
197+
params,
198+
A2AClient.emptyOptions,
199+
this.requestIdCounter++
200+
);
204201
}
205202

206203
/**
@@ -209,11 +206,13 @@ export class A2AClient {
209206
* @returns A Promise resolving to GetTaskPushNotificationConfigResponse.
210207
*/
211208
public async getTaskPushNotificationConfig(
212-
params: TaskIdParams
213-
): Promise<GetTaskPushNotificationConfigResponse> {
214-
return await this.invokeJsonRpc<TaskIdParams, GetTaskPushNotificationConfigResponse>(
215-
(t, p, id) => t.getTaskPushNotificationConfig(p, A2AClient.emptyOptions, id),
216-
params
209+
params: GetTaskPushNotificationConfigRequest
210+
): Promise<TaskPushNotificationConfig> {
211+
const transport = await this._getOrCreateTransport();
212+
return transport.getTaskPushNotificationConfig(
213+
params,
214+
A2AClient.emptyOptions,
215+
this.requestIdCounter++
217216
);
218217
}
219218

@@ -223,12 +222,14 @@ export class A2AClient {
223222
* @returns A Promise resolving to ListTaskPushNotificationConfigResponse.
224223
*/
225224
public async listTaskPushNotificationConfig(
226-
params: ListTaskPushNotificationConfigParams
227-
): Promise<ListTaskPushNotificationConfigResponse> {
228-
return await this.invokeJsonRpc<
229-
ListTaskPushNotificationConfigParams,
230-
ListTaskPushNotificationConfigResponse
231-
>((t, p, id) => t.listTaskPushNotificationConfig(p, A2AClient.emptyOptions, id), params);
225+
params: ListTaskPushNotificationConfigRequest
226+
): Promise<TaskPushNotificationConfig[]> {
227+
const transport = await this._getOrCreateTransport();
228+
return transport.listTaskPushNotificationConfig(
229+
params,
230+
A2AClient.emptyOptions,
231+
this.requestIdCounter++
232+
);
232233
}
233234

234235
/**
@@ -237,36 +238,34 @@ export class A2AClient {
237238
* @returns A Promise resolving to DeleteTaskPushNotificationConfigResponse.
238239
*/
239240
public async deleteTaskPushNotificationConfig(
240-
params: DeleteTaskPushNotificationConfigParams
241-
): Promise<DeleteTaskPushNotificationConfigResponse> {
242-
return await this.invokeJsonRpc<
243-
DeleteTaskPushNotificationConfigParams,
244-
DeleteTaskPushNotificationConfigResponse
245-
>((t, p, id) => t.deleteTaskPushNotificationConfig(p, A2AClient.emptyOptions, id), params);
241+
params: DeleteTaskPushNotificationConfigRequest
242+
): Promise<void> {
243+
const transport = await this._getOrCreateTransport();
244+
return transport.deleteTaskPushNotificationConfig(
245+
params,
246+
A2AClient.emptyOptions,
247+
this.requestIdCounter++
248+
);
246249
}
247250

248251
/**
249252
* Retrieves a task by its ID.
250253
* @param params Parameters containing the taskId and optional historyLength.
251254
* @returns A Promise resolving to GetTaskResponse, which contains the Task object or an error.
252255
*/
253-
public async getTask(params: TaskQueryParams): Promise<GetTaskResponse> {
254-
return await this.invokeJsonRpc<TaskQueryParams, GetTaskResponse>(
255-
(t, p, id) => t.getTask(p, A2AClient.emptyOptions, id),
256-
params
257-
);
256+
public async getTask(params: GetTaskRequest): Promise<Task> {
257+
const transport = await this._getOrCreateTransport();
258+
return transport.getTask(params, A2AClient.emptyOptions, this.requestIdCounter++);
258259
}
259260

260261
/**
261262
* Cancels a task by its ID.
262263
* @param params Parameters containing the taskId.
263264
* @returns A Promise resolving to CancelTaskResponse, which contains the updated Task object or an error.
264265
*/
265-
public async cancelTask(params: TaskIdParams): Promise<CancelTaskResponse> {
266-
return await this.invokeJsonRpc<TaskIdParams, CancelTaskResponse>(
267-
(t, p, id) => t.cancelTask(p, A2AClient.emptyOptions, id),
268-
params
269-
);
266+
public async cancelTask(params: CancelTaskRequest): Promise<Task> {
267+
const transport = await this._getOrCreateTransport();
268+
return transport.cancelTask(params, A2AClient.emptyOptions, this.requestIdCounter++);
270269
}
271270

272271
/**
@@ -277,26 +276,16 @@ export class A2AClient {
277276
* @param params Extension paramters defined in the AgentCard's extensions.
278277
* @returns A Promise that resolves to the RPC response.
279278
*/
280-
public async callExtensionMethod<TExtensionParams, TExtensionResponse extends JSONRPCResponse>(
279+
public async callExtensionMethod<TExtensionParams, TExtensionResponse>(
281280
method: string,
282281
params: TExtensionParams
283282
) {
284283
const transport = await this._getOrCreateTransport();
285-
try {
286-
return await transport.callExtensionMethod<TExtensionParams, TExtensionResponse>(
287-
method,
288-
params,
289-
this.requestIdCounter++
290-
);
291-
} catch (e) {
292-
// For compatibility, return JSON-RPC errors as errors instead of throwing transport-agnostic errors
293-
// produced by JsonRpcTransport.
294-
const errorResponse = extractJSONRPCError(e);
295-
if (errorResponse) {
296-
return errorResponse as TExtensionResponse;
297-
}
298-
throw e;
299-
}
284+
return await transport.callExtensionMethod<TExtensionParams, TExtensionResponse>(
285+
method,
286+
params,
287+
this.requestIdCounter++
288+
);
300289
}
301290

302291
/**
@@ -307,7 +296,7 @@ export class A2AClient {
307296
* @returns An AsyncGenerator yielding A2AStreamEventData (Message, Task, TaskStatusUpdateEvent, or TaskArtifactUpdateEvent).
308297
*/
309298
public async *resubscribeTask(
310-
params: TaskIdParams
299+
params: TaskSubscriptionRequest
311300
): AsyncGenerator<A2AStreamEventData, void, undefined> {
312301
const agentCard = await this.agentCardPromise;
313302
if (!agentCard.capabilities?.streaming) {
@@ -434,54 +423,4 @@ export class A2AClient {
434423
}
435424
return this.serviceEndpointUrl;
436425
}
437-
438-
private async invokeJsonRpc<TParams extends JsonRpcParams, TResponse extends JSONRPCResponse>(
439-
caller: JsonRpcCaller<TParams, TResponse>,
440-
params?: TParams
441-
): Promise<TResponse> {
442-
const transport = await this._getOrCreateTransport();
443-
const requestId = this.requestIdCounter++;
444-
try {
445-
const result = await caller(transport, params, requestId);
446-
return {
447-
id: requestId,
448-
jsonrpc: '2.0',
449-
result: result ?? null, // JSON-RPC requires result property on success, it will be null for "void" methods.
450-
} as TResponse;
451-
} catch (e) {
452-
// For compatibility, return JSON-RPC errors as response objects instead of throwing transport-agnostic errors
453-
// produced by JsonRpcTransport.
454-
const errorResponse = extractJSONRPCError(e);
455-
if (errorResponse) {
456-
return errorResponse as TResponse;
457-
}
458-
throw e;
459-
}
460-
}
461426
}
462-
463-
function extractJSONRPCError(error: unknown): JSONRPCErrorResponse {
464-
if (
465-
error instanceof Object &&
466-
'errorResponse' in error &&
467-
error.errorResponse instanceof Object &&
468-
'jsonrpc' in error.errorResponse &&
469-
error.errorResponse.jsonrpc === '2.0' &&
470-
'error' in error.errorResponse &&
471-
error.errorResponse.error !== null
472-
) {
473-
return error.errorResponse as JSONRPCErrorResponse;
474-
} else {
475-
return undefined;
476-
}
477-
}
478-
479-
// Utility unexported types to properly factor out common "compatibility" logic via invokeJsonRpc.
480-
type ParamsOf<T> = T extends { params: unknown } ? T['params'] : undefined;
481-
type ResultOf<T> = T extends { result: unknown } ? T['result'] : void;
482-
type JsonRpcParams = ParamsOf<A2ARequest>;
483-
type JsonRpcCaller<TParams extends JsonRpcParams, TResponse extends JSONRPCResponse> = (
484-
transport: JsonRpcTransport,
485-
params: TParams,
486-
idOverride: number
487-
) => Promise<ResultOf<TResponse>>;

src/client/factory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { TransportProtocolName } from '../core.js';
2-
import { AgentCard } from '../types.js';
2+
import { AgentCard } from '../index.js';
33
import { AgentCardResolver } from './card-resolver.js';
44
import { Client, ClientConfig } from './multitransport-client.js';
55
import { JsonRpcTransportFactory } from './transports/json_rpc_transport.js';

src/client/interceptors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { AgentCard } from '../types.js';
1+
import { AgentCard } from '../index.js';
22
import { A2AStreamEventData } from './client.js';
33
import { Client } from './multitransport-client.js';
44
import { RequestOptions } from './multitransport-client.js';

0 commit comments

Comments
 (0)