@a2a-js/sdk 0.3.3 → 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 CHANGED
@@ -535,6 +535,107 @@ class CancellableExecutor implements AgentExecutor {
535
535
  }
536
536
  ```
537
537
 
538
+ ## A2A Push Notifications
539
+
540
+ For very long-running tasks (e.g., lasting minutes, hours, or even days) or when clients cannot or prefer not to maintain persistent connections (like mobile clients or serverless functions), A2A supports asynchronous updates via push notifications. This mechanism allows the A2A Server to actively notify a client-provided webhook when a significant task update occurs.
541
+
542
+ ### Server-Side Configuration
543
+
544
+ To enable push notifications, your agent card must declare support:
545
+
546
+ ```typescript
547
+ const movieAgentCard: AgentCard = {
548
+ // ... other properties
549
+ capabilities: {
550
+ streaming: true,
551
+ pushNotifications: true, // Enable push notifications
552
+ stateTransitionHistory: true,
553
+ },
554
+ // ... rest of agent card
555
+ };
556
+ ```
557
+
558
+ When creating the `DefaultRequestHandler`, you can optionally provide custom push notification components:
559
+
560
+ ```typescript
561
+ import {
562
+ DefaultRequestHandler,
563
+ InMemoryPushNotificationStore,
564
+ DefaultPushNotificationSender
565
+ } from "@a2a-js/sdk/server";
566
+
567
+ // Optional: Custom push notification store and sender
568
+ const pushNotificationStore = new InMemoryPushNotificationStore();
569
+ const pushNotificationSender = new DefaultPushNotificationSender(
570
+ pushNotificationStore,
571
+ {
572
+ timeout: 5000, // 5 second timeout
573
+ tokenHeaderName: 'X-A2A-Notification-Token' // Custom header name
574
+ }
575
+ );
576
+
577
+ const requestHandler = new DefaultRequestHandler(
578
+ movieAgentCard,
579
+ taskStore,
580
+ agentExecutor,
581
+ undefined, // eventBusManager (optional)
582
+ pushNotificationStore, // custom store
583
+ pushNotificationSender, // custom sender
584
+ undefined // extendedAgentCard (optional)
585
+ );
586
+ ```
587
+
588
+ ### Client-Side Usage
589
+
590
+ Configure push notifications when sending messages:
591
+
592
+ ```typescript
593
+ // Configure push notification for a message
594
+ const pushConfig: PushNotificationConfig = {
595
+ id: "my-notification-config", // Optional, defaults to task ID
596
+ url: "https://my-app.com/webhook/task-updates",
597
+ token: "your-auth-token" // Optional authentication token
598
+ };
599
+
600
+ const sendParams: MessageSendParams = {
601
+ message: {
602
+ messageId: uuidv4(),
603
+ role: "user",
604
+ parts: [{ kind: "text", text: "Hello, agent!" }],
605
+ kind: "message",
606
+ },
607
+ configuration: {
608
+ blocking: true,
609
+ acceptedOutputModes: ["text/plain"],
610
+ pushNotificationConfig: pushConfig // Add push notification config
611
+ },
612
+ };
613
+ ```
614
+
615
+ ### Webhook Endpoint Implementation
616
+
617
+ Your webhook endpoint should expect POST requests with the task data:
618
+
619
+ ```typescript
620
+ // Example Express.js webhook endpoint
621
+ app.post('/webhook/task-updates', (req, res) => {
622
+ const task = req.body; // The complete task object
623
+
624
+ // Verify the token if provided
625
+ const token = req.headers['x-a2a-notification-token'];
626
+ if (token !== 'your-auth-token') {
627
+ return res.status(401).json({ error: 'Unauthorized' });
628
+ }
629
+
630
+ console.log(`Task ${task.id} status: ${task.status.state}`);
631
+
632
+ // Process the task update
633
+ // ...
634
+
635
+ res.status(200).json({ received: true });
636
+ });
637
+ ```
638
+
538
639
  ## License
539
640
 
540
641
  This project is licensed under the terms of the [Apache 2.0 License](https://raw.githubusercontent.com/google-a2a/a2a-python/refs/heads/main/LICENSE).
@@ -243,6 +243,28 @@ var A2AClient = class _A2AClient {
243
243
  params
244
244
  );
245
245
  }
246
+ /**
247
+ * Lists the push notification configurations for a given task.
248
+ * @param params Parameters containing the taskId.
249
+ * @returns A Promise resolving to ListTaskPushNotificationConfigResponse.
250
+ */
251
+ async listTaskPushNotificationConfig(params) {
252
+ return this._postRpcRequest(
253
+ "tasks/pushNotificationConfig/list",
254
+ params
255
+ );
256
+ }
257
+ /**
258
+ * Deletes the push notification configuration for a given task.
259
+ * @param params Parameters containing the taskId and push notification configuration ID.
260
+ * @returns A Promise resolving to DeleteTaskPushNotificationConfigResponse.
261
+ */
262
+ async deleteTaskPushNotificationConfig(params) {
263
+ return this._postRpcRequest(
264
+ "tasks/pushNotificationConfig/delete",
265
+ params
266
+ );
267
+ }
246
268
  /**
247
269
  * Retrieves a task by its ID.
248
270
  * @param params Parameters containing the taskId and optional historyLength.
@@ -259,6 +281,17 @@ var A2AClient = class _A2AClient {
259
281
  async cancelTask(params) {
260
282
  return this._postRpcRequest("tasks/cancel", params);
261
283
  }
284
+ /**
285
+ * @template TExtensionParams The type of parameters for the custom extension method.
286
+ * @template TExtensionResponse The type of response expected from the custom extension method.
287
+ * This should extend JSONRPCResponse. This ensures the extension response is still a valid A2A response.
288
+ * @param method Custom JSON-RPC method defined in the AgentCard's extensions.
289
+ * @param params Extension paramters defined in the AgentCard's extensions.
290
+ * @returns A Promise that resolves to the RPC response.
291
+ */
292
+ async callExtensionMethod(method, params) {
293
+ return this._postRpcRequest(method, params);
294
+ }
262
295
  /**
263
296
  * Resubscribes to a task's event stream using Server-Sent Events (SSE).
264
297
  * This is used if a previous SSE connection for an active task was broken.
@@ -1,4 +1,4 @@
1
- import { ac as AgentCard, w as MessageSendParams, S as SendMessageResponse, B as Message, aw as Task, aO as TaskStatusUpdateEvent, aQ as TaskArtifactUpdateEvent, Z as TaskPushNotificationConfig, b as SetTaskPushNotificationConfigResponse, X as TaskIdParams, c as GetTaskPushNotificationConfigResponse, V as TaskQueryParams, G as GetTaskResponse, C as CancelTaskResponse, i as JSONRPCResponse, J as JSONRPCErrorResponse } from '../types-DNKcmF0f.cjs';
1
+ import { ac as AgentCard, w as MessageSendParams, S as SendMessageResponse, B as Message, aw as Task, aO as TaskStatusUpdateEvent, aQ as TaskArtifactUpdateEvent, Z as TaskPushNotificationConfig, b as SetTaskPushNotificationConfigResponse, X as TaskIdParams, c as GetTaskPushNotificationConfigResponse, a5 as ListTaskPushNotificationConfigParams, j as ListTaskPushNotificationConfigResponse, a7 as DeleteTaskPushNotificationConfigParams, g as DeleteTaskPushNotificationConfigResponse, V as TaskQueryParams, G as GetTaskResponse, C as CancelTaskResponse, i as JSONRPCResponse, J as JSONRPCErrorResponse } from '../types-DNKcmF0f.cjs';
2
2
 
3
3
  type A2AStreamEventData = Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent;
4
4
  interface A2AClientOptions {
@@ -81,6 +81,18 @@ declare class A2AClient {
81
81
  * @returns A Promise resolving to GetTaskPushNotificationConfigResponse.
82
82
  */
83
83
  getTaskPushNotificationConfig(params: TaskIdParams): Promise<GetTaskPushNotificationConfigResponse>;
84
+ /**
85
+ * Lists the push notification configurations for a given task.
86
+ * @param params Parameters containing the taskId.
87
+ * @returns A Promise resolving to ListTaskPushNotificationConfigResponse.
88
+ */
89
+ listTaskPushNotificationConfig(params: ListTaskPushNotificationConfigParams): Promise<ListTaskPushNotificationConfigResponse>;
90
+ /**
91
+ * Deletes the push notification configuration for a given task.
92
+ * @param params Parameters containing the taskId and push notification configuration ID.
93
+ * @returns A Promise resolving to DeleteTaskPushNotificationConfigResponse.
94
+ */
95
+ deleteTaskPushNotificationConfig(params: DeleteTaskPushNotificationConfigParams): Promise<DeleteTaskPushNotificationConfigResponse>;
84
96
  /**
85
97
  * Retrieves a task by its ID.
86
98
  * @param params Parameters containing the taskId and optional historyLength.
@@ -93,6 +105,15 @@ declare class A2AClient {
93
105
  * @returns A Promise resolving to CancelTaskResponse, which contains the updated Task object or an error.
94
106
  */
95
107
  cancelTask(params: TaskIdParams): Promise<CancelTaskResponse>;
108
+ /**
109
+ * @template TExtensionParams The type of parameters for the custom extension method.
110
+ * @template TExtensionResponse The type of response expected from the custom extension method.
111
+ * This should extend JSONRPCResponse. This ensures the extension response is still a valid A2A response.
112
+ * @param method Custom JSON-RPC method defined in the AgentCard's extensions.
113
+ * @param params Extension paramters defined in the AgentCard's extensions.
114
+ * @returns A Promise that resolves to the RPC response.
115
+ */
116
+ callExtensionMethod<TExtensionParams, TExtensionResponse extends JSONRPCResponse>(method: string, params: TExtensionParams): Promise<TExtensionResponse>;
96
117
  /**
97
118
  * Resubscribes to a task's event stream using Server-Sent Events (SSE).
98
119
  * This is used if a previous SSE connection for an active task was broken.
@@ -1,4 +1,4 @@
1
- import { ac as AgentCard, w as MessageSendParams, S as SendMessageResponse, B as Message, aw as Task, aO as TaskStatusUpdateEvent, aQ as TaskArtifactUpdateEvent, Z as TaskPushNotificationConfig, b as SetTaskPushNotificationConfigResponse, X as TaskIdParams, c as GetTaskPushNotificationConfigResponse, V as TaskQueryParams, G as GetTaskResponse, C as CancelTaskResponse, i as JSONRPCResponse, J as JSONRPCErrorResponse } from '../types-DNKcmF0f.js';
1
+ import { ac as AgentCard, w as MessageSendParams, S as SendMessageResponse, B as Message, aw as Task, aO as TaskStatusUpdateEvent, aQ as TaskArtifactUpdateEvent, Z as TaskPushNotificationConfig, b as SetTaskPushNotificationConfigResponse, X as TaskIdParams, c as GetTaskPushNotificationConfigResponse, a5 as ListTaskPushNotificationConfigParams, j as ListTaskPushNotificationConfigResponse, a7 as DeleteTaskPushNotificationConfigParams, g as DeleteTaskPushNotificationConfigResponse, V as TaskQueryParams, G as GetTaskResponse, C as CancelTaskResponse, i as JSONRPCResponse, J as JSONRPCErrorResponse } from '../types-DNKcmF0f.js';
2
2
 
3
3
  type A2AStreamEventData = Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent;
4
4
  interface A2AClientOptions {
@@ -81,6 +81,18 @@ declare class A2AClient {
81
81
  * @returns A Promise resolving to GetTaskPushNotificationConfigResponse.
82
82
  */
83
83
  getTaskPushNotificationConfig(params: TaskIdParams): Promise<GetTaskPushNotificationConfigResponse>;
84
+ /**
85
+ * Lists the push notification configurations for a given task.
86
+ * @param params Parameters containing the taskId.
87
+ * @returns A Promise resolving to ListTaskPushNotificationConfigResponse.
88
+ */
89
+ listTaskPushNotificationConfig(params: ListTaskPushNotificationConfigParams): Promise<ListTaskPushNotificationConfigResponse>;
90
+ /**
91
+ * Deletes the push notification configuration for a given task.
92
+ * @param params Parameters containing the taskId and push notification configuration ID.
93
+ * @returns A Promise resolving to DeleteTaskPushNotificationConfigResponse.
94
+ */
95
+ deleteTaskPushNotificationConfig(params: DeleteTaskPushNotificationConfigParams): Promise<DeleteTaskPushNotificationConfigResponse>;
84
96
  /**
85
97
  * Retrieves a task by its ID.
86
98
  * @param params Parameters containing the taskId and optional historyLength.
@@ -93,6 +105,15 @@ declare class A2AClient {
93
105
  * @returns A Promise resolving to CancelTaskResponse, which contains the updated Task object or an error.
94
106
  */
95
107
  cancelTask(params: TaskIdParams): Promise<CancelTaskResponse>;
108
+ /**
109
+ * @template TExtensionParams The type of parameters for the custom extension method.
110
+ * @template TExtensionResponse The type of response expected from the custom extension method.
111
+ * This should extend JSONRPCResponse. This ensures the extension response is still a valid A2A response.
112
+ * @param method Custom JSON-RPC method defined in the AgentCard's extensions.
113
+ * @param params Extension paramters defined in the AgentCard's extensions.
114
+ * @returns A Promise that resolves to the RPC response.
115
+ */
116
+ callExtensionMethod<TExtensionParams, TExtensionResponse extends JSONRPCResponse>(method: string, params: TExtensionParams): Promise<TExtensionResponse>;
96
117
  /**
97
118
  * Resubscribes to a task's event stream using Server-Sent Events (SSE).
98
119
  * This is used if a previous SSE connection for an active task was broken.
@@ -218,6 +218,28 @@ var A2AClient = class _A2AClient {
218
218
  params
219
219
  );
220
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
+ }
221
243
  /**
222
244
  * Retrieves a task by its ID.
223
245
  * @param params Parameters containing the taskId and optional historyLength.
@@ -234,6 +256,17 @@ var A2AClient = class _A2AClient {
234
256
  async cancelTask(params) {
235
257
  return this._postRpcRequest("tasks/cancel", params);
236
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
+ }
237
270
  /**
238
271
  * Resubscribes to a task's event stream using Server-Sent Events (SSE).
239
272
  * This is used if a previous SSE connection for an active task was broken.
@@ -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
- // Store for push notification configurations (could be part of TaskStore or separate)
378
- pushNotificationConfigs = /* @__PURE__ */ new Map();
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
- const configs = this.pushNotificationConfigs.get(taskId) || [];
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.pushNotificationConfigs.get(params.id) || [];
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.pushNotificationConfigs.get(params.id) || [];
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
- const configs = this.pushNotificationConfigs.get(taskId);
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,
@@ -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 pushNotificationConfigs;
129
- constructor(agentCard: AgentCard, taskStore: TaskStore, agentExecutor: AgentExecutor, eventBusManager?: ExecutionEventBusManager, extendedAgentCard?: AgentCard);
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
- export { A2AError, A2ARequestHandler, type AgentExecutionEvent, type AgentExecutor, DefaultExecutionEventBus, DefaultExecutionEventBusManager, DefaultRequestHandler, type ExecutionEventBus, type ExecutionEventBusManager, ExecutionEventQueue, InMemoryTaskStore, JsonRpcTransportHandler, RequestContext, ResultManager, type TaskStore };
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 };
@@ -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.js';
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.js';
3
3
  import { A as A2ARequestHandler } from '../a2a_request_handler-B5t-IxgA.js';
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 pushNotificationConfigs;
129
- constructor(agentCard: AgentCard, taskStore: TaskStore, agentExecutor: AgentExecutor, eventBusManager?: ExecutionEventBusManager, extendedAgentCard?: AgentCard);
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
- export { A2AError, A2ARequestHandler, type AgentExecutionEvent, type AgentExecutor, DefaultExecutionEventBus, DefaultExecutionEventBusManager, DefaultRequestHandler, type ExecutionEventBus, type ExecutionEventBusManager, ExecutionEventQueue, InMemoryTaskStore, JsonRpcTransportHandler, RequestContext, ResultManager, type TaskStore };
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 };
@@ -257,6 +257,97 @@ var ResultManager = class {
257
257
  }
258
258
  };
259
259
 
260
+ // src/server/push_notification/push_notification_store.ts
261
+ var InMemoryPushNotificationStore = class {
262
+ store = /* @__PURE__ */ new Map();
263
+ async save(taskId, pushNotificationConfig) {
264
+ const configs = this.store.get(taskId) || [];
265
+ if (!pushNotificationConfig.id) {
266
+ pushNotificationConfig.id = taskId;
267
+ }
268
+ const existingIndex = configs.findIndex((config) => config.id === pushNotificationConfig.id);
269
+ if (existingIndex !== -1) {
270
+ configs.splice(existingIndex, 1);
271
+ }
272
+ configs.push(pushNotificationConfig);
273
+ this.store.set(taskId, configs);
274
+ }
275
+ async load(taskId) {
276
+ const configs = this.store.get(taskId);
277
+ return configs || [];
278
+ }
279
+ async delete(taskId, configId) {
280
+ if (configId === void 0) {
281
+ configId = taskId;
282
+ }
283
+ const configs = this.store.get(taskId);
284
+ if (!configs) {
285
+ return;
286
+ }
287
+ const configIndex = configs.findIndex((config) => config.id === configId);
288
+ if (configIndex !== -1) {
289
+ configs.splice(configIndex, 1);
290
+ }
291
+ if (configs.length === 0) {
292
+ this.store.delete(taskId);
293
+ } else {
294
+ this.store.set(taskId, configs);
295
+ }
296
+ }
297
+ };
298
+
299
+ // src/server/push_notification/default_push_notification_sender.ts
300
+ var DefaultPushNotificationSender = class {
301
+ pushNotificationStore;
302
+ options;
303
+ constructor(pushNotificationStore, options = {}) {
304
+ this.pushNotificationStore = pushNotificationStore;
305
+ this.options = {
306
+ timeout: 5e3,
307
+ tokenHeaderName: "X-A2A-Notification-Token",
308
+ ...options
309
+ };
310
+ }
311
+ async send(task) {
312
+ const pushConfigs = await this.pushNotificationStore.load(task.id);
313
+ if (!pushConfigs || pushConfigs.length === 0) {
314
+ return;
315
+ }
316
+ pushConfigs.forEach((pushConfig) => {
317
+ this._dispatchNotification(task, pushConfig).catch((error) => {
318
+ console.error(`Error sending push notification for task_id=${task.id} to URL: ${pushConfig.url}. Error:`, error);
319
+ });
320
+ });
321
+ }
322
+ async _dispatchNotification(task, pushConfig) {
323
+ const url = pushConfig.url;
324
+ const controller = new AbortController();
325
+ const timeoutId = setTimeout(() => controller.abort(), this.options.timeout);
326
+ try {
327
+ const headers = {
328
+ "Content-Type": "application/json"
329
+ };
330
+ if (pushConfig.token) {
331
+ headers[this.options.tokenHeaderName] = pushConfig.token;
332
+ }
333
+ const response = await fetch(url, {
334
+ method: "POST",
335
+ headers,
336
+ body: JSON.stringify(task),
337
+ signal: controller.signal
338
+ });
339
+ if (!response.ok) {
340
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
341
+ }
342
+ console.info(`Push notification sent for task_id=${task.id} to URL: ${url}`);
343
+ } catch (error) {
344
+ console.error(`Error sending push notification for task_id=${task.id} to URL: ${url}. Error:`, error);
345
+ } finally {
346
+ clearTimeout(timeoutId);
347
+ }
348
+ }
349
+ };
350
+
260
351
  // src/server/request_handler/default_request_handler.ts
261
352
  var terminalStates = ["completed", "failed", "canceled", "rejected"];
262
353
  var DefaultRequestHandler = class {
@@ -265,14 +356,18 @@ var DefaultRequestHandler = class {
265
356
  taskStore;
266
357
  agentExecutor;
267
358
  eventBusManager;
268
- // Store for push notification configurations (could be part of TaskStore or separate)
269
- pushNotificationConfigs = /* @__PURE__ */ new Map();
270
- constructor(agentCard, taskStore, agentExecutor, eventBusManager = new DefaultExecutionEventBusManager(), extendedAgentCard) {
359
+ pushNotificationStore;
360
+ pushNotificationSender;
361
+ constructor(agentCard, taskStore, agentExecutor, eventBusManager = new DefaultExecutionEventBusManager(), pushNotificationStore, pushNotificationSender, extendedAgentCard) {
271
362
  this.agentCard = agentCard;
272
363
  this.taskStore = taskStore;
273
364
  this.agentExecutor = agentExecutor;
274
365
  this.eventBusManager = eventBusManager;
275
366
  this.extendedAgentCard = extendedAgentCard;
367
+ if (agentCard.capabilities.pushNotifications) {
368
+ this.pushNotificationStore = pushNotificationStore || new InMemoryPushNotificationStore();
369
+ this.pushNotificationSender = pushNotificationSender || new DefaultPushNotificationSender(this.pushNotificationStore);
370
+ }
276
371
  }
277
372
  async getAgentCard() {
278
373
  return this.agentCard;
@@ -324,6 +419,7 @@ var DefaultRequestHandler = class {
324
419
  try {
325
420
  for await (const event of eventQueue.events()) {
326
421
  await resultManager.processEvent(event);
422
+ await this._sendPushNotificationIfNeeded(event);
327
423
  if (options?.firstResultResolver && !firstResultSent) {
328
424
  if (event.kind === "message" || event.kind === "task") {
329
425
  options.firstResultResolver(event);
@@ -355,6 +451,9 @@ var DefaultRequestHandler = class {
355
451
  resultManager.setContext(incomingMessage);
356
452
  const requestContext = await this._createRequestContext(incomingMessage, taskId, false);
357
453
  const finalMessageForAgent = requestContext.userMessage;
454
+ if (params.configuration?.pushNotificationConfig && this.agentCard.capabilities.pushNotifications) {
455
+ await this.pushNotificationStore?.save(taskId, params.configuration.pushNotificationConfig);
456
+ }
358
457
  const eventBus = this.eventBusManager.createOrGetByTaskId(taskId);
359
458
  const eventQueue = new ExecutionEventQueue(eventBus);
360
459
  this.agentExecutor.execute(requestContext, eventBus).catch((err) => {
@@ -422,6 +521,9 @@ var DefaultRequestHandler = class {
422
521
  const finalMessageForAgent = requestContext.userMessage;
423
522
  const eventBus = this.eventBusManager.createOrGetByTaskId(taskId);
424
523
  const eventQueue = new ExecutionEventQueue(eventBus);
524
+ if (params.configuration?.pushNotificationConfig && this.agentCard.capabilities.pushNotifications) {
525
+ await this.pushNotificationStore?.save(taskId, params.configuration.pushNotificationConfig);
526
+ }
425
527
  this.agentExecutor.execute(requestContext, eventBus).catch((err) => {
426
528
  console.error(`Agent execution failed for stream message ${finalMessageForAgent.messageId}:`, err);
427
529
  const errorTaskStatus = {
@@ -449,6 +551,7 @@ var DefaultRequestHandler = class {
449
551
  try {
450
552
  for await (const event of eventQueue.events()) {
451
553
  await resultManager.processEvent(event);
554
+ await this._sendPushNotificationIfNeeded(event);
452
555
  yield event;
453
556
  }
454
557
  } finally {
@@ -513,10 +616,7 @@ var DefaultRequestHandler = class {
513
616
  if (!pushNotificationConfig.id) {
514
617
  pushNotificationConfig.id = taskId;
515
618
  }
516
- const configs = this.pushNotificationConfigs.get(taskId) || [];
517
- const updatedConfigs = configs.filter((c) => c.id !== pushNotificationConfig.id);
518
- updatedConfigs.push(pushNotificationConfig);
519
- this.pushNotificationConfigs.set(taskId, updatedConfigs);
619
+ await this.pushNotificationStore?.save(taskId, pushNotificationConfig);
520
620
  return params;
521
621
  }
522
622
  async getTaskPushNotificationConfig(params) {
@@ -527,7 +627,7 @@ var DefaultRequestHandler = class {
527
627
  if (!task) {
528
628
  throw A2AError.taskNotFound(params.id);
529
629
  }
530
- const configs = this.pushNotificationConfigs.get(params.id) || [];
630
+ const configs = await this.pushNotificationStore?.load(params.id) || [];
531
631
  if (configs.length === 0) {
532
632
  throw A2AError.internalError(`Push notification config not found for task ${params.id}.`);
533
633
  }
@@ -551,7 +651,7 @@ var DefaultRequestHandler = class {
551
651
  if (!task) {
552
652
  throw A2AError.taskNotFound(params.id);
553
653
  }
554
- const configs = this.pushNotificationConfigs.get(params.id) || [];
654
+ const configs = await this.pushNotificationStore?.load(params.id) || [];
555
655
  return configs.map((config) => ({
556
656
  taskId: params.id,
557
657
  pushNotificationConfig: config
@@ -566,16 +666,7 @@ var DefaultRequestHandler = class {
566
666
  throw A2AError.taskNotFound(params.id);
567
667
  }
568
668
  const { id: taskId, pushNotificationConfigId } = params;
569
- const configs = this.pushNotificationConfigs.get(taskId);
570
- if (!configs) {
571
- return;
572
- }
573
- const updatedConfigs = configs.filter((c) => c.id !== pushNotificationConfigId);
574
- if (updatedConfigs.length === 0) {
575
- this.pushNotificationConfigs.delete(taskId);
576
- } else if (updatedConfigs.length < configs.length) {
577
- this.pushNotificationConfigs.set(taskId, updatedConfigs);
578
- }
669
+ await this.pushNotificationStore?.delete(taskId, pushNotificationConfigId);
579
670
  }
580
671
  async *resubscribe(params) {
581
672
  if (!this.agentCard.capabilities.streaming) {
@@ -610,6 +701,28 @@ var DefaultRequestHandler = class {
610
701
  eventQueue.stop();
611
702
  }
612
703
  }
704
+ async _sendPushNotificationIfNeeded(event) {
705
+ if (!this.agentCard.capabilities.pushNotifications) {
706
+ return;
707
+ }
708
+ let taskId = "";
709
+ if (event.kind == "task") {
710
+ const task2 = event;
711
+ taskId = task2.id;
712
+ } else {
713
+ taskId = event.taskId;
714
+ }
715
+ if (!taskId) {
716
+ console.error(`Task ID not found for event ${event.kind}.`);
717
+ return;
718
+ }
719
+ const task = await this.taskStore.load(taskId);
720
+ if (!task) {
721
+ console.error(`Task ${taskId} not found.`);
722
+ return;
723
+ }
724
+ this.pushNotificationSender?.send(task);
725
+ }
613
726
  };
614
727
 
615
728
  // src/server/store.ts
@@ -627,8 +740,10 @@ export {
627
740
  A2AError,
628
741
  DefaultExecutionEventBus,
629
742
  DefaultExecutionEventBusManager,
743
+ DefaultPushNotificationSender,
630
744
  DefaultRequestHandler,
631
745
  ExecutionEventQueue,
746
+ InMemoryPushNotificationStore,
632
747
  InMemoryTaskStore,
633
748
  JsonRpcTransportHandler,
634
749
  RequestContext,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a2a-js/sdk",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "description": "Server & Client SDK for Agent2Agent protocol",
5
5
  "repository": {
6
6
  "type": "git",