@mailmodo/a2a 0.3.3 → 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.
@@ -0,0 +1,1386 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/server/index.ts
20
+ var server_exports = {};
21
+ __export(server_exports, {
22
+ A2AError: () => A2AError,
23
+ DefaultExecutionEventBus: () => DefaultExecutionEventBus,
24
+ DefaultExecutionEventBusManager: () => DefaultExecutionEventBusManager,
25
+ DefaultPushNotificationSender: () => DefaultPushNotificationSender,
26
+ DefaultRequestHandler: () => DefaultRequestHandler,
27
+ ExecutionEventQueue: () => ExecutionEventQueue,
28
+ InMemoryPushNotificationStore: () => InMemoryPushNotificationStore,
29
+ InMemoryTaskStore: () => InMemoryTaskStore,
30
+ JsonRpcTransportHandler: () => JsonRpcTransportHandler,
31
+ RequestContext: () => RequestContext,
32
+ ResultManager: () => ResultManager,
33
+ ServerCallContext: () => ServerCallContext,
34
+ UnauthenticatedUser: () => UnauthenticatedUser
35
+ });
36
+ module.exports = __toCommonJS(server_exports);
37
+
38
+ // src/server/agent_execution/request_context.ts
39
+ var RequestContext = class {
40
+ userMessage;
41
+ taskId;
42
+ contextId;
43
+ task;
44
+ referenceTasks;
45
+ context;
46
+ constructor(userMessage, taskId, contextId, task, referenceTasks, context) {
47
+ this.userMessage = userMessage;
48
+ this.taskId = taskId;
49
+ this.contextId = contextId;
50
+ this.task = task;
51
+ this.referenceTasks = referenceTasks;
52
+ this.context = context;
53
+ }
54
+ };
55
+
56
+ // src/server/events/execution_event_bus.ts
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;
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();
72
+ publish(event) {
73
+ this.dispatchEvent(new CustomEventImpl("event", { detail: event }));
74
+ }
75
+ 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 });
245
+ }
246
+ };
247
+
248
+ // src/server/events/execution_event_bus_manager.ts
249
+ var DefaultExecutionEventBusManager = class {
250
+ taskIdToBus = /* @__PURE__ */ new Map();
251
+ /**
252
+ * Creates or retrieves an existing ExecutionEventBus based on the taskId.
253
+ * @param taskId The ID of the task.
254
+ * @returns An instance of ExecutionEventBus.
255
+ */
256
+ createOrGetByTaskId(taskId) {
257
+ if (!this.taskIdToBus.has(taskId)) {
258
+ this.taskIdToBus.set(taskId, new DefaultExecutionEventBus());
259
+ }
260
+ return this.taskIdToBus.get(taskId);
261
+ }
262
+ /**
263
+ * Retrieves an existing ExecutionEventBus based on the taskId.
264
+ * @param taskId The ID of the task.
265
+ * @returns An instance of ExecutionEventBus or undefined if not found.
266
+ */
267
+ getByTaskId(taskId) {
268
+ return this.taskIdToBus.get(taskId);
269
+ }
270
+ /**
271
+ * Removes the event bus for a given taskId.
272
+ * This should be called when an execution flow is complete to free resources.
273
+ * @param taskId The ID of the task.
274
+ */
275
+ cleanupByTaskId(taskId) {
276
+ const bus = this.taskIdToBus.get(taskId);
277
+ if (bus) {
278
+ bus.removeAllListeners();
279
+ }
280
+ this.taskIdToBus.delete(taskId);
281
+ }
282
+ };
283
+
284
+ // src/server/events/execution_event_queue.ts
285
+ var ExecutionEventQueue = class {
286
+ eventBus;
287
+ eventQueue = [];
288
+ resolvePromise;
289
+ stopped = false;
290
+ boundHandleEvent;
291
+ constructor(eventBus) {
292
+ this.eventBus = eventBus;
293
+ this.eventBus.on("event", this.handleEvent);
294
+ this.eventBus.on("finished", this.handleFinished);
295
+ }
296
+ handleEvent = (event) => {
297
+ if (this.stopped) return;
298
+ this.eventQueue.push(event);
299
+ if (this.resolvePromise) {
300
+ this.resolvePromise();
301
+ this.resolvePromise = void 0;
302
+ }
303
+ };
304
+ handleFinished = () => {
305
+ this.stop();
306
+ };
307
+ /**
308
+ * Provides an async generator that yields events from the event bus.
309
+ * Stops when a Message event is received or a TaskStatusUpdateEvent with final=true is received.
310
+ */
311
+ async *events() {
312
+ while (!this.stopped || this.eventQueue.length > 0) {
313
+ if (this.eventQueue.length > 0) {
314
+ const event = this.eventQueue.shift();
315
+ yield event;
316
+ if (event.kind === "message" || event.kind === "status-update" && event.final) {
317
+ this.handleFinished();
318
+ break;
319
+ }
320
+ } else if (!this.stopped) {
321
+ await new Promise((resolve) => {
322
+ this.resolvePromise = resolve;
323
+ });
324
+ }
325
+ }
326
+ }
327
+ /**
328
+ * Stops the event queue from processing further events.
329
+ */
330
+ stop() {
331
+ this.stopped = true;
332
+ if (this.resolvePromise) {
333
+ this.resolvePromise();
334
+ this.resolvePromise = void 0;
335
+ }
336
+ this.eventBus.off("event", this.handleEvent);
337
+ this.eventBus.off("finished", this.handleFinished);
338
+ }
339
+ };
340
+
341
+ // src/server/request_handler/default_request_handler.ts
342
+ var import_uuid = require("uuid");
343
+
344
+ // src/server/error.ts
345
+ var A2AError = class _A2AError extends Error {
346
+ code;
347
+ data;
348
+ taskId;
349
+ // Optional task ID context
350
+ constructor(code, message, data, taskId) {
351
+ super(message);
352
+ this.name = "A2AError";
353
+ this.code = code;
354
+ this.data = data;
355
+ this.taskId = taskId;
356
+ }
357
+ /**
358
+ * Formats the error into a standard JSON-RPC error object structure.
359
+ */
360
+ toJSONRPCError() {
361
+ const errorObject = {
362
+ code: this.code,
363
+ message: this.message
364
+ };
365
+ if (this.data !== void 0) {
366
+ errorObject.data = this.data;
367
+ }
368
+ return errorObject;
369
+ }
370
+ // Static factory methods for common errors
371
+ static parseError(message, data) {
372
+ return new _A2AError(-32700, message, data);
373
+ }
374
+ static invalidRequest(message, data) {
375
+ return new _A2AError(-32600, message, data);
376
+ }
377
+ static methodNotFound(method) {
378
+ return new _A2AError(-32601, `Method not found: ${method}`);
379
+ }
380
+ static invalidParams(message, data) {
381
+ return new _A2AError(-32602, message, data);
382
+ }
383
+ static internalError(message, data) {
384
+ return new _A2AError(-32603, message, data);
385
+ }
386
+ static taskNotFound(taskId) {
387
+ return new _A2AError(-32001, `Task not found: ${taskId}`, void 0, taskId);
388
+ }
389
+ static taskNotCancelable(taskId) {
390
+ return new _A2AError(-32002, `Task not cancelable: ${taskId}`, void 0, taskId);
391
+ }
392
+ static pushNotificationNotSupported() {
393
+ return new _A2AError(-32003, "Push Notification is not supported");
394
+ }
395
+ static unsupportedOperation(operation) {
396
+ return new _A2AError(-32004, `Unsupported operation: ${operation}`);
397
+ }
398
+ static authenticatedExtendedCardNotConfigured() {
399
+ return new _A2AError(-32007, `Extended card not configured.`);
400
+ }
401
+ };
402
+
403
+ // src/server/result_manager.ts
404
+ var ResultManager = class {
405
+ taskStore;
406
+ serverCallContext;
407
+ currentTask;
408
+ latestUserMessage;
409
+ // To add to history if a new task is created
410
+ finalMessageResult;
411
+ // Stores the message if it's the final result
412
+ constructor(taskStore, serverCallContext) {
413
+ this.taskStore = taskStore;
414
+ this.serverCallContext = serverCallContext;
415
+ }
416
+ setContext(latestUserMessage) {
417
+ this.latestUserMessage = latestUserMessage;
418
+ }
419
+ /**
420
+ * Processes an agent execution event and updates the task store.
421
+ * @param event The agent execution event.
422
+ */
423
+ async processEvent(event) {
424
+ if (event.kind === "message") {
425
+ this.finalMessageResult = event;
426
+ } else if (event.kind === "task") {
427
+ const taskEvent = event;
428
+ this.currentTask = { ...taskEvent };
429
+ if (this.latestUserMessage) {
430
+ if (!this.currentTask.history?.find(
431
+ (msg) => msg.messageId === this.latestUserMessage.messageId
432
+ )) {
433
+ this.currentTask.history = [this.latestUserMessage, ...this.currentTask.history || []];
434
+ }
435
+ }
436
+ await this.saveCurrentTask();
437
+ } else if (event.kind === "status-update") {
438
+ const updateEvent = event;
439
+ if (this.currentTask && this.currentTask.id === updateEvent.taskId) {
440
+ this.currentTask.status = updateEvent.status;
441
+ if (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
+ ];
449
+ }
450
+ }
451
+ await this.saveCurrentTask();
452
+ } else if (!this.currentTask && updateEvent.taskId) {
453
+ const loaded = await this.taskStore.load(updateEvent.taskId, this.serverCallContext);
454
+ if (loaded) {
455
+ this.currentTask = loaded;
456
+ this.currentTask.status = updateEvent.status;
457
+ if (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
+ ];
465
+ }
466
+ }
467
+ await this.saveCurrentTask();
468
+ } else {
469
+ console.warn(
470
+ `ResultManager: Received status update for unknown task ${updateEvent.taskId}`
471
+ );
472
+ }
473
+ }
474
+ } else if (event.kind === "artifact-update") {
475
+ const artifactEvent = event;
476
+ if (this.currentTask && this.currentTask.id === artifactEvent.taskId) {
477
+ if (!this.currentTask.artifacts) {
478
+ this.currentTask.artifacts = [];
479
+ }
480
+ const existingArtifactIndex = this.currentTask.artifacts.findIndex(
481
+ (art) => art.artifactId === artifactEvent.artifact.artifactId
482
+ );
483
+ if (existingArtifactIndex !== -1) {
484
+ if (artifactEvent.append) {
485
+ const existingArtifact = this.currentTask.artifacts[existingArtifactIndex];
486
+ existingArtifact.parts.push(...artifactEvent.artifact.parts);
487
+ if (artifactEvent.artifact.description)
488
+ existingArtifact.description = artifactEvent.artifact.description;
489
+ if (artifactEvent.artifact.name) existingArtifact.name = artifactEvent.artifact.name;
490
+ if (artifactEvent.artifact.metadata)
491
+ existingArtifact.metadata = {
492
+ ...existingArtifact.metadata,
493
+ ...artifactEvent.artifact.metadata
494
+ };
495
+ } else {
496
+ this.currentTask.artifacts[existingArtifactIndex] = artifactEvent.artifact;
497
+ }
498
+ } else {
499
+ this.currentTask.artifacts.push(artifactEvent.artifact);
500
+ }
501
+ await this.saveCurrentTask();
502
+ } else if (!this.currentTask && artifactEvent.taskId) {
503
+ const loaded = await this.taskStore.load(artifactEvent.taskId, this.serverCallContext);
504
+ if (loaded) {
505
+ this.currentTask = loaded;
506
+ if (!this.currentTask.artifacts) this.currentTask.artifacts = [];
507
+ const existingArtifactIndex = this.currentTask.artifacts.findIndex(
508
+ (art) => art.artifactId === artifactEvent.artifact.artifactId
509
+ );
510
+ if (existingArtifactIndex !== -1) {
511
+ if (artifactEvent.append) {
512
+ this.currentTask.artifacts[existingArtifactIndex].parts.push(
513
+ ...artifactEvent.artifact.parts
514
+ );
515
+ } else {
516
+ this.currentTask.artifacts[existingArtifactIndex] = artifactEvent.artifact;
517
+ }
518
+ } else {
519
+ this.currentTask.artifacts.push(artifactEvent.artifact);
520
+ }
521
+ await this.saveCurrentTask();
522
+ } else {
523
+ console.warn(
524
+ `ResultManager: Received artifact update for unknown task ${artifactEvent.taskId}`
525
+ );
526
+ }
527
+ }
528
+ }
529
+ }
530
+ async saveCurrentTask() {
531
+ if (this.currentTask) {
532
+ await this.taskStore.save(this.currentTask, this.serverCallContext);
533
+ }
534
+ }
535
+ /**
536
+ * Gets the final result, which could be a Message or a Task.
537
+ * This should be called after the event stream has been fully processed.
538
+ * @returns The final Message or the current Task.
539
+ */
540
+ getFinalResult() {
541
+ if (this.finalMessageResult) {
542
+ return this.finalMessageResult;
543
+ }
544
+ return this.currentTask;
545
+ }
546
+ /**
547
+ * Gets the task currently being managed by this ResultManager instance.
548
+ * This task could be one that was started with or one created during agent execution.
549
+ * @returns The current Task or undefined if no task is active.
550
+ */
551
+ getCurrentTask() {
552
+ return this.currentTask;
553
+ }
554
+ };
555
+
556
+ // src/server/push_notification/push_notification_store.ts
557
+ var InMemoryPushNotificationStore = class {
558
+ store = /* @__PURE__ */ new Map();
559
+ async save(taskId, pushNotificationConfig) {
560
+ const configs = this.store.get(taskId) || [];
561
+ if (!pushNotificationConfig.id) {
562
+ pushNotificationConfig.id = taskId;
563
+ }
564
+ const existingIndex = configs.findIndex((config) => config.id === pushNotificationConfig.id);
565
+ if (existingIndex !== -1) {
566
+ configs.splice(existingIndex, 1);
567
+ }
568
+ configs.push(pushNotificationConfig);
569
+ this.store.set(taskId, configs);
570
+ }
571
+ async load(taskId) {
572
+ const configs = this.store.get(taskId);
573
+ return configs || [];
574
+ }
575
+ async delete(taskId, configId) {
576
+ if (configId === void 0) {
577
+ configId = taskId;
578
+ }
579
+ const configs = this.store.get(taskId);
580
+ if (!configs) {
581
+ return;
582
+ }
583
+ const configIndex = configs.findIndex((config) => config.id === configId);
584
+ if (configIndex !== -1) {
585
+ configs.splice(configIndex, 1);
586
+ }
587
+ if (configs.length === 0) {
588
+ this.store.delete(taskId);
589
+ } else {
590
+ this.store.set(taskId, configs);
591
+ }
592
+ }
593
+ };
594
+
595
+ // src/server/push_notification/default_push_notification_sender.ts
596
+ var DefaultPushNotificationSender = class {
597
+ pushNotificationStore;
598
+ notificationChain;
599
+ options;
600
+ constructor(pushNotificationStore, options = {}) {
601
+ this.pushNotificationStore = pushNotificationStore;
602
+ this.notificationChain = /* @__PURE__ */ new Map();
603
+ this.options = {
604
+ timeout: 5e3,
605
+ tokenHeaderName: "X-A2A-Notification-Token",
606
+ ...options
607
+ };
608
+ }
609
+ async send(task) {
610
+ const pushConfigs = await this.pushNotificationStore.load(task.id);
611
+ if (!pushConfigs || pushConfigs.length === 0) {
612
+ return;
613
+ }
614
+ const lastPromise = this.notificationChain.get(task.id) ?? Promise.resolve();
615
+ const newPromise = lastPromise.then(async () => {
616
+ const dispatches = pushConfigs.map(async (pushConfig) => {
617
+ try {
618
+ await this._dispatchNotification(task, pushConfig);
619
+ } catch (error) {
620
+ console.error(
621
+ `Error sending push notification for task_id=${task.id} to URL: ${pushConfig.url}. Error:`,
622
+ error
623
+ );
624
+ }
625
+ });
626
+ await Promise.all(dispatches);
627
+ });
628
+ this.notificationChain.set(task.id, newPromise);
629
+ newPromise.finally(() => {
630
+ if (this.notificationChain.get(task.id) === newPromise) {
631
+ this.notificationChain.delete(task.id);
632
+ }
633
+ });
634
+ }
635
+ async _dispatchNotification(task, pushConfig) {
636
+ const url = pushConfig.url;
637
+ const controller = new AbortController();
638
+ const timeoutId = setTimeout(() => controller.abort(), this.options.timeout);
639
+ try {
640
+ const headers = {
641
+ "Content-Type": "application/json"
642
+ };
643
+ if (pushConfig.token) {
644
+ headers[this.options.tokenHeaderName] = pushConfig.token;
645
+ }
646
+ const response = await fetch(url, {
647
+ method: "POST",
648
+ headers,
649
+ body: JSON.stringify(task),
650
+ signal: controller.signal
651
+ });
652
+ if (!response.ok) {
653
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
654
+ }
655
+ console.info(`Push notification sent for task_id=${task.id} to URL: ${url}`);
656
+ } finally {
657
+ clearTimeout(timeoutId);
658
+ }
659
+ }
660
+ };
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
+
720
+ // src/server/request_handler/default_request_handler.ts
721
+ var terminalStates = ["completed", "failed", "canceled", "rejected"];
722
+ var DefaultRequestHandler = class {
723
+ agentCard;
724
+ taskStore;
725
+ agentExecutor;
726
+ eventBusManager;
727
+ pushNotificationStore;
728
+ pushNotificationSender;
729
+ extendedAgentCardProvider;
730
+ constructor(agentCard, taskStore, agentExecutor, eventBusManager = new DefaultExecutionEventBusManager(), pushNotificationStore, pushNotificationSender, extendedAgentCardProvider) {
731
+ this.agentCard = agentCard;
732
+ this.taskStore = taskStore;
733
+ this.agentExecutor = agentExecutor;
734
+ this.eventBusManager = eventBusManager;
735
+ this.extendedAgentCardProvider = extendedAgentCardProvider;
736
+ if (agentCard.capabilities.pushNotifications) {
737
+ this.pushNotificationStore = pushNotificationStore || new InMemoryPushNotificationStore();
738
+ this.pushNotificationSender = pushNotificationSender || new DefaultPushNotificationSender(this.pushNotificationStore);
739
+ }
740
+ }
741
+ async getAgentCard() {
742
+ return this.agentCard;
743
+ }
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) {
749
+ throw A2AError.authenticatedExtendedCardNotConfigured();
750
+ }
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;
758
+ }
759
+ async _createRequestContext(incomingMessage, context) {
760
+ let task;
761
+ let referenceTasks;
762
+ if (incomingMessage.taskId) {
763
+ task = await this.taskStore.load(incomingMessage.taskId, context);
764
+ if (!task) {
765
+ throw A2AError.taskNotFound(incomingMessage.taskId);
766
+ }
767
+ if (terminalStates.includes(task.status.state)) {
768
+ throw A2AError.invalidRequest(
769
+ `Task ${task.id} is in a terminal state (${task.status.state}) and cannot be modified.`
770
+ );
771
+ }
772
+ task.history = [...task.history || [], incomingMessage];
773
+ await this.taskStore.save(task, context);
774
+ }
775
+ const taskId = incomingMessage.taskId || (0, import_uuid.v4)();
776
+ if (incomingMessage.referenceTaskIds && incomingMessage.referenceTaskIds.length > 0) {
777
+ referenceTasks = [];
778
+ for (const refId of incomingMessage.referenceTaskIds) {
779
+ const refTask = await this.taskStore.load(refId, context);
780
+ if (refTask) {
781
+ referenceTasks.push(refTask);
782
+ } else {
783
+ console.warn(`Reference task ${refId} not found.`);
784
+ }
785
+ }
786
+ }
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
+ }
798
+ const messageForContext = {
799
+ ...incomingMessage,
800
+ contextId,
801
+ taskId
802
+ };
803
+ return new RequestContext(messageForContext, taskId, contextId, task, referenceTasks, context);
804
+ }
805
+ async _processEvents(taskId, resultManager, eventQueue, context, options) {
806
+ let firstResultSent = false;
807
+ try {
808
+ for await (const event of eventQueue.events()) {
809
+ await resultManager.processEvent(event);
810
+ try {
811
+ await this._sendPushNotificationIfNeeded(event, context);
812
+ } catch (error) {
813
+ console.error(`Error sending push notification: ${error}`);
814
+ }
815
+ if (options?.firstResultResolver && !firstResultSent) {
816
+ let firstResult;
817
+ if (event.kind === "message") {
818
+ firstResult = event;
819
+ } else {
820
+ firstResult = resultManager.getCurrentTask();
821
+ }
822
+ if (firstResult) {
823
+ options.firstResultResolver(firstResult);
824
+ firstResultSent = true;
825
+ }
826
+ }
827
+ }
828
+ if (options?.firstResultRejector && !firstResultSent) {
829
+ options.firstResultRejector(
830
+ A2AError.internalError("Execution finished before a message or task was produced.")
831
+ );
832
+ }
833
+ } catch (error) {
834
+ console.error(`Event processing loop failed for task ${taskId}:`, error);
835
+ this._handleProcessingError(
836
+ error,
837
+ resultManager,
838
+ firstResultSent,
839
+ taskId,
840
+ options?.firstResultRejector
841
+ );
842
+ } finally {
843
+ this.eventBusManager.cleanupByTaskId(taskId);
844
+ }
845
+ }
846
+ async sendMessage(params, context) {
847
+ const incomingMessage = params.message;
848
+ if (!incomingMessage.messageId) {
849
+ throw A2AError.invalidParams("message.messageId is required.");
850
+ }
851
+ const isBlocking = params.configuration?.blocking !== false;
852
+ const resultManager = new ResultManager(this.taskStore, context);
853
+ resultManager.setContext(incomingMessage);
854
+ const requestContext = await this._createRequestContext(incomingMessage, context);
855
+ const taskId = requestContext.taskId;
856
+ const finalMessageForAgent = requestContext.userMessage;
857
+ if (params.configuration?.pushNotificationConfig && this.agentCard.capabilities.pushNotifications) {
858
+ await this.pushNotificationStore?.save(taskId, params.configuration.pushNotificationConfig);
859
+ }
860
+ const eventBus = this.eventBusManager.createOrGetByTaskId(taskId);
861
+ const eventQueue = new ExecutionEventQueue(eventBus);
862
+ this.agentExecutor.execute(requestContext, eventBus).catch((err) => {
863
+ console.error(`Agent execution failed for message ${finalMessageForAgent.messageId}:`, err);
864
+ const errorTask = {
865
+ id: requestContext.task?.id || (0, import_uuid.v4)(),
866
+ // Use existing task ID or generate new
867
+ contextId: finalMessageForAgent.contextId,
868
+ status: {
869
+ state: "failed",
870
+ message: {
871
+ kind: "message",
872
+ role: "agent",
873
+ messageId: (0, import_uuid.v4)(),
874
+ parts: [{ kind: "text", text: `Agent execution error: ${err.message}` }],
875
+ taskId: requestContext.task?.id,
876
+ contextId: finalMessageForAgent.contextId
877
+ },
878
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
879
+ },
880
+ history: requestContext.task?.history ? [...requestContext.task.history] : [],
881
+ kind: "task"
882
+ };
883
+ if (finalMessageForAgent) {
884
+ if (!errorTask.history?.find((m) => m.messageId === finalMessageForAgent.messageId)) {
885
+ errorTask.history?.push(finalMessageForAgent);
886
+ }
887
+ }
888
+ eventBus.publish(errorTask);
889
+ eventBus.publish({
890
+ // And publish a final status update
891
+ kind: "status-update",
892
+ taskId: errorTask.id,
893
+ contextId: errorTask.contextId,
894
+ status: errorTask.status,
895
+ final: true
896
+ });
897
+ eventBus.finished();
898
+ });
899
+ if (isBlocking) {
900
+ await this._processEvents(taskId, resultManager, eventQueue, context);
901
+ const finalResult = resultManager.getFinalResult();
902
+ if (!finalResult) {
903
+ throw A2AError.internalError(
904
+ "Agent execution finished without a result, and no task context found."
905
+ );
906
+ }
907
+ return finalResult;
908
+ } else {
909
+ return new Promise((resolve, reject) => {
910
+ this._processEvents(taskId, resultManager, eventQueue, context, {
911
+ firstResultResolver: resolve,
912
+ firstResultRejector: reject
913
+ });
914
+ });
915
+ }
916
+ }
917
+ async *sendMessageStream(params, context) {
918
+ const incomingMessage = params.message;
919
+ if (!incomingMessage.messageId) {
920
+ throw A2AError.invalidParams("message.messageId is required for streaming.");
921
+ }
922
+ const resultManager = new ResultManager(this.taskStore, context);
923
+ resultManager.setContext(incomingMessage);
924
+ const requestContext = await this._createRequestContext(incomingMessage, context);
925
+ const taskId = requestContext.taskId;
926
+ const finalMessageForAgent = requestContext.userMessage;
927
+ const eventBus = this.eventBusManager.createOrGetByTaskId(taskId);
928
+ const eventQueue = new ExecutionEventQueue(eventBus);
929
+ if (params.configuration?.pushNotificationConfig && this.agentCard.capabilities.pushNotifications) {
930
+ await this.pushNotificationStore?.save(taskId, params.configuration.pushNotificationConfig);
931
+ }
932
+ this.agentExecutor.execute(requestContext, eventBus).catch((err) => {
933
+ console.error(
934
+ `Agent execution failed for stream message ${finalMessageForAgent.messageId}:`,
935
+ err
936
+ );
937
+ const errorTaskStatus = {
938
+ kind: "status-update",
939
+ taskId: requestContext.task?.id || (0, import_uuid.v4)(),
940
+ // Use existing or a placeholder
941
+ contextId: finalMessageForAgent.contextId,
942
+ status: {
943
+ state: "failed",
944
+ message: {
945
+ kind: "message",
946
+ role: "agent",
947
+ messageId: (0, import_uuid.v4)(),
948
+ parts: [{ kind: "text", text: `Agent execution error: ${err.message}` }],
949
+ taskId: requestContext.task?.id,
950
+ contextId: finalMessageForAgent.contextId
951
+ },
952
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
953
+ },
954
+ final: true
955
+ // This will terminate the stream for the client
956
+ };
957
+ eventBus.publish(errorTaskStatus);
958
+ });
959
+ try {
960
+ for await (const event of eventQueue.events()) {
961
+ await resultManager.processEvent(event);
962
+ await this._sendPushNotificationIfNeeded(event, context);
963
+ yield event;
964
+ }
965
+ } finally {
966
+ this.eventBusManager.cleanupByTaskId(taskId);
967
+ }
968
+ }
969
+ async getTask(params, context) {
970
+ const task = await this.taskStore.load(params.id, context);
971
+ if (!task) {
972
+ throw A2AError.taskNotFound(params.id);
973
+ }
974
+ if (params.historyLength !== void 0 && params.historyLength >= 0) {
975
+ if (task.history) {
976
+ task.history = task.history.slice(-params.historyLength);
977
+ }
978
+ } else {
979
+ task.history = [];
980
+ }
981
+ return task;
982
+ }
983
+ async cancelTask(params, context) {
984
+ const task = await this.taskStore.load(params.id, context);
985
+ if (!task) {
986
+ throw A2AError.taskNotFound(params.id);
987
+ }
988
+ const nonCancelableStates = ["completed", "failed", "canceled", "rejected"];
989
+ if (nonCancelableStates.includes(task.status.state)) {
990
+ throw A2AError.taskNotCancelable(params.id);
991
+ }
992
+ const eventBus = this.eventBusManager.getByTaskId(params.id);
993
+ if (eventBus) {
994
+ const eventQueue = new ExecutionEventQueue(eventBus);
995
+ await this.agentExecutor.cancelTask(params.id, eventBus);
996
+ await this._processEvents(
997
+ params.id,
998
+ new ResultManager(this.taskStore, context),
999
+ eventQueue,
1000
+ context
1001
+ );
1002
+ } else {
1003
+ task.status = {
1004
+ state: "canceled",
1005
+ message: {
1006
+ // Optional: Add a system message indicating cancellation
1007
+ kind: "message",
1008
+ role: "agent",
1009
+ messageId: (0, import_uuid.v4)(),
1010
+ parts: [{ kind: "text", text: "Task cancellation requested by user." }],
1011
+ taskId: task.id,
1012
+ contextId: task.contextId
1013
+ },
1014
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1015
+ };
1016
+ task.history = [...task.history || [], task.status.message];
1017
+ await this.taskStore.save(task, context);
1018
+ }
1019
+ const latestTask = await this.taskStore.load(params.id, context);
1020
+ if (!latestTask) {
1021
+ throw A2AError.internalError(`Task ${params.id} not found after cancellation.`);
1022
+ }
1023
+ if (latestTask.status.state != "canceled") {
1024
+ throw A2AError.taskNotCancelable(params.id);
1025
+ }
1026
+ return latestTask;
1027
+ }
1028
+ async setTaskPushNotificationConfig(params, context) {
1029
+ if (!this.agentCard.capabilities.pushNotifications) {
1030
+ throw A2AError.pushNotificationNotSupported();
1031
+ }
1032
+ const task = await this.taskStore.load(params.taskId, context);
1033
+ if (!task) {
1034
+ throw A2AError.taskNotFound(params.taskId);
1035
+ }
1036
+ const { taskId, pushNotificationConfig } = params;
1037
+ if (!pushNotificationConfig.id) {
1038
+ pushNotificationConfig.id = taskId;
1039
+ }
1040
+ await this.pushNotificationStore?.save(taskId, pushNotificationConfig);
1041
+ return params;
1042
+ }
1043
+ async getTaskPushNotificationConfig(params, context) {
1044
+ if (!this.agentCard.capabilities.pushNotifications) {
1045
+ throw A2AError.pushNotificationNotSupported();
1046
+ }
1047
+ const task = await this.taskStore.load(params.id, context);
1048
+ if (!task) {
1049
+ throw A2AError.taskNotFound(params.id);
1050
+ }
1051
+ const configs = await this.pushNotificationStore?.load(params.id) || [];
1052
+ if (configs.length === 0) {
1053
+ throw A2AError.internalError(`Push notification config not found for task ${params.id}.`);
1054
+ }
1055
+ let configId;
1056
+ if ("pushNotificationConfigId" in params && params.pushNotificationConfigId) {
1057
+ configId = params.pushNotificationConfigId;
1058
+ } else {
1059
+ configId = params.id;
1060
+ }
1061
+ const config = configs.find((c) => c.id === configId);
1062
+ if (!config) {
1063
+ throw A2AError.internalError(
1064
+ `Push notification config with id '${configId}' not found for task ${params.id}.`
1065
+ );
1066
+ }
1067
+ return { taskId: params.id, pushNotificationConfig: config };
1068
+ }
1069
+ async listTaskPushNotificationConfigs(params, context) {
1070
+ if (!this.agentCard.capabilities.pushNotifications) {
1071
+ throw A2AError.pushNotificationNotSupported();
1072
+ }
1073
+ const task = await this.taskStore.load(params.id, context);
1074
+ if (!task) {
1075
+ throw A2AError.taskNotFound(params.id);
1076
+ }
1077
+ const configs = await this.pushNotificationStore?.load(params.id) || [];
1078
+ return configs.map((config) => ({
1079
+ taskId: params.id,
1080
+ pushNotificationConfig: config
1081
+ }));
1082
+ }
1083
+ async deleteTaskPushNotificationConfig(params, context) {
1084
+ if (!this.agentCard.capabilities.pushNotifications) {
1085
+ throw A2AError.pushNotificationNotSupported();
1086
+ }
1087
+ const task = await this.taskStore.load(params.id, context);
1088
+ if (!task) {
1089
+ throw A2AError.taskNotFound(params.id);
1090
+ }
1091
+ const { id: taskId, pushNotificationConfigId } = params;
1092
+ await this.pushNotificationStore?.delete(taskId, pushNotificationConfigId);
1093
+ }
1094
+ async *resubscribe(params, context) {
1095
+ if (!this.agentCard.capabilities.streaming) {
1096
+ throw A2AError.unsupportedOperation("Streaming (and thus resubscription) is not supported.");
1097
+ }
1098
+ const task = await this.taskStore.load(params.id, context);
1099
+ if (!task) {
1100
+ throw A2AError.taskNotFound(params.id);
1101
+ }
1102
+ yield task;
1103
+ const finalStates = ["completed", "failed", "canceled", "rejected"];
1104
+ if (finalStates.includes(task.status.state)) {
1105
+ return;
1106
+ }
1107
+ const eventBus = this.eventBusManager.getByTaskId(params.id);
1108
+ if (!eventBus) {
1109
+ console.warn(`Resubscribe: No active event bus for task ${params.id}.`);
1110
+ return;
1111
+ }
1112
+ const eventQueue = new ExecutionEventQueue(eventBus);
1113
+ try {
1114
+ for await (const event of eventQueue.events()) {
1115
+ if (event.kind === "status-update" && event.taskId === params.id) {
1116
+ yield event;
1117
+ } else if (event.kind === "artifact-update" && event.taskId === params.id) {
1118
+ yield event;
1119
+ } else if (event.kind === "task" && event.id === params.id) {
1120
+ yield event;
1121
+ }
1122
+ }
1123
+ } finally {
1124
+ eventQueue.stop();
1125
+ }
1126
+ }
1127
+ async _sendPushNotificationIfNeeded(event, context) {
1128
+ if (!this.agentCard.capabilities.pushNotifications) {
1129
+ return;
1130
+ }
1131
+ let taskId = "";
1132
+ if (event.kind == "task") {
1133
+ const task2 = event;
1134
+ taskId = task2.id;
1135
+ } else {
1136
+ taskId = event.taskId;
1137
+ }
1138
+ if (!taskId) {
1139
+ console.error(`Task ID not found for event ${event.kind}.`);
1140
+ return;
1141
+ }
1142
+ const task = await this.taskStore.load(taskId, context);
1143
+ if (!task) {
1144
+ console.error(`Task ${taskId} not found.`);
1145
+ return;
1146
+ }
1147
+ this.pushNotificationSender?.send(task);
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
+ }
1189
+ };
1190
+
1191
+ // src/server/store.ts
1192
+ var InMemoryTaskStore = class {
1193
+ store = /* @__PURE__ */ new Map();
1194
+ async load(taskId) {
1195
+ const entry = this.store.get(taskId);
1196
+ return entry ? { ...entry } : void 0;
1197
+ }
1198
+ async save(task) {
1199
+ this.store.set(task.id, { ...task });
1200
+ }
1201
+ };
1202
+
1203
+ // src/server/transports/jsonrpc/jsonrpc_transport_handler.ts
1204
+ var JsonRpcTransportHandler = class {
1205
+ requestHandler;
1206
+ constructor(requestHandler) {
1207
+ this.requestHandler = requestHandler;
1208
+ }
1209
+ /**
1210
+ * Handles an incoming JSON-RPC request.
1211
+ * For streaming methods, it returns an AsyncGenerator of JSONRPCResult.
1212
+ * For non-streaming methods, it returns a Promise of a single JSONRPCMessage (Result or ErrorResponse).
1213
+ */
1214
+ async handle(requestBody, context) {
1215
+ let rpcRequest;
1216
+ try {
1217
+ if (typeof requestBody === "string") {
1218
+ rpcRequest = JSON.parse(requestBody);
1219
+ } else if (typeof requestBody === "object" && requestBody !== null) {
1220
+ rpcRequest = requestBody;
1221
+ } else {
1222
+ throw A2AError.parseError("Invalid request body type.");
1223
+ }
1224
+ if (!this.isRequestValid(rpcRequest)) {
1225
+ throw A2AError.invalidRequest("Invalid JSON-RPC Request.");
1226
+ }
1227
+ } catch (error) {
1228
+ const a2aError = error instanceof A2AError ? error : A2AError.parseError(
1229
+ error instanceof SyntaxError && error.message || "Failed to parse JSON request."
1230
+ );
1231
+ return {
1232
+ jsonrpc: "2.0",
1233
+ id: rpcRequest?.id !== void 0 ? rpcRequest.id : null,
1234
+ error: a2aError.toJSONRPCError()
1235
+ };
1236
+ }
1237
+ const { method, id: requestId = null } = rpcRequest;
1238
+ try {
1239
+ if (method !== "agent/getAuthenticatedExtendedCard" && !this.paramsAreValid(rpcRequest.params)) {
1240
+ throw A2AError.invalidParams(`Invalid method parameters.`);
1241
+ }
1242
+ if (method === "message/stream" || method === "tasks/resubscribe") {
1243
+ const params = rpcRequest.params;
1244
+ const agentCard = await this.requestHandler.getAgentCard();
1245
+ if (!agentCard.capabilities.streaming) {
1246
+ throw A2AError.unsupportedOperation(`Method ${method} requires streaming capability.`);
1247
+ }
1248
+ const agentEventStream = method === "message/stream" ? this.requestHandler.sendMessageStream(params, context) : this.requestHandler.resubscribe(params, context);
1249
+ return (async function* jsonRpcEventStream() {
1250
+ try {
1251
+ for await (const event of agentEventStream) {
1252
+ yield {
1253
+ jsonrpc: "2.0",
1254
+ id: requestId,
1255
+ // Use the original request ID for all streamed responses
1256
+ result: event
1257
+ };
1258
+ }
1259
+ } catch (streamError) {
1260
+ console.error(
1261
+ `Error in agent event stream for ${method} (request ${requestId}):`,
1262
+ streamError
1263
+ );
1264
+ throw streamError;
1265
+ }
1266
+ })();
1267
+ } else {
1268
+ let result;
1269
+ switch (method) {
1270
+ case "message/send":
1271
+ result = await this.requestHandler.sendMessage(rpcRequest.params, context);
1272
+ break;
1273
+ case "tasks/get":
1274
+ result = await this.requestHandler.getTask(rpcRequest.params, context);
1275
+ break;
1276
+ case "tasks/cancel":
1277
+ result = await this.requestHandler.cancelTask(rpcRequest.params, context);
1278
+ break;
1279
+ case "tasks/pushNotificationConfig/set":
1280
+ result = await this.requestHandler.setTaskPushNotificationConfig(
1281
+ rpcRequest.params,
1282
+ context
1283
+ );
1284
+ break;
1285
+ case "tasks/pushNotificationConfig/get":
1286
+ result = await this.requestHandler.getTaskPushNotificationConfig(
1287
+ rpcRequest.params,
1288
+ context
1289
+ );
1290
+ break;
1291
+ case "tasks/pushNotificationConfig/delete":
1292
+ await this.requestHandler.deleteTaskPushNotificationConfig(rpcRequest.params, context);
1293
+ result = null;
1294
+ break;
1295
+ case "tasks/pushNotificationConfig/list":
1296
+ result = await this.requestHandler.listTaskPushNotificationConfigs(
1297
+ rpcRequest.params,
1298
+ context
1299
+ );
1300
+ break;
1301
+ case "agent/getAuthenticatedExtendedCard":
1302
+ result = await this.requestHandler.getAuthenticatedExtendedAgentCard(context);
1303
+ break;
1304
+ default:
1305
+ throw A2AError.methodNotFound(method);
1306
+ }
1307
+ return {
1308
+ jsonrpc: "2.0",
1309
+ id: requestId,
1310
+ result
1311
+ };
1312
+ }
1313
+ } catch (error) {
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
+ }
1322
+ return {
1323
+ jsonrpc: "2.0",
1324
+ id: requestId,
1325
+ error: a2aError.toJSONRPCError()
1326
+ };
1327
+ }
1328
+ }
1329
+ // Validates the basic structure of a JSON-RPC request
1330
+ isRequestValid(rpcRequest) {
1331
+ if (rpcRequest.jsonrpc !== "2.0") {
1332
+ return false;
1333
+ }
1334
+ if ("id" in rpcRequest) {
1335
+ const id = rpcRequest.id;
1336
+ const isString = typeof id === "string";
1337
+ const isInteger = typeof id === "number" && Number.isInteger(id);
1338
+ const isNull = id === null;
1339
+ if (!isString && !isInteger && !isNull) {
1340
+ return false;
1341
+ }
1342
+ }
1343
+ if (!rpcRequest.method || typeof rpcRequest.method !== "string") {
1344
+ return false;
1345
+ }
1346
+ return true;
1347
+ }
1348
+ // Validates that params is an object with non-empty string keys
1349
+ paramsAreValid(params) {
1350
+ if (typeof params !== "object" || params === null || Array.isArray(params)) {
1351
+ return false;
1352
+ }
1353
+ for (const key of Object.keys(params)) {
1354
+ if (key === "") {
1355
+ return false;
1356
+ }
1357
+ }
1358
+ return true;
1359
+ }
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
+ };
1371
+ // Annotate the CommonJS export names for ESM import in node:
1372
+ 0 && (module.exports = {
1373
+ A2AError,
1374
+ DefaultExecutionEventBus,
1375
+ DefaultExecutionEventBusManager,
1376
+ DefaultPushNotificationSender,
1377
+ DefaultRequestHandler,
1378
+ ExecutionEventQueue,
1379
+ InMemoryPushNotificationStore,
1380
+ InMemoryTaskStore,
1381
+ JsonRpcTransportHandler,
1382
+ RequestContext,
1383
+ ResultManager,
1384
+ ServerCallContext,
1385
+ UnauthenticatedUser
1386
+ });