@a2a-js/sdk 0.3.2 → 0.3.4
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 +506 -314
- package/dist/client/index.cjs +171 -71
- package/dist/client/index.d.cts +67 -34
- package/dist/client/index.d.ts +67 -34
- package/dist/client/index.js +171 -71
- package/dist/server/index.cjs +136 -19
- package/dist/server/index.d.cts +40 -4
- package/dist/server/index.d.ts +40 -4
- package/dist/server/index.js +134 -19
- package/package.json +4 -4
package/dist/client/index.js
CHANGED
|
@@ -3,94 +3,80 @@ import {
|
|
|
3
3
|
} from "../chunk-67JNQ6TZ.js";
|
|
4
4
|
|
|
5
5
|
// src/client/client.ts
|
|
6
|
-
var A2AClient = class {
|
|
6
|
+
var A2AClient = class _A2AClient {
|
|
7
7
|
agentCardPromise;
|
|
8
8
|
requestIdCounter = 1;
|
|
9
9
|
serviceEndpointUrl;
|
|
10
10
|
// To be populated from AgentCard after fetching
|
|
11
|
-
|
|
11
|
+
customFetchImpl;
|
|
12
12
|
/**
|
|
13
|
-
* Constructs an A2AClient instance.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* The `url` field from the Agent Card will be used as the RPC service endpoint.
|
|
17
|
-
* @param agentBaseUrl The base URL of the A2A agent (e.g., https://agent.example.com)
|
|
18
|
-
* @param options Optional. The options for the A2AClient including the fetch implementation, agent card path, and authentication handler.
|
|
19
|
-
*/
|
|
20
|
-
constructor(agentBaseUrl, options) {
|
|
21
|
-
this.fetchImpl = options?.fetchImpl ?? fetch;
|
|
22
|
-
this.agentCardPromise = this._fetchAndCacheAgentCard(agentBaseUrl, options?.agentCardPath);
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Fetches the Agent Card from the agent's well-known URI and caches its service endpoint URL.
|
|
26
|
-
* This method is called by the constructor.
|
|
27
|
-
* @param agentBaseUrl The base URL of the A2A agent (e.g., https://agent.example.com)
|
|
28
|
-
* @param agentCardPath path to the agent card, defaults to .well-known/agent-card.json
|
|
29
|
-
* @returns A Promise that resolves to the AgentCard.
|
|
13
|
+
* Constructs an A2AClient instance from an AgentCard.
|
|
14
|
+
* @param agentCard The AgentCard object.
|
|
15
|
+
* @param options Optional. The options for the A2AClient including the fetch/auth implementation.
|
|
30
16
|
*/
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (!response.ok) {
|
|
38
|
-
throw new Error(`Failed to fetch Agent Card from ${agentCardUrl}: ${response.status} ${response.statusText}`);
|
|
39
|
-
}
|
|
40
|
-
const agentCard = await response.json();
|
|
17
|
+
constructor(agentCard, options) {
|
|
18
|
+
this.customFetchImpl = options?.fetchImpl;
|
|
19
|
+
if (typeof agentCard === "string") {
|
|
20
|
+
console.warn("Warning: Constructing A2AClient with a URL is deprecated. Please use A2AClient.fromCardUrl() instead.");
|
|
21
|
+
this.agentCardPromise = this._fetchAndCacheAgentCard(agentCard, options?.agentCardPath);
|
|
22
|
+
} else {
|
|
41
23
|
if (!agentCard.url) {
|
|
42
|
-
throw new Error("
|
|
24
|
+
throw new Error("Provided Agent Card does not contain a valid 'url' for the service endpoint.");
|
|
43
25
|
}
|
|
44
26
|
this.serviceEndpointUrl = agentCard.url;
|
|
45
|
-
|
|
46
|
-
} catch (error) {
|
|
47
|
-
console.error("Error fetching or parsing Agent Card:", error);
|
|
48
|
-
throw error;
|
|
27
|
+
this.agentCardPromise = Promise.resolve(agentCard);
|
|
49
28
|
}
|
|
50
29
|
}
|
|
51
30
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* @param
|
|
56
|
-
* @
|
|
57
|
-
* If provided, this will fetch a new card, not use the cached one from the constructor's URL.
|
|
58
|
-
* @returns A Promise that resolves to the AgentCard.
|
|
31
|
+
* Dynamically resolves the fetch implementation to use for requests.
|
|
32
|
+
* Prefers a custom implementation if provided, otherwise falls back to the global fetch.
|
|
33
|
+
* @returns The fetch implementation.
|
|
34
|
+
* @param args Arguments to pass to the fetch implementation.
|
|
35
|
+
* @throws If no fetch implementation is available.
|
|
59
36
|
*/
|
|
60
|
-
|
|
61
|
-
if (
|
|
62
|
-
|
|
63
|
-
const response = await this.fetchImpl(agentCardUrl, {
|
|
64
|
-
headers: { "Accept": "application/json" }
|
|
65
|
-
});
|
|
66
|
-
if (!response.ok) {
|
|
67
|
-
throw new Error(`Failed to fetch Agent Card from ${agentCardUrl}: ${response.status} ${response.statusText}`);
|
|
68
|
-
}
|
|
69
|
-
return await response.json();
|
|
37
|
+
_fetch(...args) {
|
|
38
|
+
if (this.customFetchImpl) {
|
|
39
|
+
return this.customFetchImpl(...args);
|
|
70
40
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
*/
|
|
78
|
-
resolveAgentCardUrl(agentBaseUrl, agentCardPath = AGENT_CARD_PATH) {
|
|
79
|
-
return `${agentBaseUrl.replace(/\/$/, "")}/${agentCardPath.replace(/^\//, "")}`;
|
|
41
|
+
if (typeof fetch === "function") {
|
|
42
|
+
return fetch(...args);
|
|
43
|
+
}
|
|
44
|
+
throw new Error(
|
|
45
|
+
"A `fetch` implementation was not provided and is not available in the global scope. Please provide a `fetchImpl` in the A2AClientOptions. For earlier Node.js versions (pre-v18), you can use a library like `node-fetch`."
|
|
46
|
+
);
|
|
80
47
|
}
|
|
81
48
|
/**
|
|
82
|
-
*
|
|
83
|
-
* @
|
|
49
|
+
* Creates an A2AClient instance by fetching the AgentCard from a URL then constructing the A2AClient.
|
|
50
|
+
* @param agentCardUrl The URL of the agent card.
|
|
51
|
+
* @param options Optional. The options for the A2AClient including the fetch/auth implementation.
|
|
52
|
+
* @returns A Promise that resolves to a new A2AClient instance.
|
|
84
53
|
*/
|
|
85
|
-
async
|
|
86
|
-
|
|
87
|
-
|
|
54
|
+
static async fromCardUrl(agentCardUrl, options) {
|
|
55
|
+
const fetchImpl = options?.fetchImpl;
|
|
56
|
+
const requestInit = {
|
|
57
|
+
headers: { "Accept": "application/json" }
|
|
58
|
+
};
|
|
59
|
+
let response;
|
|
60
|
+
if (fetchImpl) {
|
|
61
|
+
response = await fetchImpl(agentCardUrl, requestInit);
|
|
62
|
+
} else if (typeof fetch === "function") {
|
|
63
|
+
response = await fetch(agentCardUrl, requestInit);
|
|
64
|
+
} else {
|
|
65
|
+
throw new Error(
|
|
66
|
+
"A `fetch` implementation was not provided and is not available in the global scope. Please provide a `fetchImpl` in the A2AClientOptions. For earlier Node.js versions (pre-v18), you can use a library like `node-fetch`."
|
|
67
|
+
);
|
|
88
68
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
throw new Error("Agent Card URL for RPC endpoint is not available. Fetching might have failed.");
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
throw new Error(`Failed to fetch Agent Card from ${agentCardUrl}: ${response.status} ${response.statusText}`);
|
|
92
71
|
}
|
|
93
|
-
|
|
72
|
+
let agentCard;
|
|
73
|
+
try {
|
|
74
|
+
agentCard = await response.json();
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error("Failed to parse Agent Card JSON:", error);
|
|
77
|
+
throw new Error(`Failed to parse Agent Card JSON from ${agentCardUrl}. Original error: ${error.message}`);
|
|
78
|
+
}
|
|
79
|
+
return new _A2AClient(agentCard, options);
|
|
94
80
|
}
|
|
95
81
|
/**
|
|
96
82
|
* Helper method to make a generic JSON-RPC POST request.
|
|
@@ -149,7 +135,7 @@ var A2AClient = class {
|
|
|
149
135
|
},
|
|
150
136
|
body: JSON.stringify(rpcRequest)
|
|
151
137
|
};
|
|
152
|
-
return this.
|
|
138
|
+
return this._fetch(url, requestInit);
|
|
153
139
|
}
|
|
154
140
|
/**
|
|
155
141
|
* Sends a message to the agent.
|
|
@@ -232,6 +218,28 @@ var A2AClient = class {
|
|
|
232
218
|
params
|
|
233
219
|
);
|
|
234
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* Lists the push notification configurations for a given task.
|
|
223
|
+
* @param params Parameters containing the taskId.
|
|
224
|
+
* @returns A Promise resolving to ListTaskPushNotificationConfigResponse.
|
|
225
|
+
*/
|
|
226
|
+
async listTaskPushNotificationConfig(params) {
|
|
227
|
+
return this._postRpcRequest(
|
|
228
|
+
"tasks/pushNotificationConfig/list",
|
|
229
|
+
params
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Deletes the push notification configuration for a given task.
|
|
234
|
+
* @param params Parameters containing the taskId and push notification configuration ID.
|
|
235
|
+
* @returns A Promise resolving to DeleteTaskPushNotificationConfigResponse.
|
|
236
|
+
*/
|
|
237
|
+
async deleteTaskPushNotificationConfig(params) {
|
|
238
|
+
return this._postRpcRequest(
|
|
239
|
+
"tasks/pushNotificationConfig/delete",
|
|
240
|
+
params
|
|
241
|
+
);
|
|
242
|
+
}
|
|
235
243
|
/**
|
|
236
244
|
* Retrieves a task by its ID.
|
|
237
245
|
* @param params Parameters containing the taskId and optional historyLength.
|
|
@@ -248,6 +256,17 @@ var A2AClient = class {
|
|
|
248
256
|
async cancelTask(params) {
|
|
249
257
|
return this._postRpcRequest("tasks/cancel", params);
|
|
250
258
|
}
|
|
259
|
+
/**
|
|
260
|
+
* @template TExtensionParams The type of parameters for the custom extension method.
|
|
261
|
+
* @template TExtensionResponse The type of response expected from the custom extension method.
|
|
262
|
+
* This should extend JSONRPCResponse. This ensures the extension response is still a valid A2A response.
|
|
263
|
+
* @param method Custom JSON-RPC method defined in the AgentCard's extensions.
|
|
264
|
+
* @param params Extension paramters defined in the AgentCard's extensions.
|
|
265
|
+
* @returns A Promise that resolves to the RPC response.
|
|
266
|
+
*/
|
|
267
|
+
async callExtensionMethod(method, params) {
|
|
268
|
+
return this._postRpcRequest(method, params);
|
|
269
|
+
}
|
|
251
270
|
/**
|
|
252
271
|
* Resubscribes to a task's event stream using Server-Sent Events (SSE).
|
|
253
272
|
* This is used if a previous SSE connection for an active task was broken.
|
|
@@ -269,7 +288,7 @@ var A2AClient = class {
|
|
|
269
288
|
params,
|
|
270
289
|
id: clientRequestId
|
|
271
290
|
};
|
|
272
|
-
const response = await this.
|
|
291
|
+
const response = await this._fetch(endpoint, {
|
|
273
292
|
method: "POST",
|
|
274
293
|
headers: {
|
|
275
294
|
"Content-Type": "application/json",
|
|
@@ -384,6 +403,87 @@ var A2AClient = class {
|
|
|
384
403
|
isErrorResponse(response) {
|
|
385
404
|
return "error" in response;
|
|
386
405
|
}
|
|
406
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
407
|
+
// Functions used to support old A2AClient Constructor to be deprecated soon
|
|
408
|
+
// TODOs:
|
|
409
|
+
// * remove `agentCardPromise`, and just use agentCard initialized
|
|
410
|
+
// * _getServiceEndpoint can be made synchronous or deleted and accessed via
|
|
411
|
+
// agentCard.url
|
|
412
|
+
// * getAgentCard changed to this.agentCard
|
|
413
|
+
// * delete resolveAgentCardUrl(), _fetchAndCacheAgentCard(),
|
|
414
|
+
// agentCardPath from A2AClientOptions
|
|
415
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
416
|
+
/**
|
|
417
|
+
* Fetches the Agent Card from the agent's well-known URI and caches its service endpoint URL.
|
|
418
|
+
* This method is called by the constructor.
|
|
419
|
+
* @param agentBaseUrl The base URL of the A2A agent (e.g., https://agent.example.com)
|
|
420
|
+
* @param agentCardPath path to the agent card, defaults to .well-known/agent-card.json
|
|
421
|
+
* @returns A Promise that resolves to the AgentCard.
|
|
422
|
+
*/
|
|
423
|
+
async _fetchAndCacheAgentCard(agentBaseUrl, agentCardPath) {
|
|
424
|
+
try {
|
|
425
|
+
const agentCardUrl = this.resolveAgentCardUrl(agentBaseUrl, agentCardPath);
|
|
426
|
+
const response = await this._fetch(agentCardUrl, {
|
|
427
|
+
headers: { "Accept": "application/json" }
|
|
428
|
+
});
|
|
429
|
+
if (!response.ok) {
|
|
430
|
+
throw new Error(`Failed to fetch Agent Card from ${agentCardUrl}: ${response.status} ${response.statusText}`);
|
|
431
|
+
}
|
|
432
|
+
const agentCard = await response.json();
|
|
433
|
+
if (!agentCard.url) {
|
|
434
|
+
throw new Error("Fetched Agent Card does not contain a valid 'url' for the service endpoint.");
|
|
435
|
+
}
|
|
436
|
+
this.serviceEndpointUrl = agentCard.url;
|
|
437
|
+
return agentCard;
|
|
438
|
+
} catch (error) {
|
|
439
|
+
console.error("Error fetching or parsing Agent Card:", error);
|
|
440
|
+
throw error;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Retrieves the Agent Card.
|
|
445
|
+
* If an `agentBaseUrl` is provided, it fetches the card from that specific URL.
|
|
446
|
+
* Otherwise, it returns the card fetched and cached during client construction.
|
|
447
|
+
* @param agentBaseUrl Optional. The base URL of the agent to fetch the card from.
|
|
448
|
+
* @param agentCardPath path to the agent card, defaults to .well-known/agent-card.json
|
|
449
|
+
* If provided, this will fetch a new card, not use the cached one from the constructor's URL.
|
|
450
|
+
* @returns A Promise that resolves to the AgentCard.
|
|
451
|
+
*/
|
|
452
|
+
async getAgentCard(agentBaseUrl, agentCardPath) {
|
|
453
|
+
if (agentBaseUrl) {
|
|
454
|
+
const agentCardUrl = this.resolveAgentCardUrl(agentBaseUrl, agentCardPath);
|
|
455
|
+
const response = await this._fetch(agentCardUrl, {
|
|
456
|
+
headers: { "Accept": "application/json" }
|
|
457
|
+
});
|
|
458
|
+
if (!response.ok) {
|
|
459
|
+
throw new Error(`Failed to fetch Agent Card from ${agentCardUrl}: ${response.status} ${response.statusText}`);
|
|
460
|
+
}
|
|
461
|
+
return await response.json();
|
|
462
|
+
}
|
|
463
|
+
return this.agentCardPromise;
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Determines the agent card URL based on the agent URL.
|
|
467
|
+
* @param agentBaseUrl The agent URL.
|
|
468
|
+
* @param agentCardPath Optional relative path to the agent card, defaults to .well-known/agent-card.json
|
|
469
|
+
*/
|
|
470
|
+
resolveAgentCardUrl(agentBaseUrl, agentCardPath = AGENT_CARD_PATH) {
|
|
471
|
+
return `${agentBaseUrl.replace(/\/$/, "")}/${agentCardPath.replace(/^\//, "")}`;
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Gets the RPC service endpoint URL. Ensures the agent card has been fetched first.
|
|
475
|
+
* @returns A Promise that resolves to the service endpoint URL string.
|
|
476
|
+
*/
|
|
477
|
+
async _getServiceEndpoint() {
|
|
478
|
+
if (this.serviceEndpointUrl) {
|
|
479
|
+
return this.serviceEndpointUrl;
|
|
480
|
+
}
|
|
481
|
+
await this.agentCardPromise;
|
|
482
|
+
if (!this.serviceEndpointUrl) {
|
|
483
|
+
throw new Error("Agent Card URL for RPC endpoint is not available. Fetching might have failed.");
|
|
484
|
+
}
|
|
485
|
+
return this.serviceEndpointUrl;
|
|
486
|
+
}
|
|
387
487
|
};
|
|
388
488
|
|
|
389
489
|
// src/client/auth-handler.ts
|
package/dist/server/index.cjs
CHANGED
|
@@ -22,8 +22,10 @@ __export(server_exports, {
|
|
|
22
22
|
A2AError: () => A2AError,
|
|
23
23
|
DefaultExecutionEventBus: () => DefaultExecutionEventBus,
|
|
24
24
|
DefaultExecutionEventBusManager: () => DefaultExecutionEventBusManager,
|
|
25
|
+
DefaultPushNotificationSender: () => DefaultPushNotificationSender,
|
|
25
26
|
DefaultRequestHandler: () => DefaultRequestHandler,
|
|
26
27
|
ExecutionEventQueue: () => ExecutionEventQueue,
|
|
28
|
+
InMemoryPushNotificationStore: () => InMemoryPushNotificationStore,
|
|
27
29
|
InMemoryTaskStore: () => InMemoryTaskStore,
|
|
28
30
|
JsonRpcTransportHandler: () => JsonRpcTransportHandler,
|
|
29
31
|
RequestContext: () => RequestContext,
|
|
@@ -366,6 +368,97 @@ var ResultManager = class {
|
|
|
366
368
|
}
|
|
367
369
|
};
|
|
368
370
|
|
|
371
|
+
// src/server/push_notification/push_notification_store.ts
|
|
372
|
+
var InMemoryPushNotificationStore = class {
|
|
373
|
+
store = /* @__PURE__ */ new Map();
|
|
374
|
+
async save(taskId, pushNotificationConfig) {
|
|
375
|
+
const configs = this.store.get(taskId) || [];
|
|
376
|
+
if (!pushNotificationConfig.id) {
|
|
377
|
+
pushNotificationConfig.id = taskId;
|
|
378
|
+
}
|
|
379
|
+
const existingIndex = configs.findIndex((config) => config.id === pushNotificationConfig.id);
|
|
380
|
+
if (existingIndex !== -1) {
|
|
381
|
+
configs.splice(existingIndex, 1);
|
|
382
|
+
}
|
|
383
|
+
configs.push(pushNotificationConfig);
|
|
384
|
+
this.store.set(taskId, configs);
|
|
385
|
+
}
|
|
386
|
+
async load(taskId) {
|
|
387
|
+
const configs = this.store.get(taskId);
|
|
388
|
+
return configs || [];
|
|
389
|
+
}
|
|
390
|
+
async delete(taskId, configId) {
|
|
391
|
+
if (configId === void 0) {
|
|
392
|
+
configId = taskId;
|
|
393
|
+
}
|
|
394
|
+
const configs = this.store.get(taskId);
|
|
395
|
+
if (!configs) {
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
const configIndex = configs.findIndex((config) => config.id === configId);
|
|
399
|
+
if (configIndex !== -1) {
|
|
400
|
+
configs.splice(configIndex, 1);
|
|
401
|
+
}
|
|
402
|
+
if (configs.length === 0) {
|
|
403
|
+
this.store.delete(taskId);
|
|
404
|
+
} else {
|
|
405
|
+
this.store.set(taskId, configs);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
// src/server/push_notification/default_push_notification_sender.ts
|
|
411
|
+
var DefaultPushNotificationSender = class {
|
|
412
|
+
pushNotificationStore;
|
|
413
|
+
options;
|
|
414
|
+
constructor(pushNotificationStore, options = {}) {
|
|
415
|
+
this.pushNotificationStore = pushNotificationStore;
|
|
416
|
+
this.options = {
|
|
417
|
+
timeout: 5e3,
|
|
418
|
+
tokenHeaderName: "X-A2A-Notification-Token",
|
|
419
|
+
...options
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
async send(task) {
|
|
423
|
+
const pushConfigs = await this.pushNotificationStore.load(task.id);
|
|
424
|
+
if (!pushConfigs || pushConfigs.length === 0) {
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
pushConfigs.forEach((pushConfig) => {
|
|
428
|
+
this._dispatchNotification(task, pushConfig).catch((error) => {
|
|
429
|
+
console.error(`Error sending push notification for task_id=${task.id} to URL: ${pushConfig.url}. Error:`, error);
|
|
430
|
+
});
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
async _dispatchNotification(task, pushConfig) {
|
|
434
|
+
const url = pushConfig.url;
|
|
435
|
+
const controller = new AbortController();
|
|
436
|
+
const timeoutId = setTimeout(() => controller.abort(), this.options.timeout);
|
|
437
|
+
try {
|
|
438
|
+
const headers = {
|
|
439
|
+
"Content-Type": "application/json"
|
|
440
|
+
};
|
|
441
|
+
if (pushConfig.token) {
|
|
442
|
+
headers[this.options.tokenHeaderName] = pushConfig.token;
|
|
443
|
+
}
|
|
444
|
+
const response = await fetch(url, {
|
|
445
|
+
method: "POST",
|
|
446
|
+
headers,
|
|
447
|
+
body: JSON.stringify(task),
|
|
448
|
+
signal: controller.signal
|
|
449
|
+
});
|
|
450
|
+
if (!response.ok) {
|
|
451
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
452
|
+
}
|
|
453
|
+
console.info(`Push notification sent for task_id=${task.id} to URL: ${url}`);
|
|
454
|
+
} catch (error) {
|
|
455
|
+
console.error(`Error sending push notification for task_id=${task.id} to URL: ${url}. Error:`, error);
|
|
456
|
+
} finally {
|
|
457
|
+
clearTimeout(timeoutId);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
|
|
369
462
|
// src/server/request_handler/default_request_handler.ts
|
|
370
463
|
var terminalStates = ["completed", "failed", "canceled", "rejected"];
|
|
371
464
|
var DefaultRequestHandler = class {
|
|
@@ -374,14 +467,18 @@ var DefaultRequestHandler = class {
|
|
|
374
467
|
taskStore;
|
|
375
468
|
agentExecutor;
|
|
376
469
|
eventBusManager;
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
constructor(agentCard, taskStore, agentExecutor, eventBusManager = new DefaultExecutionEventBusManager(), extendedAgentCard) {
|
|
470
|
+
pushNotificationStore;
|
|
471
|
+
pushNotificationSender;
|
|
472
|
+
constructor(agentCard, taskStore, agentExecutor, eventBusManager = new DefaultExecutionEventBusManager(), pushNotificationStore, pushNotificationSender, extendedAgentCard) {
|
|
380
473
|
this.agentCard = agentCard;
|
|
381
474
|
this.taskStore = taskStore;
|
|
382
475
|
this.agentExecutor = agentExecutor;
|
|
383
476
|
this.eventBusManager = eventBusManager;
|
|
384
477
|
this.extendedAgentCard = extendedAgentCard;
|
|
478
|
+
if (agentCard.capabilities.pushNotifications) {
|
|
479
|
+
this.pushNotificationStore = pushNotificationStore || new InMemoryPushNotificationStore();
|
|
480
|
+
this.pushNotificationSender = pushNotificationSender || new DefaultPushNotificationSender(this.pushNotificationStore);
|
|
481
|
+
}
|
|
385
482
|
}
|
|
386
483
|
async getAgentCard() {
|
|
387
484
|
return this.agentCard;
|
|
@@ -433,6 +530,7 @@ var DefaultRequestHandler = class {
|
|
|
433
530
|
try {
|
|
434
531
|
for await (const event of eventQueue.events()) {
|
|
435
532
|
await resultManager.processEvent(event);
|
|
533
|
+
await this._sendPushNotificationIfNeeded(event);
|
|
436
534
|
if (options?.firstResultResolver && !firstResultSent) {
|
|
437
535
|
if (event.kind === "message" || event.kind === "task") {
|
|
438
536
|
options.firstResultResolver(event);
|
|
@@ -464,6 +562,9 @@ var DefaultRequestHandler = class {
|
|
|
464
562
|
resultManager.setContext(incomingMessage);
|
|
465
563
|
const requestContext = await this._createRequestContext(incomingMessage, taskId, false);
|
|
466
564
|
const finalMessageForAgent = requestContext.userMessage;
|
|
565
|
+
if (params.configuration?.pushNotificationConfig && this.agentCard.capabilities.pushNotifications) {
|
|
566
|
+
await this.pushNotificationStore?.save(taskId, params.configuration.pushNotificationConfig);
|
|
567
|
+
}
|
|
467
568
|
const eventBus = this.eventBusManager.createOrGetByTaskId(taskId);
|
|
468
569
|
const eventQueue = new ExecutionEventQueue(eventBus);
|
|
469
570
|
this.agentExecutor.execute(requestContext, eventBus).catch((err) => {
|
|
@@ -531,6 +632,9 @@ var DefaultRequestHandler = class {
|
|
|
531
632
|
const finalMessageForAgent = requestContext.userMessage;
|
|
532
633
|
const eventBus = this.eventBusManager.createOrGetByTaskId(taskId);
|
|
533
634
|
const eventQueue = new ExecutionEventQueue(eventBus);
|
|
635
|
+
if (params.configuration?.pushNotificationConfig && this.agentCard.capabilities.pushNotifications) {
|
|
636
|
+
await this.pushNotificationStore?.save(taskId, params.configuration.pushNotificationConfig);
|
|
637
|
+
}
|
|
534
638
|
this.agentExecutor.execute(requestContext, eventBus).catch((err) => {
|
|
535
639
|
console.error(`Agent execution failed for stream message ${finalMessageForAgent.messageId}:`, err);
|
|
536
640
|
const errorTaskStatus = {
|
|
@@ -558,6 +662,7 @@ var DefaultRequestHandler = class {
|
|
|
558
662
|
try {
|
|
559
663
|
for await (const event of eventQueue.events()) {
|
|
560
664
|
await resultManager.processEvent(event);
|
|
665
|
+
await this._sendPushNotificationIfNeeded(event);
|
|
561
666
|
yield event;
|
|
562
667
|
}
|
|
563
668
|
} finally {
|
|
@@ -622,10 +727,7 @@ var DefaultRequestHandler = class {
|
|
|
622
727
|
if (!pushNotificationConfig.id) {
|
|
623
728
|
pushNotificationConfig.id = taskId;
|
|
624
729
|
}
|
|
625
|
-
|
|
626
|
-
const updatedConfigs = configs.filter((c) => c.id !== pushNotificationConfig.id);
|
|
627
|
-
updatedConfigs.push(pushNotificationConfig);
|
|
628
|
-
this.pushNotificationConfigs.set(taskId, updatedConfigs);
|
|
730
|
+
await this.pushNotificationStore?.save(taskId, pushNotificationConfig);
|
|
629
731
|
return params;
|
|
630
732
|
}
|
|
631
733
|
async getTaskPushNotificationConfig(params) {
|
|
@@ -636,7 +738,7 @@ var DefaultRequestHandler = class {
|
|
|
636
738
|
if (!task) {
|
|
637
739
|
throw A2AError.taskNotFound(params.id);
|
|
638
740
|
}
|
|
639
|
-
const configs = this.
|
|
741
|
+
const configs = await this.pushNotificationStore?.load(params.id) || [];
|
|
640
742
|
if (configs.length === 0) {
|
|
641
743
|
throw A2AError.internalError(`Push notification config not found for task ${params.id}.`);
|
|
642
744
|
}
|
|
@@ -660,7 +762,7 @@ var DefaultRequestHandler = class {
|
|
|
660
762
|
if (!task) {
|
|
661
763
|
throw A2AError.taskNotFound(params.id);
|
|
662
764
|
}
|
|
663
|
-
const configs = this.
|
|
765
|
+
const configs = await this.pushNotificationStore?.load(params.id) || [];
|
|
664
766
|
return configs.map((config) => ({
|
|
665
767
|
taskId: params.id,
|
|
666
768
|
pushNotificationConfig: config
|
|
@@ -675,16 +777,7 @@ var DefaultRequestHandler = class {
|
|
|
675
777
|
throw A2AError.taskNotFound(params.id);
|
|
676
778
|
}
|
|
677
779
|
const { id: taskId, pushNotificationConfigId } = params;
|
|
678
|
-
|
|
679
|
-
if (!configs) {
|
|
680
|
-
return;
|
|
681
|
-
}
|
|
682
|
-
const updatedConfigs = configs.filter((c) => c.id !== pushNotificationConfigId);
|
|
683
|
-
if (updatedConfigs.length === 0) {
|
|
684
|
-
this.pushNotificationConfigs.delete(taskId);
|
|
685
|
-
} else if (updatedConfigs.length < configs.length) {
|
|
686
|
-
this.pushNotificationConfigs.set(taskId, updatedConfigs);
|
|
687
|
-
}
|
|
780
|
+
await this.pushNotificationStore?.delete(taskId, pushNotificationConfigId);
|
|
688
781
|
}
|
|
689
782
|
async *resubscribe(params) {
|
|
690
783
|
if (!this.agentCard.capabilities.streaming) {
|
|
@@ -719,6 +812,28 @@ var DefaultRequestHandler = class {
|
|
|
719
812
|
eventQueue.stop();
|
|
720
813
|
}
|
|
721
814
|
}
|
|
815
|
+
async _sendPushNotificationIfNeeded(event) {
|
|
816
|
+
if (!this.agentCard.capabilities.pushNotifications) {
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
let taskId = "";
|
|
820
|
+
if (event.kind == "task") {
|
|
821
|
+
const task2 = event;
|
|
822
|
+
taskId = task2.id;
|
|
823
|
+
} else {
|
|
824
|
+
taskId = event.taskId;
|
|
825
|
+
}
|
|
826
|
+
if (!taskId) {
|
|
827
|
+
console.error(`Task ID not found for event ${event.kind}.`);
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
const task = await this.taskStore.load(taskId);
|
|
831
|
+
if (!task) {
|
|
832
|
+
console.error(`Task ${taskId} not found.`);
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
this.pushNotificationSender?.send(task);
|
|
836
|
+
}
|
|
722
837
|
};
|
|
723
838
|
|
|
724
839
|
// src/server/store.ts
|
|
@@ -859,8 +974,10 @@ var JsonRpcTransportHandler = class {
|
|
|
859
974
|
A2AError,
|
|
860
975
|
DefaultExecutionEventBus,
|
|
861
976
|
DefaultExecutionEventBusManager,
|
|
977
|
+
DefaultPushNotificationSender,
|
|
862
978
|
DefaultRequestHandler,
|
|
863
979
|
ExecutionEventQueue,
|
|
980
|
+
InMemoryPushNotificationStore,
|
|
864
981
|
InMemoryTaskStore,
|
|
865
982
|
JsonRpcTransportHandler,
|
|
866
983
|
RequestContext,
|
package/dist/server/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EventEmitter } from 'events';
|
|
2
|
-
import { B as Message, aw as Task, aO as TaskStatusUpdateEvent, aQ as TaskArtifactUpdateEvent, ac as AgentCard, w as MessageSendParams, V as TaskQueryParams, X as TaskIdParams, Z as TaskPushNotificationConfig, a1 as GetTaskPushNotificationConfigParams, a5 as ListTaskPushNotificationConfigParams, a7 as DeleteTaskPushNotificationConfigParams, i as JSONRPCResponse, au as JSONRPCError } from '../types-DNKcmF0f.cjs';
|
|
2
|
+
import { B as Message, aw as Task, aO as TaskStatusUpdateEvent, aQ as TaskArtifactUpdateEvent, y as PushNotificationConfig, ac as AgentCard, w as MessageSendParams, V as TaskQueryParams, X as TaskIdParams, Z as TaskPushNotificationConfig, a1 as GetTaskPushNotificationConfigParams, a5 as ListTaskPushNotificationConfigParams, a7 as DeleteTaskPushNotificationConfigParams, i as JSONRPCResponse, au as JSONRPCError } from '../types-DNKcmF0f.cjs';
|
|
3
3
|
import { A as A2ARequestHandler } from '../a2a_request_handler-DUvKWfix.cjs';
|
|
4
4
|
|
|
5
5
|
type AgentExecutionEvent = Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent;
|
|
@@ -119,14 +119,31 @@ declare class InMemoryTaskStore implements TaskStore {
|
|
|
119
119
|
save(task: Task): Promise<void>;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
interface PushNotificationStore {
|
|
123
|
+
save(taskId: string, pushNotificationConfig: PushNotificationConfig): Promise<void>;
|
|
124
|
+
load(taskId: string): Promise<PushNotificationConfig[]>;
|
|
125
|
+
delete(taskId: string, configId?: string): Promise<void>;
|
|
126
|
+
}
|
|
127
|
+
declare class InMemoryPushNotificationStore implements PushNotificationStore {
|
|
128
|
+
private store;
|
|
129
|
+
save(taskId: string, pushNotificationConfig: PushNotificationConfig): Promise<void>;
|
|
130
|
+
load(taskId: string): Promise<PushNotificationConfig[]>;
|
|
131
|
+
delete(taskId: string, configId?: string): Promise<void>;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
interface PushNotificationSender {
|
|
135
|
+
send(task: Task): Promise<void>;
|
|
136
|
+
}
|
|
137
|
+
|
|
122
138
|
declare class DefaultRequestHandler implements A2ARequestHandler {
|
|
123
139
|
private readonly agentCard;
|
|
124
140
|
private readonly extendedAgentCard?;
|
|
125
141
|
private readonly taskStore;
|
|
126
142
|
private readonly agentExecutor;
|
|
127
143
|
private readonly eventBusManager;
|
|
128
|
-
private readonly
|
|
129
|
-
|
|
144
|
+
private readonly pushNotificationStore?;
|
|
145
|
+
private readonly pushNotificationSender?;
|
|
146
|
+
constructor(agentCard: AgentCard, taskStore: TaskStore, agentExecutor: AgentExecutor, eventBusManager?: ExecutionEventBusManager, pushNotificationStore?: PushNotificationStore, pushNotificationSender?: PushNotificationSender, extendedAgentCard?: AgentCard);
|
|
130
147
|
getAgentCard(): Promise<AgentCard>;
|
|
131
148
|
getAuthenticatedExtendedAgentCard(): Promise<AgentCard>;
|
|
132
149
|
private _createRequestContext;
|
|
@@ -140,6 +157,7 @@ declare class DefaultRequestHandler implements A2ARequestHandler {
|
|
|
140
157
|
listTaskPushNotificationConfigs(params: ListTaskPushNotificationConfigParams): Promise<TaskPushNotificationConfig[]>;
|
|
141
158
|
deleteTaskPushNotificationConfig(params: DeleteTaskPushNotificationConfigParams): Promise<void>;
|
|
142
159
|
resubscribe(params: TaskIdParams): AsyncGenerator<Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent, void, undefined>;
|
|
160
|
+
private _sendPushNotificationIfNeeded;
|
|
143
161
|
}
|
|
144
162
|
|
|
145
163
|
declare class ResultManager {
|
|
@@ -207,4 +225,22 @@ declare class A2AError extends Error {
|
|
|
207
225
|
static authenticatedExtendedCardNotConfigured(): A2AError;
|
|
208
226
|
}
|
|
209
227
|
|
|
210
|
-
|
|
228
|
+
interface DefaultPushNotificationSenderOptions {
|
|
229
|
+
/**
|
|
230
|
+
* Timeout in milliseconds for the abort controller. Defaults to 5000ms.
|
|
231
|
+
*/
|
|
232
|
+
timeout?: number;
|
|
233
|
+
/**
|
|
234
|
+
* Custom header name for the token. Defaults to 'X-A2A-Notification-Token'.
|
|
235
|
+
*/
|
|
236
|
+
tokenHeaderName?: string;
|
|
237
|
+
}
|
|
238
|
+
declare class DefaultPushNotificationSender implements PushNotificationSender {
|
|
239
|
+
private readonly pushNotificationStore;
|
|
240
|
+
private readonly options;
|
|
241
|
+
constructor(pushNotificationStore: PushNotificationStore, options?: DefaultPushNotificationSenderOptions);
|
|
242
|
+
send(task: Task): Promise<void>;
|
|
243
|
+
private _dispatchNotification;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export { A2AError, A2ARequestHandler, type AgentExecutionEvent, type AgentExecutor, DefaultExecutionEventBus, DefaultExecutionEventBusManager, DefaultPushNotificationSender, type DefaultPushNotificationSenderOptions, DefaultRequestHandler, type ExecutionEventBus, type ExecutionEventBusManager, ExecutionEventQueue, InMemoryPushNotificationStore, InMemoryTaskStore, JsonRpcTransportHandler, type PushNotificationSender, type PushNotificationStore, RequestContext, ResultManager, type TaskStore };
|