@a2a-js/sdk 0.3.5 → 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.
@@ -29,37 +29,219 @@ __export(server_exports, {
29
29
  InMemoryTaskStore: () => InMemoryTaskStore,
30
30
  JsonRpcTransportHandler: () => JsonRpcTransportHandler,
31
31
  RequestContext: () => RequestContext,
32
- ResultManager: () => ResultManager
32
+ ResultManager: () => ResultManager,
33
+ ServerCallContext: () => ServerCallContext,
34
+ UnauthenticatedUser: () => UnauthenticatedUser
33
35
  });
34
36
  module.exports = __toCommonJS(server_exports);
35
37
 
36
38
  // src/server/agent_execution/request_context.ts
37
39
  var RequestContext = class {
38
40
  userMessage;
39
- task;
40
- referenceTasks;
41
41
  taskId;
42
42
  contextId;
43
- constructor(userMessage, taskId, contextId, task, referenceTasks) {
43
+ task;
44
+ referenceTasks;
45
+ context;
46
+ constructor(userMessage, taskId, contextId, task, referenceTasks, context) {
44
47
  this.userMessage = userMessage;
45
48
  this.taskId = taskId;
46
49
  this.contextId = contextId;
47
50
  this.task = task;
48
51
  this.referenceTasks = referenceTasks;
52
+ this.context = context;
49
53
  }
50
54
  };
51
55
 
52
56
  // src/server/events/execution_event_bus.ts
53
- var import_events = require("events");
54
- var DefaultExecutionEventBus = class extends import_events.EventEmitter {
55
- constructor() {
56
- super();
57
+ var CustomEventImpl = typeof CustomEvent !== "undefined" ? CustomEvent : class CustomEventPolyfill extends Event {
58
+ detail;
59
+ constructor(type, eventInitDict) {
60
+ super(type, eventInitDict);
61
+ this.detail = eventInitDict?.detail ?? null;
57
62
  }
63
+ };
64
+ function isAgentExecutionCustomEvent(e) {
65
+ return e instanceof CustomEventImpl;
66
+ }
67
+ var DefaultExecutionEventBus = class extends EventTarget {
68
+ // Separate storage for each event type - both use the interface's Listener type
69
+ // but are invoked differently (with event payload vs. no arguments)
70
+ eventListeners = /* @__PURE__ */ new Map();
71
+ finishedListeners = /* @__PURE__ */ new Map();
58
72
  publish(event) {
59
- this.emit("event", event);
73
+ this.dispatchEvent(new CustomEventImpl("event", { detail: event }));
60
74
  }
61
75
  finished() {
62
- this.emit("finished");
76
+ this.dispatchEvent(new Event("finished"));
77
+ }
78
+ /**
79
+ * EventEmitter-compatible 'on' method.
80
+ * Wraps the listener to extract event detail from CustomEvent.
81
+ * Supports multiple registrations of the same listener (like EventEmitter).
82
+ * @param eventName The event name to listen for.
83
+ * @param listener The callback function to invoke when the event is emitted.
84
+ * @returns This instance for method chaining.
85
+ */
86
+ on(eventName, listener) {
87
+ if (eventName === "event") {
88
+ this.addEventListenerInternal(listener);
89
+ } else {
90
+ this.addFinishedListenerInternal(listener);
91
+ }
92
+ return this;
93
+ }
94
+ /**
95
+ * EventEmitter-compatible 'off' method.
96
+ * Uses the stored wrapped listener for proper removal.
97
+ * Removes at most one instance of a listener per call (like EventEmitter).
98
+ * @param eventName The event name to stop listening for.
99
+ * @param listener The callback function to remove.
100
+ * @returns This instance for method chaining.
101
+ */
102
+ off(eventName, listener) {
103
+ if (eventName === "event") {
104
+ this.removeEventListenerInternal(listener);
105
+ } else {
106
+ this.removeFinishedListenerInternal(listener);
107
+ }
108
+ return this;
109
+ }
110
+ /**
111
+ * EventEmitter-compatible 'once' method.
112
+ * Listener is automatically removed after first invocation.
113
+ * Supports multiple registrations of the same listener (like EventEmitter).
114
+ * @param eventName The event name to listen for once.
115
+ * @param listener The callback function to invoke when the event is emitted.
116
+ * @returns This instance for method chaining.
117
+ */
118
+ once(eventName, listener) {
119
+ if (eventName === "event") {
120
+ this.addEventListenerOnceInternal(listener);
121
+ } else {
122
+ this.addFinishedListenerOnceInternal(listener);
123
+ }
124
+ return this;
125
+ }
126
+ /**
127
+ * EventEmitter-compatible 'removeAllListeners' method.
128
+ * Removes all listeners for a specific event or all events.
129
+ * @param eventName Optional event name to remove listeners for. If omitted, removes all.
130
+ * @returns This instance for method chaining.
131
+ */
132
+ removeAllListeners(eventName) {
133
+ if (eventName === void 0 || eventName === "event") {
134
+ for (const wrappedListeners of this.eventListeners.values()) {
135
+ for (const wrapped of wrappedListeners) {
136
+ this.removeEventListener("event", wrapped);
137
+ }
138
+ }
139
+ this.eventListeners.clear();
140
+ }
141
+ if (eventName === void 0 || eventName === "finished") {
142
+ for (const wrappedListeners of this.finishedListeners.values()) {
143
+ for (const wrapped of wrappedListeners) {
144
+ this.removeEventListener("finished", wrapped);
145
+ }
146
+ }
147
+ this.finishedListeners.clear();
148
+ }
149
+ return this;
150
+ }
151
+ // ========================
152
+ // Helper methods for listener tracking
153
+ // ========================
154
+ /**
155
+ * Adds a wrapped listener to the tracking map.
156
+ */
157
+ trackListener(listenerMap, listener, wrapped) {
158
+ const existing = listenerMap.get(listener);
159
+ if (existing) {
160
+ existing.push(wrapped);
161
+ } else {
162
+ listenerMap.set(listener, [wrapped]);
163
+ }
164
+ }
165
+ /**
166
+ * Removes a wrapped listener from the tracking map (for once cleanup).
167
+ */
168
+ untrackWrappedListener(listenerMap, listener, wrapped) {
169
+ const wrappedList = listenerMap.get(listener);
170
+ if (wrappedList && wrappedList.length > 0) {
171
+ const index = wrappedList.indexOf(wrapped);
172
+ if (index !== -1) {
173
+ wrappedList.splice(index, 1);
174
+ if (wrappedList.length === 0) {
175
+ listenerMap.delete(listener);
176
+ }
177
+ }
178
+ }
179
+ }
180
+ // ========================
181
+ // Internal methods for 'event' listeners
182
+ // ========================
183
+ addEventListenerInternal(listener) {
184
+ const wrapped = (e) => {
185
+ if (!isAgentExecutionCustomEvent(e)) {
186
+ throw new Error('Internal error: expected CustomEvent for "event" type');
187
+ }
188
+ listener.call(this, e.detail);
189
+ };
190
+ this.trackListener(this.eventListeners, listener, wrapped);
191
+ this.addEventListener("event", wrapped);
192
+ }
193
+ removeEventListenerInternal(listener) {
194
+ const wrappedList = this.eventListeners.get(listener);
195
+ if (wrappedList && wrappedList.length > 0) {
196
+ const wrapped = wrappedList.pop();
197
+ if (wrappedList.length === 0) {
198
+ this.eventListeners.delete(listener);
199
+ }
200
+ this.removeEventListener("event", wrapped);
201
+ }
202
+ }
203
+ addEventListenerOnceInternal(listener) {
204
+ const wrapped = (e) => {
205
+ if (!isAgentExecutionCustomEvent(e)) {
206
+ throw new Error('Internal error: expected CustomEvent for "event" type');
207
+ }
208
+ this.untrackWrappedListener(this.eventListeners, listener, wrapped);
209
+ listener.call(this, e.detail);
210
+ };
211
+ this.trackListener(this.eventListeners, listener, wrapped);
212
+ this.addEventListener("event", wrapped, { once: true });
213
+ }
214
+ // ========================
215
+ // Internal methods for 'finished' listeners
216
+ // ========================
217
+ // The interface declares listeners as (event: AgentExecutionEvent) => void,
218
+ // but for 'finished' events they are invoked with no arguments (EventEmitter behavior).
219
+ // We use Function.prototype.call to invoke with `this` as the event bus (matching
220
+ // EventEmitter semantics) and no arguments, which is type-safe.
221
+ addFinishedListenerInternal(listener) {
222
+ const wrapped = () => {
223
+ listener.call(this);
224
+ };
225
+ this.trackListener(this.finishedListeners, listener, wrapped);
226
+ this.addEventListener("finished", wrapped);
227
+ }
228
+ removeFinishedListenerInternal(listener) {
229
+ const wrappedList = this.finishedListeners.get(listener);
230
+ if (wrappedList && wrappedList.length > 0) {
231
+ const wrapped = wrappedList.pop();
232
+ if (wrappedList.length === 0) {
233
+ this.finishedListeners.delete(listener);
234
+ }
235
+ this.removeEventListener("finished", wrapped);
236
+ }
237
+ }
238
+ addFinishedListenerOnceInternal(listener) {
239
+ const wrapped = () => {
240
+ this.untrackWrappedListener(this.finishedListeners, listener, wrapped);
241
+ listener.call(this);
242
+ };
243
+ this.trackListener(this.finishedListeners, listener, wrapped);
244
+ this.addEventListener("finished", wrapped, { once: true });
63
245
  }
64
246
  };
65
247
 
@@ -69,7 +251,7 @@ var DefaultExecutionEventBusManager = class {
69
251
  /**
70
252
  * Creates or retrieves an existing ExecutionEventBus based on the taskId.
71
253
  * @param taskId The ID of the task.
72
- * @returns An instance of IExecutionEventBus.
254
+ * @returns An instance of ExecutionEventBus.
73
255
  */
74
256
  createOrGetByTaskId(taskId) {
75
257
  if (!this.taskIdToBus.has(taskId)) {
@@ -80,7 +262,7 @@ var DefaultExecutionEventBusManager = class {
80
262
  /**
81
263
  * Retrieves an existing ExecutionEventBus based on the taskId.
82
264
  * @param taskId The ID of the task.
83
- * @returns An instance of IExecutionEventBus or undefined if not found.
265
+ * @returns An instance of ExecutionEventBus or undefined if not found.
84
266
  */
85
267
  getByTaskId(taskId) {
86
268
  return this.taskIdToBus.get(taskId);
@@ -193,10 +375,7 @@ var A2AError = class _A2AError extends Error {
193
375
  return new _A2AError(-32600, message, data);
194
376
  }
195
377
  static methodNotFound(method) {
196
- return new _A2AError(
197
- -32601,
198
- `Method not found: ${method}`
199
- );
378
+ return new _A2AError(-32601, `Method not found: ${method}`);
200
379
  }
201
380
  static invalidParams(message, data) {
202
381
  return new _A2AError(-32602, message, data);
@@ -205,51 +384,34 @@ var A2AError = class _A2AError extends Error {
205
384
  return new _A2AError(-32603, message, data);
206
385
  }
207
386
  static taskNotFound(taskId) {
208
- return new _A2AError(
209
- -32001,
210
- `Task not found: ${taskId}`,
211
- void 0,
212
- taskId
213
- );
387
+ return new _A2AError(-32001, `Task not found: ${taskId}`, void 0, taskId);
214
388
  }
215
389
  static taskNotCancelable(taskId) {
216
- return new _A2AError(
217
- -32002,
218
- `Task not cancelable: ${taskId}`,
219
- void 0,
220
- taskId
221
- );
390
+ return new _A2AError(-32002, `Task not cancelable: ${taskId}`, void 0, taskId);
222
391
  }
223
392
  static pushNotificationNotSupported() {
224
- return new _A2AError(
225
- -32003,
226
- "Push Notification is not supported"
227
- );
393
+ return new _A2AError(-32003, "Push Notification is not supported");
228
394
  }
229
395
  static unsupportedOperation(operation) {
230
- return new _A2AError(
231
- -32004,
232
- `Unsupported operation: ${operation}`
233
- );
396
+ return new _A2AError(-32004, `Unsupported operation: ${operation}`);
234
397
  }
235
398
  static authenticatedExtendedCardNotConfigured() {
236
- return new _A2AError(
237
- -32007,
238
- `Extended card not configured.`
239
- );
399
+ return new _A2AError(-32007, `Extended card not configured.`);
240
400
  }
241
401
  };
242
402
 
243
403
  // src/server/result_manager.ts
244
404
  var ResultManager = class {
245
405
  taskStore;
406
+ serverCallContext;
246
407
  currentTask;
247
408
  latestUserMessage;
248
409
  // To add to history if a new task is created
249
410
  finalMessageResult;
250
411
  // Stores the message if it's the final result
251
- constructor(taskStore) {
412
+ constructor(taskStore, serverCallContext) {
252
413
  this.taskStore = taskStore;
414
+ this.serverCallContext = serverCallContext;
253
415
  }
254
416
  setContext(latestUserMessage) {
255
417
  this.latestUserMessage = latestUserMessage;
@@ -265,7 +427,9 @@ var ResultManager = class {
265
427
  const taskEvent = event;
266
428
  this.currentTask = { ...taskEvent };
267
429
  if (this.latestUserMessage) {
268
- if (!this.currentTask.history?.find((msg) => msg.messageId === this.latestUserMessage.messageId)) {
430
+ if (!this.currentTask.history?.find(
431
+ (msg) => msg.messageId === this.latestUserMessage.messageId
432
+ )) {
269
433
  this.currentTask.history = [this.latestUserMessage, ...this.currentTask.history || []];
270
434
  }
271
435
  }
@@ -275,24 +439,36 @@ var ResultManager = class {
275
439
  if (this.currentTask && this.currentTask.id === updateEvent.taskId) {
276
440
  this.currentTask.status = updateEvent.status;
277
441
  if (updateEvent.status.message) {
278
- if (!this.currentTask.history?.find((msg) => msg.messageId === updateEvent.status.message.messageId)) {
279
- this.currentTask.history = [...this.currentTask.history || [], updateEvent.status.message];
442
+ if (!this.currentTask.history?.find(
443
+ (msg) => msg.messageId === updateEvent.status.message.messageId
444
+ )) {
445
+ this.currentTask.history = [
446
+ ...this.currentTask.history || [],
447
+ updateEvent.status.message
448
+ ];
280
449
  }
281
450
  }
282
451
  await this.saveCurrentTask();
283
452
  } else if (!this.currentTask && updateEvent.taskId) {
284
- const loaded = await this.taskStore.load(updateEvent.taskId);
453
+ const loaded = await this.taskStore.load(updateEvent.taskId, this.serverCallContext);
285
454
  if (loaded) {
286
455
  this.currentTask = loaded;
287
456
  this.currentTask.status = updateEvent.status;
288
457
  if (updateEvent.status.message) {
289
- if (!this.currentTask.history?.find((msg) => msg.messageId === updateEvent.status.message.messageId)) {
290
- this.currentTask.history = [...this.currentTask.history || [], updateEvent.status.message];
458
+ if (!this.currentTask.history?.find(
459
+ (msg) => msg.messageId === updateEvent.status.message.messageId
460
+ )) {
461
+ this.currentTask.history = [
462
+ ...this.currentTask.history || [],
463
+ updateEvent.status.message
464
+ ];
291
465
  }
292
466
  }
293
467
  await this.saveCurrentTask();
294
468
  } else {
295
- console.warn(`ResultManager: Received status update for unknown task ${updateEvent.taskId}`);
469
+ console.warn(
470
+ `ResultManager: Received status update for unknown task ${updateEvent.taskId}`
471
+ );
296
472
  }
297
473
  }
298
474
  } else if (event.kind === "artifact-update") {
@@ -308,9 +484,14 @@ var ResultManager = class {
308
484
  if (artifactEvent.append) {
309
485
  const existingArtifact = this.currentTask.artifacts[existingArtifactIndex];
310
486
  existingArtifact.parts.push(...artifactEvent.artifact.parts);
311
- if (artifactEvent.artifact.description) existingArtifact.description = artifactEvent.artifact.description;
487
+ if (artifactEvent.artifact.description)
488
+ existingArtifact.description = artifactEvent.artifact.description;
312
489
  if (artifactEvent.artifact.name) existingArtifact.name = artifactEvent.artifact.name;
313
- if (artifactEvent.artifact.metadata) existingArtifact.metadata = { ...existingArtifact.metadata, ...artifactEvent.artifact.metadata };
490
+ if (artifactEvent.artifact.metadata)
491
+ existingArtifact.metadata = {
492
+ ...existingArtifact.metadata,
493
+ ...artifactEvent.artifact.metadata
494
+ };
314
495
  } else {
315
496
  this.currentTask.artifacts[existingArtifactIndex] = artifactEvent.artifact;
316
497
  }
@@ -319,7 +500,7 @@ var ResultManager = class {
319
500
  }
320
501
  await this.saveCurrentTask();
321
502
  } else if (!this.currentTask && artifactEvent.taskId) {
322
- const loaded = await this.taskStore.load(artifactEvent.taskId);
503
+ const loaded = await this.taskStore.load(artifactEvent.taskId, this.serverCallContext);
323
504
  if (loaded) {
324
505
  this.currentTask = loaded;
325
506
  if (!this.currentTask.artifacts) this.currentTask.artifacts = [];
@@ -328,7 +509,9 @@ var ResultManager = class {
328
509
  );
329
510
  if (existingArtifactIndex !== -1) {
330
511
  if (artifactEvent.append) {
331
- this.currentTask.artifacts[existingArtifactIndex].parts.push(...artifactEvent.artifact.parts);
512
+ this.currentTask.artifacts[existingArtifactIndex].parts.push(
513
+ ...artifactEvent.artifact.parts
514
+ );
332
515
  } else {
333
516
  this.currentTask.artifacts[existingArtifactIndex] = artifactEvent.artifact;
334
517
  }
@@ -337,14 +520,16 @@ var ResultManager = class {
337
520
  }
338
521
  await this.saveCurrentTask();
339
522
  } else {
340
- console.warn(`ResultManager: Received artifact update for unknown task ${artifactEvent.taskId}`);
523
+ console.warn(
524
+ `ResultManager: Received artifact update for unknown task ${artifactEvent.taskId}`
525
+ );
341
526
  }
342
527
  }
343
528
  }
344
529
  }
345
530
  async saveCurrentTask() {
346
531
  if (this.currentTask) {
347
- await this.taskStore.save(this.currentTask);
532
+ await this.taskStore.save(this.currentTask, this.serverCallContext);
348
533
  }
349
534
  }
350
535
  /**
@@ -432,7 +617,10 @@ var DefaultPushNotificationSender = class {
432
617
  try {
433
618
  await this._dispatchNotification(task, pushConfig);
434
619
  } catch (error) {
435
- console.error(`Error sending push notification for task_id=${task.id} to URL: ${pushConfig.url}. Error:`, error);
620
+ console.error(
621
+ `Error sending push notification for task_id=${task.id} to URL: ${pushConfig.url}. Error:`,
622
+ error
623
+ );
436
624
  }
437
625
  });
438
626
  await Promise.all(dispatches);
@@ -471,22 +659,80 @@ var DefaultPushNotificationSender = class {
471
659
  }
472
660
  };
473
661
 
662
+ // src/extensions.ts
663
+ var Extensions = {
664
+ /**
665
+ * Creates new {@link Extensions} from `current` and `additional`.
666
+ * If `current` already contains `additional` it is returned unmodified.
667
+ */
668
+ createFrom: (current, additional) => {
669
+ if (current?.includes(additional)) {
670
+ return current;
671
+ }
672
+ return [...current ?? [], additional];
673
+ },
674
+ /**
675
+ * Creates {@link Extensions} from comma separated extensions identifiers as per
676
+ * https://a2a-protocol.org/latest/specification/#326-service-parameters.
677
+ * Parses the output of `toServiceParameter`.
678
+ */
679
+ parseServiceParameter: (value) => {
680
+ if (!value) {
681
+ return [];
682
+ }
683
+ const unique = new Set(
684
+ value.split(",").map((ext) => ext.trim()).filter((ext) => ext.length > 0)
685
+ );
686
+ return Array.from(unique);
687
+ },
688
+ /**
689
+ * Converts {@link Extensions} to comma separated extensions identifiers as per
690
+ * https://a2a-protocol.org/latest/specification/#326-service-parameters.
691
+ */
692
+ toServiceParameter: (value) => {
693
+ return value.join(",");
694
+ }
695
+ };
696
+
697
+ // src/server/context.ts
698
+ var ServerCallContext = class {
699
+ _requestedExtensions;
700
+ _user;
701
+ _activatedExtensions;
702
+ constructor(requestedExtensions, user) {
703
+ this._requestedExtensions = requestedExtensions;
704
+ this._user = user;
705
+ }
706
+ get user() {
707
+ return this._user;
708
+ }
709
+ get activatedExtensions() {
710
+ return this._activatedExtensions;
711
+ }
712
+ get requestedExtensions() {
713
+ return this._requestedExtensions;
714
+ }
715
+ addActivatedExtension(uri) {
716
+ this._activatedExtensions = Extensions.createFrom(this._activatedExtensions, uri);
717
+ }
718
+ };
719
+
474
720
  // src/server/request_handler/default_request_handler.ts
475
721
  var terminalStates = ["completed", "failed", "canceled", "rejected"];
476
722
  var DefaultRequestHandler = class {
477
723
  agentCard;
478
- extendedAgentCard;
479
724
  taskStore;
480
725
  agentExecutor;
481
726
  eventBusManager;
482
727
  pushNotificationStore;
483
728
  pushNotificationSender;
484
- constructor(agentCard, taskStore, agentExecutor, eventBusManager = new DefaultExecutionEventBusManager(), pushNotificationStore, pushNotificationSender, extendedAgentCard) {
729
+ extendedAgentCardProvider;
730
+ constructor(agentCard, taskStore, agentExecutor, eventBusManager = new DefaultExecutionEventBusManager(), pushNotificationStore, pushNotificationSender, extendedAgentCardProvider) {
485
731
  this.agentCard = agentCard;
486
732
  this.taskStore = taskStore;
487
733
  this.agentExecutor = agentExecutor;
488
734
  this.eventBusManager = eventBusManager;
489
- this.extendedAgentCard = extendedAgentCard;
735
+ this.extendedAgentCardProvider = extendedAgentCardProvider;
490
736
  if (agentCard.capabilities.pushNotifications) {
491
737
  this.pushNotificationStore = pushNotificationStore || new InMemoryPushNotificationStore();
492
738
  this.pushNotificationSender = pushNotificationSender || new DefaultPushNotificationSender(this.pushNotificationStore);
@@ -495,30 +741,42 @@ var DefaultRequestHandler = class {
495
741
  async getAgentCard() {
496
742
  return this.agentCard;
497
743
  }
498
- async getAuthenticatedExtendedAgentCard() {
499
- if (!this.extendedAgentCard) {
744
+ async getAuthenticatedExtendedAgentCard(context) {
745
+ if (!this.agentCard.supportsAuthenticatedExtendedCard) {
746
+ throw A2AError.unsupportedOperation("Agent does not support authenticated extended card.");
747
+ }
748
+ if (!this.extendedAgentCardProvider) {
500
749
  throw A2AError.authenticatedExtendedCardNotConfigured();
501
750
  }
502
- return this.extendedAgentCard;
751
+ if (typeof this.extendedAgentCardProvider === "function") {
752
+ return this.extendedAgentCardProvider(context);
753
+ }
754
+ if (context?.user?.isAuthenticated) {
755
+ return this.extendedAgentCardProvider;
756
+ }
757
+ return this.agentCard;
503
758
  }
504
- async _createRequestContext(incomingMessage, taskId, isStream) {
759
+ async _createRequestContext(incomingMessage, context) {
505
760
  let task;
506
761
  let referenceTasks;
507
762
  if (incomingMessage.taskId) {
508
- task = await this.taskStore.load(incomingMessage.taskId);
763
+ task = await this.taskStore.load(incomingMessage.taskId, context);
509
764
  if (!task) {
510
765
  throw A2AError.taskNotFound(incomingMessage.taskId);
511
766
  }
512
767
  if (terminalStates.includes(task.status.state)) {
513
- throw A2AError.invalidRequest(`Task ${task.id} is in a terminal state (${task.status.state}) and cannot be modified.`);
768
+ throw A2AError.invalidRequest(
769
+ `Task ${task.id} is in a terminal state (${task.status.state}) and cannot be modified.`
770
+ );
514
771
  }
515
772
  task.history = [...task.history || [], incomingMessage];
516
- await this.taskStore.save(task);
773
+ await this.taskStore.save(task, context);
517
774
  }
775
+ const taskId = incomingMessage.taskId || (0, import_uuid.v4)();
518
776
  if (incomingMessage.referenceTaskIds && incomingMessage.referenceTaskIds.length > 0) {
519
777
  referenceTasks = [];
520
778
  for (const refId of incomingMessage.referenceTaskIds) {
521
- const refTask = await this.taskStore.load(refId);
779
+ const refTask = await this.taskStore.load(refId, context);
522
780
  if (refTask) {
523
781
  referenceTasks.push(refTask);
524
782
  } else {
@@ -527,24 +785,33 @@ var DefaultRequestHandler = class {
527
785
  }
528
786
  }
529
787
  const contextId = incomingMessage.contextId || task?.contextId || (0, import_uuid.v4)();
788
+ if (context?.requestedExtensions) {
789
+ const agentCard = await this.getAgentCard();
790
+ const exposedExtensions = new Set(
791
+ agentCard.capabilities.extensions?.map((ext) => ext.uri) || []
792
+ );
793
+ const validExtensions = context.requestedExtensions.filter(
794
+ (extension) => exposedExtensions.has(extension)
795
+ );
796
+ context = new ServerCallContext(validExtensions, context.user);
797
+ }
530
798
  const messageForContext = {
531
799
  ...incomingMessage,
532
- contextId
533
- };
534
- return new RequestContext(
535
- messageForContext,
536
- taskId,
537
800
  contextId,
538
- task,
539
- referenceTasks
540
- );
801
+ taskId
802
+ };
803
+ return new RequestContext(messageForContext, taskId, contextId, task, referenceTasks, context);
541
804
  }
542
- async _processEvents(taskId, resultManager, eventQueue, options) {
805
+ async _processEvents(taskId, resultManager, eventQueue, context, options) {
543
806
  let firstResultSent = false;
544
807
  try {
545
808
  for await (const event of eventQueue.events()) {
546
809
  await resultManager.processEvent(event);
547
- await this._sendPushNotificationIfNeeded(event);
810
+ try {
811
+ await this._sendPushNotificationIfNeeded(event, context);
812
+ } catch (error) {
813
+ console.error(`Error sending push notification: ${error}`);
814
+ }
548
815
  if (options?.firstResultResolver && !firstResultSent) {
549
816
  let firstResult;
550
817
  if (event.kind === "message") {
@@ -559,28 +826,33 @@ var DefaultRequestHandler = class {
559
826
  }
560
827
  }
561
828
  if (options?.firstResultRejector && !firstResultSent) {
562
- options.firstResultRejector(A2AError.internalError("Execution finished before a message or task was produced."));
829
+ options.firstResultRejector(
830
+ A2AError.internalError("Execution finished before a message or task was produced.")
831
+ );
563
832
  }
564
833
  } catch (error) {
565
834
  console.error(`Event processing loop failed for task ${taskId}:`, error);
566
- if (options?.firstResultRejector && !firstResultSent) {
567
- options.firstResultRejector(error);
568
- }
569
- throw error;
835
+ this._handleProcessingError(
836
+ error,
837
+ resultManager,
838
+ firstResultSent,
839
+ taskId,
840
+ options?.firstResultRejector
841
+ );
570
842
  } finally {
571
843
  this.eventBusManager.cleanupByTaskId(taskId);
572
844
  }
573
845
  }
574
- async sendMessage(params) {
846
+ async sendMessage(params, context) {
575
847
  const incomingMessage = params.message;
576
848
  if (!incomingMessage.messageId) {
577
849
  throw A2AError.invalidParams("message.messageId is required.");
578
850
  }
579
851
  const isBlocking = params.configuration?.blocking !== false;
580
- const taskId = incomingMessage.taskId || (0, import_uuid.v4)();
581
- const resultManager = new ResultManager(this.taskStore);
852
+ const resultManager = new ResultManager(this.taskStore, context);
582
853
  resultManager.setContext(incomingMessage);
583
- const requestContext = await this._createRequestContext(incomingMessage, taskId, false);
854
+ const requestContext = await this._createRequestContext(incomingMessage, context);
855
+ const taskId = requestContext.taskId;
584
856
  const finalMessageForAgent = requestContext.userMessage;
585
857
  if (params.configuration?.pushNotificationConfig && this.agentCard.capabilities.pushNotifications) {
586
858
  await this.pushNotificationStore?.save(taskId, params.configuration.pushNotificationConfig);
@@ -625,30 +897,32 @@ var DefaultRequestHandler = class {
625
897
  eventBus.finished();
626
898
  });
627
899
  if (isBlocking) {
628
- await this._processEvents(taskId, resultManager, eventQueue);
900
+ await this._processEvents(taskId, resultManager, eventQueue, context);
629
901
  const finalResult = resultManager.getFinalResult();
630
902
  if (!finalResult) {
631
- throw A2AError.internalError("Agent execution finished without a result, and no task context found.");
903
+ throw A2AError.internalError(
904
+ "Agent execution finished without a result, and no task context found."
905
+ );
632
906
  }
633
907
  return finalResult;
634
908
  } else {
635
909
  return new Promise((resolve, reject) => {
636
- this._processEvents(taskId, resultManager, eventQueue, {
910
+ this._processEvents(taskId, resultManager, eventQueue, context, {
637
911
  firstResultResolver: resolve,
638
912
  firstResultRejector: reject
639
913
  });
640
914
  });
641
915
  }
642
916
  }
643
- async *sendMessageStream(params) {
917
+ async *sendMessageStream(params, context) {
644
918
  const incomingMessage = params.message;
645
919
  if (!incomingMessage.messageId) {
646
920
  throw A2AError.invalidParams("message.messageId is required for streaming.");
647
921
  }
648
- const taskId = incomingMessage.taskId || (0, import_uuid.v4)();
649
- const resultManager = new ResultManager(this.taskStore);
922
+ const resultManager = new ResultManager(this.taskStore, context);
650
923
  resultManager.setContext(incomingMessage);
651
- const requestContext = await this._createRequestContext(incomingMessage, taskId, true);
924
+ const requestContext = await this._createRequestContext(incomingMessage, context);
925
+ const taskId = requestContext.taskId;
652
926
  const finalMessageForAgent = requestContext.userMessage;
653
927
  const eventBus = this.eventBusManager.createOrGetByTaskId(taskId);
654
928
  const eventQueue = new ExecutionEventQueue(eventBus);
@@ -656,7 +930,10 @@ var DefaultRequestHandler = class {
656
930
  await this.pushNotificationStore?.save(taskId, params.configuration.pushNotificationConfig);
657
931
  }
658
932
  this.agentExecutor.execute(requestContext, eventBus).catch((err) => {
659
- console.error(`Agent execution failed for stream message ${finalMessageForAgent.messageId}:`, err);
933
+ console.error(
934
+ `Agent execution failed for stream message ${finalMessageForAgent.messageId}:`,
935
+ err
936
+ );
660
937
  const errorTaskStatus = {
661
938
  kind: "status-update",
662
939
  taskId: requestContext.task?.id || (0, import_uuid.v4)(),
@@ -682,15 +959,15 @@ var DefaultRequestHandler = class {
682
959
  try {
683
960
  for await (const event of eventQueue.events()) {
684
961
  await resultManager.processEvent(event);
685
- await this._sendPushNotificationIfNeeded(event);
962
+ await this._sendPushNotificationIfNeeded(event, context);
686
963
  yield event;
687
964
  }
688
965
  } finally {
689
966
  this.eventBusManager.cleanupByTaskId(taskId);
690
967
  }
691
968
  }
692
- async getTask(params) {
693
- const task = await this.taskStore.load(params.id);
969
+ async getTask(params, context) {
970
+ const task = await this.taskStore.load(params.id, context);
694
971
  if (!task) {
695
972
  throw A2AError.taskNotFound(params.id);
696
973
  }
@@ -703,8 +980,8 @@ var DefaultRequestHandler = class {
703
980
  }
704
981
  return task;
705
982
  }
706
- async cancelTask(params) {
707
- const task = await this.taskStore.load(params.id);
983
+ async cancelTask(params, context) {
984
+ const task = await this.taskStore.load(params.id, context);
708
985
  if (!task) {
709
986
  throw A2AError.taskNotFound(params.id);
710
987
  }
@@ -716,7 +993,12 @@ var DefaultRequestHandler = class {
716
993
  if (eventBus) {
717
994
  const eventQueue = new ExecutionEventQueue(eventBus);
718
995
  await this.agentExecutor.cancelTask(params.id, eventBus);
719
- await this._processEvents(params.id, new ResultManager(this.taskStore), eventQueue);
996
+ await this._processEvents(
997
+ params.id,
998
+ new ResultManager(this.taskStore, context),
999
+ eventQueue,
1000
+ context
1001
+ );
720
1002
  } else {
721
1003
  task.status = {
722
1004
  state: "canceled",
@@ -732,9 +1014,9 @@ var DefaultRequestHandler = class {
732
1014
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
733
1015
  };
734
1016
  task.history = [...task.history || [], task.status.message];
735
- await this.taskStore.save(task);
1017
+ await this.taskStore.save(task, context);
736
1018
  }
737
- const latestTask = await this.taskStore.load(params.id);
1019
+ const latestTask = await this.taskStore.load(params.id, context);
738
1020
  if (!latestTask) {
739
1021
  throw A2AError.internalError(`Task ${params.id} not found after cancellation.`);
740
1022
  }
@@ -743,11 +1025,11 @@ var DefaultRequestHandler = class {
743
1025
  }
744
1026
  return latestTask;
745
1027
  }
746
- async setTaskPushNotificationConfig(params) {
1028
+ async setTaskPushNotificationConfig(params, context) {
747
1029
  if (!this.agentCard.capabilities.pushNotifications) {
748
1030
  throw A2AError.pushNotificationNotSupported();
749
1031
  }
750
- const task = await this.taskStore.load(params.taskId);
1032
+ const task = await this.taskStore.load(params.taskId, context);
751
1033
  if (!task) {
752
1034
  throw A2AError.taskNotFound(params.taskId);
753
1035
  }
@@ -758,11 +1040,11 @@ var DefaultRequestHandler = class {
758
1040
  await this.pushNotificationStore?.save(taskId, pushNotificationConfig);
759
1041
  return params;
760
1042
  }
761
- async getTaskPushNotificationConfig(params) {
1043
+ async getTaskPushNotificationConfig(params, context) {
762
1044
  if (!this.agentCard.capabilities.pushNotifications) {
763
1045
  throw A2AError.pushNotificationNotSupported();
764
1046
  }
765
- const task = await this.taskStore.load(params.id);
1047
+ const task = await this.taskStore.load(params.id, context);
766
1048
  if (!task) {
767
1049
  throw A2AError.taskNotFound(params.id);
768
1050
  }
@@ -778,15 +1060,17 @@ var DefaultRequestHandler = class {
778
1060
  }
779
1061
  const config = configs.find((c) => c.id === configId);
780
1062
  if (!config) {
781
- throw A2AError.internalError(`Push notification config with id '${configId}' not found for task ${params.id}.`);
1063
+ throw A2AError.internalError(
1064
+ `Push notification config with id '${configId}' not found for task ${params.id}.`
1065
+ );
782
1066
  }
783
1067
  return { taskId: params.id, pushNotificationConfig: config };
784
1068
  }
785
- async listTaskPushNotificationConfigs(params) {
1069
+ async listTaskPushNotificationConfigs(params, context) {
786
1070
  if (!this.agentCard.capabilities.pushNotifications) {
787
1071
  throw A2AError.pushNotificationNotSupported();
788
1072
  }
789
- const task = await this.taskStore.load(params.id);
1073
+ const task = await this.taskStore.load(params.id, context);
790
1074
  if (!task) {
791
1075
  throw A2AError.taskNotFound(params.id);
792
1076
  }
@@ -796,22 +1080,22 @@ var DefaultRequestHandler = class {
796
1080
  pushNotificationConfig: config
797
1081
  }));
798
1082
  }
799
- async deleteTaskPushNotificationConfig(params) {
1083
+ async deleteTaskPushNotificationConfig(params, context) {
800
1084
  if (!this.agentCard.capabilities.pushNotifications) {
801
1085
  throw A2AError.pushNotificationNotSupported();
802
1086
  }
803
- const task = await this.taskStore.load(params.id);
1087
+ const task = await this.taskStore.load(params.id, context);
804
1088
  if (!task) {
805
1089
  throw A2AError.taskNotFound(params.id);
806
1090
  }
807
1091
  const { id: taskId, pushNotificationConfigId } = params;
808
1092
  await this.pushNotificationStore?.delete(taskId, pushNotificationConfigId);
809
1093
  }
810
- async *resubscribe(params) {
1094
+ async *resubscribe(params, context) {
811
1095
  if (!this.agentCard.capabilities.streaming) {
812
1096
  throw A2AError.unsupportedOperation("Streaming (and thus resubscription) is not supported.");
813
1097
  }
814
- const task = await this.taskStore.load(params.id);
1098
+ const task = await this.taskStore.load(params.id, context);
815
1099
  if (!task) {
816
1100
  throw A2AError.taskNotFound(params.id);
817
1101
  }
@@ -840,7 +1124,7 @@ var DefaultRequestHandler = class {
840
1124
  eventQueue.stop();
841
1125
  }
842
1126
  }
843
- async _sendPushNotificationIfNeeded(event) {
1127
+ async _sendPushNotificationIfNeeded(event, context) {
844
1128
  if (!this.agentCard.capabilities.pushNotifications) {
845
1129
  return;
846
1130
  }
@@ -855,13 +1139,53 @@ var DefaultRequestHandler = class {
855
1139
  console.error(`Task ID not found for event ${event.kind}.`);
856
1140
  return;
857
1141
  }
858
- const task = await this.taskStore.load(taskId);
1142
+ const task = await this.taskStore.load(taskId, context);
859
1143
  if (!task) {
860
1144
  console.error(`Task ${taskId} not found.`);
861
1145
  return;
862
1146
  }
863
1147
  this.pushNotificationSender?.send(task);
864
1148
  }
1149
+ async _handleProcessingError(error, resultManager, firstResultSent, taskId, firstResultRejector) {
1150
+ if (firstResultRejector && !firstResultSent) {
1151
+ firstResultRejector(error);
1152
+ return;
1153
+ }
1154
+ if (!firstResultRejector) {
1155
+ throw error;
1156
+ }
1157
+ const currentTask = resultManager.getCurrentTask();
1158
+ const errorMessage = error instanceof Error && error.message || "Unknown error";
1159
+ if (currentTask) {
1160
+ const statusUpdateFailed = {
1161
+ taskId: currentTask.id,
1162
+ contextId: currentTask.contextId,
1163
+ status: {
1164
+ state: "failed",
1165
+ message: {
1166
+ kind: "message",
1167
+ role: "agent",
1168
+ messageId: (0, import_uuid.v4)(),
1169
+ parts: [{ kind: "text", text: `Event processing loop failed: ${errorMessage}` }],
1170
+ taskId: currentTask.id,
1171
+ contextId: currentTask.contextId
1172
+ },
1173
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1174
+ },
1175
+ kind: "status-update",
1176
+ final: true
1177
+ };
1178
+ try {
1179
+ await resultManager.processEvent(statusUpdateFailed);
1180
+ } catch (error2) {
1181
+ console.error(
1182
+ `Event processing loop failed for task ${taskId}: ${error2 instanceof Error && error2.message || "Unknown error"}`
1183
+ );
1184
+ }
1185
+ } else {
1186
+ console.error(`Event processing loop failed for task ${taskId}: ${errorMessage}`);
1187
+ }
1188
+ }
865
1189
  };
866
1190
 
867
1191
  // src/server/store.ts
@@ -876,7 +1200,7 @@ var InMemoryTaskStore = class {
876
1200
  }
877
1201
  };
878
1202
 
879
- // src/server/transports/jsonrpc_transport_handler.ts
1203
+ // src/server/transports/jsonrpc/jsonrpc_transport_handler.ts
880
1204
  var JsonRpcTransportHandler = class {
881
1205
  requestHandler;
882
1206
  constructor(requestHandler) {
@@ -887,7 +1211,7 @@ var JsonRpcTransportHandler = class {
887
1211
  * For streaming methods, it returns an AsyncGenerator of JSONRPCResult.
888
1212
  * For non-streaming methods, it returns a Promise of a single JSONRPCMessage (Result or ErrorResponse).
889
1213
  */
890
- async handle(requestBody) {
1214
+ async handle(requestBody, context) {
891
1215
  let rpcRequest;
892
1216
  try {
893
1217
  if (typeof requestBody === "string") {
@@ -901,24 +1225,18 @@ var JsonRpcTransportHandler = class {
901
1225
  throw A2AError.invalidRequest("Invalid JSON-RPC Request.");
902
1226
  }
903
1227
  } catch (error) {
904
- const a2aError = error instanceof A2AError ? error : A2AError.parseError(error.message || "Failed to parse JSON request.");
1228
+ const a2aError = error instanceof A2AError ? error : A2AError.parseError(
1229
+ error instanceof SyntaxError && error.message || "Failed to parse JSON request."
1230
+ );
905
1231
  return {
906
1232
  jsonrpc: "2.0",
907
- id: typeof rpcRequest?.id !== "undefined" ? rpcRequest.id : null,
1233
+ id: rpcRequest?.id !== void 0 ? rpcRequest.id : null,
908
1234
  error: a2aError.toJSONRPCError()
909
1235
  };
910
1236
  }
911
1237
  const { method, id: requestId = null } = rpcRequest;
912
1238
  try {
913
- if (method === "agent/getAuthenticatedExtendedCard") {
914
- const result = await this.requestHandler.getAuthenticatedExtendedAgentCard();
915
- return {
916
- jsonrpc: "2.0",
917
- id: requestId,
918
- result
919
- };
920
- }
921
- if (!this.paramsAreValid(rpcRequest.params)) {
1239
+ if (method !== "agent/getAuthenticatedExtendedCard" && !this.paramsAreValid(rpcRequest.params)) {
922
1240
  throw A2AError.invalidParams(`Invalid method parameters.`);
923
1241
  }
924
1242
  if (method === "message/stream" || method === "tasks/resubscribe") {
@@ -927,8 +1245,8 @@ var JsonRpcTransportHandler = class {
927
1245
  if (!agentCard.capabilities.streaming) {
928
1246
  throw A2AError.unsupportedOperation(`Method ${method} requires streaming capability.`);
929
1247
  }
930
- const agentEventStream = method === "message/stream" ? this.requestHandler.sendMessageStream(params) : this.requestHandler.resubscribe(params);
931
- return async function* jsonRpcEventStream() {
1248
+ const agentEventStream = method === "message/stream" ? this.requestHandler.sendMessageStream(params, context) : this.requestHandler.resubscribe(params, context);
1249
+ return (async function* jsonRpcEventStream() {
932
1250
  try {
933
1251
  for await (const event of agentEventStream) {
934
1252
  yield {
@@ -939,43 +1257,50 @@ var JsonRpcTransportHandler = class {
939
1257
  };
940
1258
  }
941
1259
  } catch (streamError) {
942
- console.error(`Error in agent event stream for ${method} (request ${requestId}):`, streamError);
1260
+ console.error(
1261
+ `Error in agent event stream for ${method} (request ${requestId}):`,
1262
+ streamError
1263
+ );
943
1264
  throw streamError;
944
1265
  }
945
- }();
1266
+ })();
946
1267
  } else {
947
1268
  let result;
948
1269
  switch (method) {
949
1270
  case "message/send":
950
- result = await this.requestHandler.sendMessage(rpcRequest.params);
1271
+ result = await this.requestHandler.sendMessage(rpcRequest.params, context);
951
1272
  break;
952
1273
  case "tasks/get":
953
- result = await this.requestHandler.getTask(rpcRequest.params);
1274
+ result = await this.requestHandler.getTask(rpcRequest.params, context);
954
1275
  break;
955
1276
  case "tasks/cancel":
956
- result = await this.requestHandler.cancelTask(rpcRequest.params);
1277
+ result = await this.requestHandler.cancelTask(rpcRequest.params, context);
957
1278
  break;
958
1279
  case "tasks/pushNotificationConfig/set":
959
1280
  result = await this.requestHandler.setTaskPushNotificationConfig(
960
- rpcRequest.params
1281
+ rpcRequest.params,
1282
+ context
961
1283
  );
962
1284
  break;
963
1285
  case "tasks/pushNotificationConfig/get":
964
1286
  result = await this.requestHandler.getTaskPushNotificationConfig(
965
- rpcRequest.params
1287
+ rpcRequest.params,
1288
+ context
966
1289
  );
967
1290
  break;
968
1291
  case "tasks/pushNotificationConfig/delete":
969
- await this.requestHandler.deleteTaskPushNotificationConfig(
970
- rpcRequest.params
971
- );
1292
+ await this.requestHandler.deleteTaskPushNotificationConfig(rpcRequest.params, context);
972
1293
  result = null;
973
1294
  break;
974
1295
  case "tasks/pushNotificationConfig/list":
975
1296
  result = await this.requestHandler.listTaskPushNotificationConfigs(
976
- rpcRequest.params
1297
+ rpcRequest.params,
1298
+ context
977
1299
  );
978
1300
  break;
1301
+ case "agent/getAuthenticatedExtendedCard":
1302
+ result = await this.requestHandler.getAuthenticatedExtendedAgentCard(context);
1303
+ break;
979
1304
  default:
980
1305
  throw A2AError.methodNotFound(method);
981
1306
  }
@@ -986,7 +1311,14 @@ var JsonRpcTransportHandler = class {
986
1311
  };
987
1312
  }
988
1313
  } catch (error) {
989
- const a2aError = error instanceof A2AError ? error : A2AError.internalError(error.message || "An unexpected error occurred.");
1314
+ let a2aError;
1315
+ if (error instanceof A2AError) {
1316
+ a2aError = error;
1317
+ } else {
1318
+ a2aError = A2AError.internalError(
1319
+ error instanceof Error && error.message || "An unexpected error occurred."
1320
+ );
1321
+ }
990
1322
  return {
991
1323
  jsonrpc: "2.0",
992
1324
  id: requestId,
@@ -1026,6 +1358,16 @@ var JsonRpcTransportHandler = class {
1026
1358
  return true;
1027
1359
  }
1028
1360
  };
1361
+
1362
+ // src/server/authentication/user.ts
1363
+ var UnauthenticatedUser = class {
1364
+ get isAuthenticated() {
1365
+ return false;
1366
+ }
1367
+ get userName() {
1368
+ return "";
1369
+ }
1370
+ };
1029
1371
  // Annotate the CommonJS export names for ESM import in node:
1030
1372
  0 && (module.exports = {
1031
1373
  A2AError,
@@ -1038,5 +1380,7 @@ var JsonRpcTransportHandler = class {
1038
1380
  InMemoryTaskStore,
1039
1381
  JsonRpcTransportHandler,
1040
1382
  RequestContext,
1041
- ResultManager
1383
+ ResultManager,
1384
+ ServerCallContext,
1385
+ UnauthenticatedUser
1042
1386
  });