@a2a-js/sdk 0.3.6 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/dist/chunk-SJNAG4AL.js +122 -0
- package/dist/client/index.cjs +289 -51
- package/dist/client/index.d.cts +60 -2
- package/dist/client/index.d.ts +60 -2
- package/dist/client/index.js +245 -95
- package/dist/server/express/index.cjs +19 -16
- package/dist/server/express/index.js +9 -38
- package/dist/server/index.cjs +184 -6
- package/dist/server/index.d.cts +68 -8
- package/dist/server/index.d.ts +68 -8
- package/dist/server/index.js +184 -6
- package/package.json +9 -15
package/README.md
CHANGED
|
@@ -23,13 +23,13 @@ npm install @a2a-js/sdk
|
|
|
23
23
|
|
|
24
24
|
### For Server Usage
|
|
25
25
|
|
|
26
|
-
If you plan to use the
|
|
26
|
+
If you plan to use the Express integration (imports from `@a2a-js/sdk/server/express`) for A2A server, you'll also need to install Express as it's a peer dependency:
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
29
|
npm install express
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
You can also find
|
|
32
|
+
You can also find some samples [here](https://github.com/a2aproject/a2a-js/tree/main/src/samples).
|
|
33
33
|
|
|
34
34
|
---
|
|
35
35
|
|
|
@@ -121,8 +121,8 @@ The [`ClientFactory`](src/client/factory.ts) makes it easy to communicate with a
|
|
|
121
121
|
|
|
122
122
|
```typescript
|
|
123
123
|
// client.ts
|
|
124
|
-
import { ClientFactory
|
|
125
|
-
import { Message, MessageSendParams } from '@a2a-js/sdk';
|
|
124
|
+
import { ClientFactory } from '@a2a-js/sdk/client';
|
|
125
|
+
import { Message, MessageSendParams, SendMessageSuccessResponse } from '@a2a-js/sdk';
|
|
126
126
|
import { v4 as uuidv4 } from 'uuid';
|
|
127
127
|
|
|
128
128
|
async function run() {
|
|
@@ -222,8 +222,8 @@ The client sends a message and receives a `Task` object as the result.
|
|
|
222
222
|
|
|
223
223
|
```typescript
|
|
224
224
|
// client.ts
|
|
225
|
-
import { ClientFactory
|
|
226
|
-
import { Message, MessageSendParams, Task } from '@a2a-js/sdk';
|
|
225
|
+
import { ClientFactory } from '@a2a-js/sdk/client';
|
|
226
|
+
import { Message, MessageSendParams, SendMessageSuccessResponse, Task } from '@a2a-js/sdk';
|
|
227
227
|
// ... other imports ...
|
|
228
228
|
|
|
229
229
|
const factory = new ClientFactory();
|
|
@@ -354,7 +354,7 @@ Here's how to use it to manage a Bearer token:
|
|
|
354
354
|
```typescript
|
|
355
355
|
import {
|
|
356
356
|
ClientFactory,
|
|
357
|
-
ClientFactoryOptions
|
|
357
|
+
ClientFactoryOptions,
|
|
358
358
|
JsonRpcTransportFactory,
|
|
359
359
|
AuthenticationHandler,
|
|
360
360
|
createAuthenticatingFetchWithRetry,
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
var A2A_ERROR_CODE = {
|
|
3
|
+
PARSE_ERROR: -32700,
|
|
4
|
+
INVALID_REQUEST: -32600,
|
|
5
|
+
METHOD_NOT_FOUND: -32601,
|
|
6
|
+
INVALID_PARAMS: -32602,
|
|
7
|
+
INTERNAL_ERROR: -32603,
|
|
8
|
+
TASK_NOT_FOUND: -32001,
|
|
9
|
+
TASK_NOT_CANCELABLE: -32002,
|
|
10
|
+
PUSH_NOTIFICATION_NOT_SUPPORTED: -32003,
|
|
11
|
+
UNSUPPORTED_OPERATION: -32004,
|
|
12
|
+
CONTENT_TYPE_NOT_SUPPORTED: -32005,
|
|
13
|
+
INVALID_AGENT_RESPONSE: -32006,
|
|
14
|
+
AUTHENTICATED_EXTENDED_CARD_NOT_CONFIGURED: -32007
|
|
15
|
+
};
|
|
16
|
+
var TaskNotFoundError = class extends Error {
|
|
17
|
+
constructor(message) {
|
|
18
|
+
super(message ?? "Task not found");
|
|
19
|
+
this.name = "TaskNotFoundError";
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
var TaskNotCancelableError = class extends Error {
|
|
23
|
+
constructor(message) {
|
|
24
|
+
super(message ?? "Task cannot be canceled");
|
|
25
|
+
this.name = "TaskNotCancelableError";
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
var PushNotificationNotSupportedError = class extends Error {
|
|
29
|
+
constructor(message) {
|
|
30
|
+
super(message ?? "Push Notification is not supported");
|
|
31
|
+
this.name = "PushNotificationNotSupportedError";
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
var UnsupportedOperationError = class extends Error {
|
|
35
|
+
constructor(message) {
|
|
36
|
+
super(message ?? "This operation is not supported");
|
|
37
|
+
this.name = "UnsupportedOperationError";
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
var ContentTypeNotSupportedError = class extends Error {
|
|
41
|
+
constructor(message) {
|
|
42
|
+
super(message ?? "Incompatible content types");
|
|
43
|
+
this.name = "ContentTypeNotSupportedError";
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
var InvalidAgentResponseError = class extends Error {
|
|
47
|
+
constructor(message) {
|
|
48
|
+
super(message ?? "Invalid agent response type");
|
|
49
|
+
this.name = "InvalidAgentResponseError";
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
var AuthenticatedExtendedCardNotConfiguredError = class extends Error {
|
|
53
|
+
constructor(message) {
|
|
54
|
+
super(message ?? "Authenticated Extended Card not configured");
|
|
55
|
+
this.name = "AuthenticatedExtendedCardNotConfiguredError";
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// src/sse_utils.ts
|
|
60
|
+
var SSE_HEADERS = {
|
|
61
|
+
"Content-Type": "text/event-stream",
|
|
62
|
+
"Cache-Control": "no-cache",
|
|
63
|
+
Connection: "keep-alive",
|
|
64
|
+
"X-Accel-Buffering": "no"
|
|
65
|
+
// Disable buffering in nginx
|
|
66
|
+
};
|
|
67
|
+
function formatSSEEvent(event) {
|
|
68
|
+
return `data: ${JSON.stringify(event)}
|
|
69
|
+
|
|
70
|
+
`;
|
|
71
|
+
}
|
|
72
|
+
function formatSSEErrorEvent(error) {
|
|
73
|
+
return `event: error
|
|
74
|
+
data: ${JSON.stringify(error)}
|
|
75
|
+
|
|
76
|
+
`;
|
|
77
|
+
}
|
|
78
|
+
async function* parseSseStream(response) {
|
|
79
|
+
if (!response.body) {
|
|
80
|
+
throw new Error("SSE response body is undefined. Cannot read stream.");
|
|
81
|
+
}
|
|
82
|
+
let buffer = "";
|
|
83
|
+
let eventType = "message";
|
|
84
|
+
let eventData = "";
|
|
85
|
+
for await (const value of response.body.pipeThrough(new TextDecoderStream())) {
|
|
86
|
+
buffer += value;
|
|
87
|
+
let lineEndIndex;
|
|
88
|
+
while ((lineEndIndex = buffer.indexOf("\n")) >= 0) {
|
|
89
|
+
const line = buffer.substring(0, lineEndIndex).trim();
|
|
90
|
+
buffer = buffer.substring(lineEndIndex + 1);
|
|
91
|
+
if (line === "") {
|
|
92
|
+
if (eventData) {
|
|
93
|
+
yield { type: eventType, data: eventData };
|
|
94
|
+
eventData = "";
|
|
95
|
+
eventType = "message";
|
|
96
|
+
}
|
|
97
|
+
} else if (line.startsWith("event:")) {
|
|
98
|
+
eventType = line.substring("event:".length).trim();
|
|
99
|
+
} else if (line.startsWith("data:")) {
|
|
100
|
+
eventData = line.substring("data:".length).trim();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (eventData) {
|
|
105
|
+
yield { type: eventType, data: eventData };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export {
|
|
110
|
+
A2A_ERROR_CODE,
|
|
111
|
+
TaskNotFoundError,
|
|
112
|
+
TaskNotCancelableError,
|
|
113
|
+
PushNotificationNotSupportedError,
|
|
114
|
+
UnsupportedOperationError,
|
|
115
|
+
ContentTypeNotSupportedError,
|
|
116
|
+
InvalidAgentResponseError,
|
|
117
|
+
AuthenticatedExtendedCardNotConfiguredError,
|
|
118
|
+
SSE_HEADERS,
|
|
119
|
+
formatSSEEvent,
|
|
120
|
+
formatSSEErrorEvent,
|
|
121
|
+
parseSseStream
|
|
122
|
+
};
|
package/dist/client/index.cjs
CHANGED
|
@@ -21,15 +21,24 @@ var client_exports = {};
|
|
|
21
21
|
__export(client_exports, {
|
|
22
22
|
A2AClient: () => A2AClient,
|
|
23
23
|
AgentCardResolver: () => AgentCardResolver,
|
|
24
|
+
AuthenticatedExtendedCardNotConfiguredError: () => AuthenticatedExtendedCardNotConfiguredError,
|
|
24
25
|
Client: () => Client,
|
|
25
26
|
ClientCallContext: () => ClientCallContext,
|
|
26
27
|
ClientCallContextKey: () => ClientCallContextKey,
|
|
27
28
|
ClientFactory: () => ClientFactory,
|
|
28
29
|
ClientFactoryOptions: () => ClientFactoryOptions,
|
|
30
|
+
ContentTypeNotSupportedError: () => ContentTypeNotSupportedError,
|
|
29
31
|
DefaultAgentCardResolver: () => DefaultAgentCardResolver,
|
|
32
|
+
InvalidAgentResponseError: () => InvalidAgentResponseError,
|
|
30
33
|
JsonRpcTransport: () => JsonRpcTransport,
|
|
31
34
|
JsonRpcTransportFactory: () => JsonRpcTransportFactory,
|
|
35
|
+
PushNotificationNotSupportedError: () => PushNotificationNotSupportedError,
|
|
36
|
+
RestTransport: () => RestTransport,
|
|
37
|
+
RestTransportFactory: () => RestTransportFactory,
|
|
32
38
|
ServiceParameters: () => ServiceParameters,
|
|
39
|
+
TaskNotCancelableError: () => TaskNotCancelableError,
|
|
40
|
+
TaskNotFoundError: () => TaskNotFoundError,
|
|
41
|
+
UnsupportedOperationError: () => UnsupportedOperationError,
|
|
33
42
|
createAuthenticatingFetchWithRetry: () => createAuthenticatingFetchWithRetry,
|
|
34
43
|
withA2AExtensions: () => withA2AExtensions
|
|
35
44
|
});
|
|
@@ -40,6 +49,20 @@ var AGENT_CARD_PATH = ".well-known/agent-card.json";
|
|
|
40
49
|
var HTTP_EXTENSION_HEADER = "X-A2A-Extensions";
|
|
41
50
|
|
|
42
51
|
// src/errors.ts
|
|
52
|
+
var A2A_ERROR_CODE = {
|
|
53
|
+
PARSE_ERROR: -32700,
|
|
54
|
+
INVALID_REQUEST: -32600,
|
|
55
|
+
METHOD_NOT_FOUND: -32601,
|
|
56
|
+
INVALID_PARAMS: -32602,
|
|
57
|
+
INTERNAL_ERROR: -32603,
|
|
58
|
+
TASK_NOT_FOUND: -32001,
|
|
59
|
+
TASK_NOT_CANCELABLE: -32002,
|
|
60
|
+
PUSH_NOTIFICATION_NOT_SUPPORTED: -32003,
|
|
61
|
+
UNSUPPORTED_OPERATION: -32004,
|
|
62
|
+
CONTENT_TYPE_NOT_SUPPORTED: -32005,
|
|
63
|
+
INVALID_AGENT_RESPONSE: -32006,
|
|
64
|
+
AUTHENTICATED_EXTENDED_CARD_NOT_CONFIGURED: -32007
|
|
65
|
+
};
|
|
43
66
|
var TaskNotFoundError = class extends Error {
|
|
44
67
|
constructor(message) {
|
|
45
68
|
super(message ?? "Task not found");
|
|
@@ -83,6 +106,38 @@ var AuthenticatedExtendedCardNotConfiguredError = class extends Error {
|
|
|
83
106
|
}
|
|
84
107
|
};
|
|
85
108
|
|
|
109
|
+
// src/sse_utils.ts
|
|
110
|
+
async function* parseSseStream(response) {
|
|
111
|
+
if (!response.body) {
|
|
112
|
+
throw new Error("SSE response body is undefined. Cannot read stream.");
|
|
113
|
+
}
|
|
114
|
+
let buffer = "";
|
|
115
|
+
let eventType = "message";
|
|
116
|
+
let eventData = "";
|
|
117
|
+
for await (const value of response.body.pipeThrough(new TextDecoderStream())) {
|
|
118
|
+
buffer += value;
|
|
119
|
+
let lineEndIndex;
|
|
120
|
+
while ((lineEndIndex = buffer.indexOf("\n")) >= 0) {
|
|
121
|
+
const line = buffer.substring(0, lineEndIndex).trim();
|
|
122
|
+
buffer = buffer.substring(lineEndIndex + 1);
|
|
123
|
+
if (line === "") {
|
|
124
|
+
if (eventData) {
|
|
125
|
+
yield { type: eventType, data: eventData };
|
|
126
|
+
eventData = "";
|
|
127
|
+
eventType = "message";
|
|
128
|
+
}
|
|
129
|
+
} else if (line.startsWith("event:")) {
|
|
130
|
+
eventType = line.substring("event:".length).trim();
|
|
131
|
+
} else if (line.startsWith("data:")) {
|
|
132
|
+
eventData = line.substring("data:".length).trim();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (eventData) {
|
|
137
|
+
yield { type: eventType, data: eventData };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
86
141
|
// src/client/transports/json_rpc_transport.ts
|
|
87
142
|
var JsonRpcTransport = class _JsonRpcTransport {
|
|
88
143
|
customFetchImpl;
|
|
@@ -251,55 +306,8 @@ var JsonRpcTransport = class _JsonRpcTransport {
|
|
|
251
306
|
`Invalid response Content-Type for SSE stream for ${method}. Expected 'text/event-stream'.`
|
|
252
307
|
);
|
|
253
308
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
async *_parseA2ASseStream(response, originalRequestId) {
|
|
257
|
-
if (!response.body) {
|
|
258
|
-
throw new Error("SSE response body is undefined. Cannot read stream.");
|
|
259
|
-
}
|
|
260
|
-
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
|
|
261
|
-
let buffer = "";
|
|
262
|
-
let eventDataBuffer = "";
|
|
263
|
-
try {
|
|
264
|
-
while (true) {
|
|
265
|
-
const { done, value } = await reader.read();
|
|
266
|
-
if (done) {
|
|
267
|
-
if (eventDataBuffer.trim()) {
|
|
268
|
-
const result = this._processSseEventData(
|
|
269
|
-
eventDataBuffer,
|
|
270
|
-
originalRequestId
|
|
271
|
-
);
|
|
272
|
-
yield result;
|
|
273
|
-
}
|
|
274
|
-
break;
|
|
275
|
-
}
|
|
276
|
-
buffer += value;
|
|
277
|
-
let lineEndIndex;
|
|
278
|
-
while ((lineEndIndex = buffer.indexOf("\n")) >= 0) {
|
|
279
|
-
const line = buffer.substring(0, lineEndIndex).trim();
|
|
280
|
-
buffer = buffer.substring(lineEndIndex + 1);
|
|
281
|
-
if (line === "") {
|
|
282
|
-
if (eventDataBuffer) {
|
|
283
|
-
const result = this._processSseEventData(
|
|
284
|
-
eventDataBuffer,
|
|
285
|
-
originalRequestId
|
|
286
|
-
);
|
|
287
|
-
yield result;
|
|
288
|
-
eventDataBuffer = "";
|
|
289
|
-
}
|
|
290
|
-
} else if (line.startsWith("data:")) {
|
|
291
|
-
eventDataBuffer += line.substring(5).trimStart() + "\n";
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
} catch (error) {
|
|
296
|
-
console.error(
|
|
297
|
-
"Error reading or parsing SSE stream:",
|
|
298
|
-
error instanceof Error && error.message || "Error unknown"
|
|
299
|
-
);
|
|
300
|
-
throw error;
|
|
301
|
-
} finally {
|
|
302
|
-
reader.releaseLock();
|
|
309
|
+
for await (const event of parseSseStream(response)) {
|
|
310
|
+
yield this._processSseEventData(event.data, clientRequestId);
|
|
303
311
|
}
|
|
304
312
|
}
|
|
305
313
|
_processSseEventData(jsonData, originalRequestId) {
|
|
@@ -307,7 +315,7 @@ var JsonRpcTransport = class _JsonRpcTransport {
|
|
|
307
315
|
throw new Error("Attempted to process empty SSE event data.");
|
|
308
316
|
}
|
|
309
317
|
try {
|
|
310
|
-
const sseJsonRpcResponse = JSON.parse(jsonData
|
|
318
|
+
const sseJsonRpcResponse = JSON.parse(jsonData);
|
|
311
319
|
const a2aStreamResponse = sseJsonRpcResponse;
|
|
312
320
|
if (a2aStreamResponse.id !== originalRequestId) {
|
|
313
321
|
console.warn(
|
|
@@ -1107,13 +1115,234 @@ var Client = class {
|
|
|
1107
1115
|
}
|
|
1108
1116
|
};
|
|
1109
1117
|
|
|
1118
|
+
// src/client/transports/rest_transport.ts
|
|
1119
|
+
var RestTransport = class _RestTransport {
|
|
1120
|
+
customFetchImpl;
|
|
1121
|
+
endpoint;
|
|
1122
|
+
constructor(options) {
|
|
1123
|
+
this.endpoint = options.endpoint.replace(/\/+$/, "");
|
|
1124
|
+
this.customFetchImpl = options.fetchImpl;
|
|
1125
|
+
}
|
|
1126
|
+
async getExtendedAgentCard(options) {
|
|
1127
|
+
return this._sendRequest("GET", "/v1/card", void 0, options);
|
|
1128
|
+
}
|
|
1129
|
+
async sendMessage(params, options) {
|
|
1130
|
+
return this._sendRequest("POST", "/v1/message:send", params, options);
|
|
1131
|
+
}
|
|
1132
|
+
async *sendMessageStream(params, options) {
|
|
1133
|
+
yield* this._sendStreamingRequest("/v1/message:stream", params, options);
|
|
1134
|
+
}
|
|
1135
|
+
async setTaskPushNotificationConfig(params, options) {
|
|
1136
|
+
return this._sendRequest(
|
|
1137
|
+
"POST",
|
|
1138
|
+
`/v1/tasks/${encodeURIComponent(params.taskId)}/pushNotificationConfigs`,
|
|
1139
|
+
{
|
|
1140
|
+
pushNotificationConfig: params.pushNotificationConfig
|
|
1141
|
+
},
|
|
1142
|
+
options
|
|
1143
|
+
);
|
|
1144
|
+
}
|
|
1145
|
+
async getTaskPushNotificationConfig(params, options) {
|
|
1146
|
+
const { pushNotificationConfigId } = params;
|
|
1147
|
+
if (!pushNotificationConfigId) {
|
|
1148
|
+
throw new Error(
|
|
1149
|
+
"pushNotificationConfigId is required for getTaskPushNotificationConfig with REST transport."
|
|
1150
|
+
);
|
|
1151
|
+
}
|
|
1152
|
+
return this._sendRequest(
|
|
1153
|
+
"GET",
|
|
1154
|
+
`/v1/tasks/${encodeURIComponent(params.id)}/pushNotificationConfigs/${encodeURIComponent(pushNotificationConfigId)}`,
|
|
1155
|
+
void 0,
|
|
1156
|
+
options
|
|
1157
|
+
);
|
|
1158
|
+
}
|
|
1159
|
+
async listTaskPushNotificationConfig(params, options) {
|
|
1160
|
+
return this._sendRequest(
|
|
1161
|
+
"GET",
|
|
1162
|
+
`/v1/tasks/${encodeURIComponent(params.id)}/pushNotificationConfigs`,
|
|
1163
|
+
void 0,
|
|
1164
|
+
options
|
|
1165
|
+
);
|
|
1166
|
+
}
|
|
1167
|
+
async deleteTaskPushNotificationConfig(params, options) {
|
|
1168
|
+
await this._sendRequest(
|
|
1169
|
+
"DELETE",
|
|
1170
|
+
`/v1/tasks/${encodeURIComponent(params.id)}/pushNotificationConfigs/${encodeURIComponent(params.pushNotificationConfigId)}`,
|
|
1171
|
+
void 0,
|
|
1172
|
+
options
|
|
1173
|
+
);
|
|
1174
|
+
}
|
|
1175
|
+
async getTask(params, options) {
|
|
1176
|
+
const queryParams = new URLSearchParams();
|
|
1177
|
+
if (params.historyLength !== void 0) {
|
|
1178
|
+
queryParams.set("historyLength", String(params.historyLength));
|
|
1179
|
+
}
|
|
1180
|
+
const queryString = queryParams.toString();
|
|
1181
|
+
const path = `/v1/tasks/${encodeURIComponent(params.id)}${queryString ? `?${queryString}` : ""}`;
|
|
1182
|
+
return this._sendRequest("GET", path, void 0, options);
|
|
1183
|
+
}
|
|
1184
|
+
async cancelTask(params, options) {
|
|
1185
|
+
return this._sendRequest(
|
|
1186
|
+
"POST",
|
|
1187
|
+
`/v1/tasks/${encodeURIComponent(params.id)}:cancel`,
|
|
1188
|
+
void 0,
|
|
1189
|
+
options
|
|
1190
|
+
);
|
|
1191
|
+
}
|
|
1192
|
+
async *resubscribeTask(params, options) {
|
|
1193
|
+
yield* this._sendStreamingRequest(
|
|
1194
|
+
`/v1/tasks/${encodeURIComponent(params.id)}:subscribe`,
|
|
1195
|
+
void 0,
|
|
1196
|
+
options
|
|
1197
|
+
);
|
|
1198
|
+
}
|
|
1199
|
+
_fetch(...args) {
|
|
1200
|
+
if (this.customFetchImpl) {
|
|
1201
|
+
return this.customFetchImpl(...args);
|
|
1202
|
+
}
|
|
1203
|
+
if (typeof fetch === "function") {
|
|
1204
|
+
return fetch(...args);
|
|
1205
|
+
}
|
|
1206
|
+
throw new Error(
|
|
1207
|
+
"A `fetch` implementation was not provided and is not available in the global scope. Please provide a `fetchImpl` in the RestTransportOptions."
|
|
1208
|
+
);
|
|
1209
|
+
}
|
|
1210
|
+
_buildHeaders(options, acceptHeader = "application/json") {
|
|
1211
|
+
return {
|
|
1212
|
+
...options?.serviceParameters,
|
|
1213
|
+
"Content-Type": "application/json",
|
|
1214
|
+
Accept: acceptHeader
|
|
1215
|
+
};
|
|
1216
|
+
}
|
|
1217
|
+
async _sendRequest(method, path, body, options) {
|
|
1218
|
+
const url = `${this.endpoint}${path}`;
|
|
1219
|
+
const requestInit = {
|
|
1220
|
+
method,
|
|
1221
|
+
headers: this._buildHeaders(options),
|
|
1222
|
+
signal: options?.signal
|
|
1223
|
+
};
|
|
1224
|
+
if (body !== void 0 && method !== "GET") {
|
|
1225
|
+
requestInit.body = JSON.stringify(body);
|
|
1226
|
+
}
|
|
1227
|
+
const response = await this._fetch(url, requestInit);
|
|
1228
|
+
if (!response.ok) {
|
|
1229
|
+
await this._handleErrorResponse(response, path);
|
|
1230
|
+
}
|
|
1231
|
+
if (response.status === 204) {
|
|
1232
|
+
return void 0;
|
|
1233
|
+
}
|
|
1234
|
+
const result = await response.json();
|
|
1235
|
+
return result;
|
|
1236
|
+
}
|
|
1237
|
+
async _handleErrorResponse(response, path) {
|
|
1238
|
+
let errorBodyText = "(empty or non-JSON response)";
|
|
1239
|
+
let errorBody;
|
|
1240
|
+
try {
|
|
1241
|
+
errorBodyText = await response.text();
|
|
1242
|
+
if (errorBodyText) {
|
|
1243
|
+
errorBody = JSON.parse(errorBodyText);
|
|
1244
|
+
}
|
|
1245
|
+
} catch (e) {
|
|
1246
|
+
throw new Error(
|
|
1247
|
+
`HTTP error for ${path}! Status: ${response.status} ${response.statusText}. Response: ${errorBodyText}`,
|
|
1248
|
+
{ cause: e }
|
|
1249
|
+
);
|
|
1250
|
+
}
|
|
1251
|
+
if (errorBody && typeof errorBody.code === "number") {
|
|
1252
|
+
throw _RestTransport.mapToError(errorBody);
|
|
1253
|
+
}
|
|
1254
|
+
throw new Error(
|
|
1255
|
+
`HTTP error for ${path}! Status: ${response.status} ${response.statusText}. Response: ${errorBodyText}`
|
|
1256
|
+
);
|
|
1257
|
+
}
|
|
1258
|
+
async *_sendStreamingRequest(path, body, options) {
|
|
1259
|
+
const url = `${this.endpoint}${path}`;
|
|
1260
|
+
const requestInit = {
|
|
1261
|
+
method: "POST",
|
|
1262
|
+
headers: this._buildHeaders(options, "text/event-stream"),
|
|
1263
|
+
signal: options?.signal
|
|
1264
|
+
};
|
|
1265
|
+
if (body !== void 0) {
|
|
1266
|
+
requestInit.body = JSON.stringify(body);
|
|
1267
|
+
}
|
|
1268
|
+
const response = await this._fetch(url, requestInit);
|
|
1269
|
+
if (!response.ok) {
|
|
1270
|
+
await this._handleErrorResponse(response, path);
|
|
1271
|
+
}
|
|
1272
|
+
const contentType = response.headers.get("Content-Type");
|
|
1273
|
+
if (!contentType?.startsWith("text/event-stream")) {
|
|
1274
|
+
throw new Error(
|
|
1275
|
+
`Invalid response Content-Type for SSE stream. Expected 'text/event-stream', got '${contentType}'.`
|
|
1276
|
+
);
|
|
1277
|
+
}
|
|
1278
|
+
for await (const event of parseSseStream(response)) {
|
|
1279
|
+
if (event.type === "error") {
|
|
1280
|
+
const errorData = JSON.parse(event.data);
|
|
1281
|
+
throw _RestTransport.mapToError(errorData);
|
|
1282
|
+
}
|
|
1283
|
+
yield this._processSseEventData(event.data);
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
_processSseEventData(jsonData) {
|
|
1287
|
+
if (!jsonData.trim()) {
|
|
1288
|
+
throw new Error("Attempted to process empty SSE event data.");
|
|
1289
|
+
}
|
|
1290
|
+
try {
|
|
1291
|
+
const data = JSON.parse(jsonData);
|
|
1292
|
+
return data;
|
|
1293
|
+
} catch (e) {
|
|
1294
|
+
console.error("Failed to parse SSE event data:", jsonData, e);
|
|
1295
|
+
throw new Error(
|
|
1296
|
+
`Failed to parse SSE event data: "${jsonData.substring(0, 100)}...". Original error: ${e instanceof Error && e.message || "Unknown error"}`
|
|
1297
|
+
);
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
static mapToError(error) {
|
|
1301
|
+
switch (error.code) {
|
|
1302
|
+
case A2A_ERROR_CODE.TASK_NOT_FOUND:
|
|
1303
|
+
return new TaskNotFoundError(error.message);
|
|
1304
|
+
case A2A_ERROR_CODE.TASK_NOT_CANCELABLE:
|
|
1305
|
+
return new TaskNotCancelableError(error.message);
|
|
1306
|
+
case A2A_ERROR_CODE.PUSH_NOTIFICATION_NOT_SUPPORTED:
|
|
1307
|
+
return new PushNotificationNotSupportedError(error.message);
|
|
1308
|
+
case A2A_ERROR_CODE.UNSUPPORTED_OPERATION:
|
|
1309
|
+
return new UnsupportedOperationError(error.message);
|
|
1310
|
+
case A2A_ERROR_CODE.CONTENT_TYPE_NOT_SUPPORTED:
|
|
1311
|
+
return new ContentTypeNotSupportedError(error.message);
|
|
1312
|
+
case A2A_ERROR_CODE.INVALID_AGENT_RESPONSE:
|
|
1313
|
+
return new InvalidAgentResponseError(error.message);
|
|
1314
|
+
case A2A_ERROR_CODE.AUTHENTICATED_EXTENDED_CARD_NOT_CONFIGURED:
|
|
1315
|
+
return new AuthenticatedExtendedCardNotConfiguredError(error.message);
|
|
1316
|
+
default:
|
|
1317
|
+
return new Error(
|
|
1318
|
+
`REST error: ${error.message} (Code: ${error.code})${error.data ? ` Data: ${JSON.stringify(error.data)}` : ""}`
|
|
1319
|
+
);
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
};
|
|
1323
|
+
var RestTransportFactory = class _RestTransportFactory {
|
|
1324
|
+
constructor(options) {
|
|
1325
|
+
this.options = options;
|
|
1326
|
+
}
|
|
1327
|
+
static name = "HTTP+JSON";
|
|
1328
|
+
get protocolName() {
|
|
1329
|
+
return _RestTransportFactory.name;
|
|
1330
|
+
}
|
|
1331
|
+
async create(url, _agentCard) {
|
|
1332
|
+
return new RestTransport({
|
|
1333
|
+
endpoint: url,
|
|
1334
|
+
fetchImpl: this.options?.fetchImpl
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1337
|
+
};
|
|
1338
|
+
|
|
1110
1339
|
// src/client/factory.ts
|
|
1111
1340
|
var ClientFactoryOptions = {
|
|
1112
1341
|
/**
|
|
1113
1342
|
* SDK default options for {@link ClientFactory}.
|
|
1114
1343
|
*/
|
|
1115
1344
|
default: {
|
|
1116
|
-
transports: [new JsonRpcTransportFactory()]
|
|
1345
|
+
transports: [new JsonRpcTransportFactory(), new RestTransportFactory()]
|
|
1117
1346
|
},
|
|
1118
1347
|
/**
|
|
1119
1348
|
* Creates new options by merging an original and an override object.
|
|
@@ -1337,15 +1566,24 @@ var ClientCallContextKey = class {
|
|
|
1337
1566
|
0 && (module.exports = {
|
|
1338
1567
|
A2AClient,
|
|
1339
1568
|
AgentCardResolver,
|
|
1569
|
+
AuthenticatedExtendedCardNotConfiguredError,
|
|
1340
1570
|
Client,
|
|
1341
1571
|
ClientCallContext,
|
|
1342
1572
|
ClientCallContextKey,
|
|
1343
1573
|
ClientFactory,
|
|
1344
1574
|
ClientFactoryOptions,
|
|
1575
|
+
ContentTypeNotSupportedError,
|
|
1345
1576
|
DefaultAgentCardResolver,
|
|
1577
|
+
InvalidAgentResponseError,
|
|
1346
1578
|
JsonRpcTransport,
|
|
1347
1579
|
JsonRpcTransportFactory,
|
|
1580
|
+
PushNotificationNotSupportedError,
|
|
1581
|
+
RestTransport,
|
|
1582
|
+
RestTransportFactory,
|
|
1348
1583
|
ServiceParameters,
|
|
1584
|
+
TaskNotCancelableError,
|
|
1585
|
+
TaskNotFoundError,
|
|
1586
|
+
UnsupportedOperationError,
|
|
1349
1587
|
createAuthenticatingFetchWithRetry,
|
|
1350
1588
|
withA2AExtensions
|
|
1351
1589
|
});
|
package/dist/client/index.d.cts
CHANGED
|
@@ -566,6 +566,28 @@ declare class ClientFactory {
|
|
|
566
566
|
createFromUrl(baseUrl: string, path?: string): Promise<Client>;
|
|
567
567
|
}
|
|
568
568
|
|
|
569
|
+
declare class TaskNotFoundError extends Error {
|
|
570
|
+
constructor(message?: string);
|
|
571
|
+
}
|
|
572
|
+
declare class TaskNotCancelableError extends Error {
|
|
573
|
+
constructor(message?: string);
|
|
574
|
+
}
|
|
575
|
+
declare class PushNotificationNotSupportedError extends Error {
|
|
576
|
+
constructor(message?: string);
|
|
577
|
+
}
|
|
578
|
+
declare class UnsupportedOperationError extends Error {
|
|
579
|
+
constructor(message?: string);
|
|
580
|
+
}
|
|
581
|
+
declare class ContentTypeNotSupportedError extends Error {
|
|
582
|
+
constructor(message?: string);
|
|
583
|
+
}
|
|
584
|
+
declare class InvalidAgentResponseError extends Error {
|
|
585
|
+
constructor(message?: string);
|
|
586
|
+
}
|
|
587
|
+
declare class AuthenticatedExtendedCardNotConfiguredError extends Error {
|
|
588
|
+
constructor(message?: string);
|
|
589
|
+
}
|
|
590
|
+
|
|
569
591
|
interface JsonRpcTransportOptions {
|
|
570
592
|
endpoint: string;
|
|
571
593
|
fetchImpl?: typeof fetch;
|
|
@@ -590,7 +612,6 @@ declare class JsonRpcTransport implements Transport {
|
|
|
590
612
|
private _sendRpcRequest;
|
|
591
613
|
private _fetchRpc;
|
|
592
614
|
private _sendStreamingRequest;
|
|
593
|
-
private _parseA2ASseStream;
|
|
594
615
|
private _processSseEventData;
|
|
595
616
|
private static mapToError;
|
|
596
617
|
}
|
|
@@ -605,4 +626,41 @@ declare class JsonRpcTransportFactory implements TransportFactory {
|
|
|
605
626
|
create(url: string, _agentCard: AgentCard): Promise<Transport>;
|
|
606
627
|
}
|
|
607
628
|
|
|
608
|
-
|
|
629
|
+
interface RestTransportOptions {
|
|
630
|
+
endpoint: string;
|
|
631
|
+
fetchImpl?: typeof fetch;
|
|
632
|
+
}
|
|
633
|
+
declare class RestTransport implements Transport {
|
|
634
|
+
private readonly customFetchImpl?;
|
|
635
|
+
private readonly endpoint;
|
|
636
|
+
constructor(options: RestTransportOptions);
|
|
637
|
+
getExtendedAgentCard(options?: RequestOptions): Promise<AgentCard>;
|
|
638
|
+
sendMessage(params: MessageSendParams, options?: RequestOptions): Promise<SendMessageResult>;
|
|
639
|
+
sendMessageStream(params: MessageSendParams, options?: RequestOptions): AsyncGenerator<A2AStreamEventData, void, undefined>;
|
|
640
|
+
setTaskPushNotificationConfig(params: TaskPushNotificationConfig, options?: RequestOptions): Promise<TaskPushNotificationConfig>;
|
|
641
|
+
getTaskPushNotificationConfig(params: GetTaskPushNotificationConfigParams, options?: RequestOptions): Promise<TaskPushNotificationConfig>;
|
|
642
|
+
listTaskPushNotificationConfig(params: ListTaskPushNotificationConfigParams, options?: RequestOptions): Promise<TaskPushNotificationConfig[]>;
|
|
643
|
+
deleteTaskPushNotificationConfig(params: DeleteTaskPushNotificationConfigParams, options?: RequestOptions): Promise<void>;
|
|
644
|
+
getTask(params: TaskQueryParams, options?: RequestOptions): Promise<Task>;
|
|
645
|
+
cancelTask(params: TaskIdParams, options?: RequestOptions): Promise<Task>;
|
|
646
|
+
resubscribeTask(params: TaskIdParams, options?: RequestOptions): AsyncGenerator<A2AStreamEventData, void, undefined>;
|
|
647
|
+
private _fetch;
|
|
648
|
+
private _buildHeaders;
|
|
649
|
+
private _sendRequest;
|
|
650
|
+
private _handleErrorResponse;
|
|
651
|
+
private _sendStreamingRequest;
|
|
652
|
+
private _processSseEventData;
|
|
653
|
+
private static mapToError;
|
|
654
|
+
}
|
|
655
|
+
interface RestTransportFactoryOptions {
|
|
656
|
+
fetchImpl?: typeof fetch;
|
|
657
|
+
}
|
|
658
|
+
declare class RestTransportFactory implements TransportFactory {
|
|
659
|
+
private readonly options?;
|
|
660
|
+
static readonly name: TransportProtocolName;
|
|
661
|
+
constructor(options?: RestTransportFactoryOptions);
|
|
662
|
+
get protocolName(): string;
|
|
663
|
+
create(url: string, _agentCard: AgentCard): Promise<Transport>;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
export { A2AClient, type A2AClientOptions, type AfterArgs, AgentCardResolver, type AgentCardResolverOptions, AuthenticatedExtendedCardNotConfiguredError, type AuthenticationHandler, type BeforeArgs, type CallInterceptor, Client, ClientCallContext, ClientCallContextKey, type ClientCallInput, type ClientCallResult, type ClientConfig, ClientFactory, ClientFactoryOptions, ContentTypeNotSupportedError, type ContextUpdate, DefaultAgentCardResolver, type HttpHeaders, InvalidAgentResponseError, JsonRpcTransport, JsonRpcTransportFactory, type JsonRpcTransportOptions, PushNotificationNotSupportedError, type RequestOptions, RestTransport, RestTransportFactory, type RestTransportOptions, ServiceParameters, type ServiceParametersUpdate, TaskNotCancelableError, TaskNotFoundError, type Transport, type TransportFactory, UnsupportedOperationError, createAuthenticatingFetchWithRetry, withA2AExtensions };
|