@a2a-js/sdk 0.2.3 → 0.2.5

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,887 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // src/server/index.ts
30
+ var server_exports = {};
31
+ __export(server_exports, {
32
+ A2AError: () => A2AError,
33
+ A2AExpressApp: () => A2AExpressApp,
34
+ DefaultExecutionEventBus: () => DefaultExecutionEventBus,
35
+ DefaultExecutionEventBusManager: () => DefaultExecutionEventBusManager,
36
+ DefaultRequestHandler: () => DefaultRequestHandler,
37
+ ExecutionEventQueue: () => ExecutionEventQueue,
38
+ InMemoryTaskStore: () => InMemoryTaskStore,
39
+ JsonRpcTransportHandler: () => JsonRpcTransportHandler,
40
+ RequestContext: () => RequestContext,
41
+ ResultManager: () => ResultManager
42
+ });
43
+ module.exports = __toCommonJS(server_exports);
44
+
45
+ // src/server/agent_execution/request_context.ts
46
+ var RequestContext = class {
47
+ userMessage;
48
+ task;
49
+ referenceTasks;
50
+ taskId;
51
+ contextId;
52
+ constructor(userMessage, taskId, contextId, task, referenceTasks) {
53
+ this.userMessage = userMessage;
54
+ this.taskId = taskId;
55
+ this.contextId = contextId;
56
+ this.task = task;
57
+ this.referenceTasks = referenceTasks;
58
+ }
59
+ };
60
+
61
+ // src/server/events/execution_event_bus.ts
62
+ var import_events = require("events");
63
+ var DefaultExecutionEventBus = class extends import_events.EventEmitter {
64
+ constructor() {
65
+ super();
66
+ }
67
+ publish(event) {
68
+ this.emit("event", event);
69
+ }
70
+ finished() {
71
+ this.emit("finished");
72
+ }
73
+ };
74
+
75
+ // src/server/events/execution_event_bus_manager.ts
76
+ var DefaultExecutionEventBusManager = class {
77
+ taskIdToBus = /* @__PURE__ */ new Map();
78
+ /**
79
+ * Creates or retrieves an existing ExecutionEventBus based on the taskId.
80
+ * @param taskId The ID of the task.
81
+ * @returns An instance of IExecutionEventBus.
82
+ */
83
+ createOrGetByTaskId(taskId) {
84
+ if (!this.taskIdToBus.has(taskId)) {
85
+ this.taskIdToBus.set(taskId, new DefaultExecutionEventBus());
86
+ }
87
+ return this.taskIdToBus.get(taskId);
88
+ }
89
+ /**
90
+ * Retrieves an existing ExecutionEventBus based on the taskId.
91
+ * @param taskId The ID of the task.
92
+ * @returns An instance of IExecutionEventBus or undefined if not found.
93
+ */
94
+ getByTaskId(taskId) {
95
+ return this.taskIdToBus.get(taskId);
96
+ }
97
+ /**
98
+ * Removes the event bus for a given taskId.
99
+ * This should be called when an execution flow is complete to free resources.
100
+ * @param taskId The ID of the task.
101
+ */
102
+ cleanupByTaskId(taskId) {
103
+ const bus = this.taskIdToBus.get(taskId);
104
+ if (bus) {
105
+ bus.removeAllListeners();
106
+ }
107
+ this.taskIdToBus.delete(taskId);
108
+ }
109
+ };
110
+
111
+ // src/server/events/execution_event_queue.ts
112
+ var ExecutionEventQueue = class {
113
+ eventBus;
114
+ eventQueue = [];
115
+ resolvePromise;
116
+ stopped = false;
117
+ boundHandleEvent;
118
+ constructor(eventBus) {
119
+ this.eventBus = eventBus;
120
+ this.eventBus.on("event", this.handleEvent);
121
+ this.eventBus.on("finished", this.handleFinished);
122
+ }
123
+ handleEvent = (event) => {
124
+ if (this.stopped) return;
125
+ this.eventQueue.push(event);
126
+ if (this.resolvePromise) {
127
+ this.resolvePromise();
128
+ this.resolvePromise = void 0;
129
+ }
130
+ };
131
+ handleFinished = () => {
132
+ this.stop();
133
+ };
134
+ /**
135
+ * Provides an async generator that yields events from the event bus.
136
+ * Stops when a Message event is received or a TaskStatusUpdateEvent with final=true is received.
137
+ */
138
+ async *events() {
139
+ while (!this.stopped || this.eventQueue.length > 0) {
140
+ if (this.eventQueue.length > 0) {
141
+ const event = this.eventQueue.shift();
142
+ yield event;
143
+ if (event.kind === "message" || event.kind === "status-update" && event.final) {
144
+ this.handleFinished();
145
+ break;
146
+ }
147
+ } else if (!this.stopped) {
148
+ await new Promise((resolve) => {
149
+ this.resolvePromise = resolve;
150
+ });
151
+ }
152
+ }
153
+ }
154
+ /**
155
+ * Stops the event queue from processing further events.
156
+ */
157
+ stop() {
158
+ this.stopped = true;
159
+ if (this.resolvePromise) {
160
+ this.resolvePromise();
161
+ this.resolvePromise = void 0;
162
+ }
163
+ this.eventBus.off("event", this.handleEvent);
164
+ this.eventBus.off("finished", this.handleFinished);
165
+ }
166
+ };
167
+
168
+ // src/server/request_handler/default_request_handler.ts
169
+ var import_uuid = require("uuid");
170
+
171
+ // src/server/error.ts
172
+ var A2AError = class _A2AError extends Error {
173
+ code;
174
+ data;
175
+ taskId;
176
+ // Optional task ID context
177
+ constructor(code, message, data, taskId) {
178
+ super(message);
179
+ this.name = "A2AError";
180
+ this.code = code;
181
+ this.data = data;
182
+ this.taskId = taskId;
183
+ }
184
+ /**
185
+ * Formats the error into a standard JSON-RPC error object structure.
186
+ */
187
+ toJSONRPCError() {
188
+ const errorObject = {
189
+ code: this.code,
190
+ message: this.message
191
+ };
192
+ if (this.data !== void 0) {
193
+ errorObject.data = this.data;
194
+ }
195
+ return errorObject;
196
+ }
197
+ // Static factory methods for common errors
198
+ static parseError(message, data) {
199
+ return new _A2AError(-32700, message, data);
200
+ }
201
+ static invalidRequest(message, data) {
202
+ return new _A2AError(-32600, message, data);
203
+ }
204
+ static methodNotFound(method) {
205
+ return new _A2AError(
206
+ -32601,
207
+ `Method not found: ${method}`
208
+ );
209
+ }
210
+ static invalidParams(message, data) {
211
+ return new _A2AError(-32602, message, data);
212
+ }
213
+ static internalError(message, data) {
214
+ return new _A2AError(-32603, message, data);
215
+ }
216
+ static taskNotFound(taskId) {
217
+ return new _A2AError(
218
+ -32001,
219
+ `Task not found: ${taskId}`,
220
+ void 0,
221
+ taskId
222
+ );
223
+ }
224
+ static taskNotCancelable(taskId) {
225
+ return new _A2AError(
226
+ -32002,
227
+ `Task not cancelable: ${taskId}`,
228
+ void 0,
229
+ taskId
230
+ );
231
+ }
232
+ static pushNotificationNotSupported() {
233
+ return new _A2AError(
234
+ -32003,
235
+ "Push Notification is not supported"
236
+ );
237
+ }
238
+ static unsupportedOperation(operation) {
239
+ return new _A2AError(
240
+ -32004,
241
+ `Unsupported operation: ${operation}`
242
+ );
243
+ }
244
+ };
245
+
246
+ // src/server/result_manager.ts
247
+ var ResultManager = class {
248
+ taskStore;
249
+ currentTask;
250
+ latestUserMessage;
251
+ // To add to history if a new task is created
252
+ finalMessageResult;
253
+ // Stores the message if it's the final result
254
+ constructor(taskStore) {
255
+ this.taskStore = taskStore;
256
+ }
257
+ setContext(latestUserMessage) {
258
+ this.latestUserMessage = latestUserMessage;
259
+ }
260
+ /**
261
+ * Processes an agent execution event and updates the task store.
262
+ * @param event The agent execution event.
263
+ */
264
+ async processEvent(event) {
265
+ if (event.kind === "message") {
266
+ this.finalMessageResult = event;
267
+ } else if (event.kind === "task") {
268
+ const taskEvent = event;
269
+ this.currentTask = { ...taskEvent };
270
+ if (this.latestUserMessage) {
271
+ if (!this.currentTask.history?.find((msg) => msg.messageId === this.latestUserMessage.messageId)) {
272
+ this.currentTask.history = [this.latestUserMessage, ...this.currentTask.history || []];
273
+ }
274
+ }
275
+ await this.saveCurrentTask();
276
+ } else if (event.kind === "status-update") {
277
+ const updateEvent = event;
278
+ if (this.currentTask && this.currentTask.id === updateEvent.taskId) {
279
+ this.currentTask.status = updateEvent.status;
280
+ if (updateEvent.status.message) {
281
+ if (!this.currentTask.history?.find((msg) => msg.messageId === updateEvent.status.message.messageId)) {
282
+ this.currentTask.history = [...this.currentTask.history || [], updateEvent.status.message];
283
+ }
284
+ }
285
+ await this.saveCurrentTask();
286
+ } else if (!this.currentTask && updateEvent.taskId) {
287
+ const loaded = await this.taskStore.load(updateEvent.taskId);
288
+ if (loaded) {
289
+ this.currentTask = loaded;
290
+ this.currentTask.status = updateEvent.status;
291
+ if (updateEvent.status.message) {
292
+ if (!this.currentTask.history?.find((msg) => msg.messageId === updateEvent.status.message.messageId)) {
293
+ this.currentTask.history = [...this.currentTask.history || [], updateEvent.status.message];
294
+ }
295
+ }
296
+ await this.saveCurrentTask();
297
+ } else {
298
+ console.warn(`ResultManager: Received status update for unknown task ${updateEvent.taskId}`);
299
+ }
300
+ }
301
+ } else if (event.kind === "artifact-update") {
302
+ const artifactEvent = event;
303
+ if (this.currentTask && this.currentTask.id === artifactEvent.taskId) {
304
+ if (!this.currentTask.artifacts) {
305
+ this.currentTask.artifacts = [];
306
+ }
307
+ const existingArtifactIndex = this.currentTask.artifacts.findIndex(
308
+ (art) => art.artifactId === artifactEvent.artifact.artifactId
309
+ );
310
+ if (existingArtifactIndex !== -1) {
311
+ if (artifactEvent.append) {
312
+ const existingArtifact = this.currentTask.artifacts[existingArtifactIndex];
313
+ existingArtifact.parts.push(...artifactEvent.artifact.parts);
314
+ if (artifactEvent.artifact.description) existingArtifact.description = artifactEvent.artifact.description;
315
+ if (artifactEvent.artifact.name) existingArtifact.name = artifactEvent.artifact.name;
316
+ if (artifactEvent.artifact.metadata) existingArtifact.metadata = { ...existingArtifact.metadata, ...artifactEvent.artifact.metadata };
317
+ } else {
318
+ this.currentTask.artifacts[existingArtifactIndex] = artifactEvent.artifact;
319
+ }
320
+ } else {
321
+ this.currentTask.artifacts.push(artifactEvent.artifact);
322
+ }
323
+ await this.saveCurrentTask();
324
+ } else if (!this.currentTask && artifactEvent.taskId) {
325
+ const loaded = await this.taskStore.load(artifactEvent.taskId);
326
+ if (loaded) {
327
+ this.currentTask = loaded;
328
+ if (!this.currentTask.artifacts) this.currentTask.artifacts = [];
329
+ const existingArtifactIndex = this.currentTask.artifacts.findIndex(
330
+ (art) => art.artifactId === artifactEvent.artifact.artifactId
331
+ );
332
+ if (existingArtifactIndex !== -1) {
333
+ if (artifactEvent.append) {
334
+ this.currentTask.artifacts[existingArtifactIndex].parts.push(...artifactEvent.artifact.parts);
335
+ } else {
336
+ this.currentTask.artifacts[existingArtifactIndex] = artifactEvent.artifact;
337
+ }
338
+ } else {
339
+ this.currentTask.artifacts.push(artifactEvent.artifact);
340
+ }
341
+ await this.saveCurrentTask();
342
+ } else {
343
+ console.warn(`ResultManager: Received artifact update for unknown task ${artifactEvent.taskId}`);
344
+ }
345
+ }
346
+ }
347
+ }
348
+ async saveCurrentTask() {
349
+ if (this.currentTask) {
350
+ await this.taskStore.save(this.currentTask);
351
+ }
352
+ }
353
+ /**
354
+ * Gets the final result, which could be a Message or a Task.
355
+ * This should be called after the event stream has been fully processed.
356
+ * @returns The final Message or the current Task.
357
+ */
358
+ getFinalResult() {
359
+ if (this.finalMessageResult) {
360
+ return this.finalMessageResult;
361
+ }
362
+ return this.currentTask;
363
+ }
364
+ /**
365
+ * Gets the task currently being managed by this ResultManager instance.
366
+ * This task could be one that was started with or one created during agent execution.
367
+ * @returns The current Task or undefined if no task is active.
368
+ */
369
+ getCurrentTask() {
370
+ return this.currentTask;
371
+ }
372
+ };
373
+
374
+ // src/server/request_handler/default_request_handler.ts
375
+ var terminalStates = ["completed", "failed", "canceled", "rejected"];
376
+ var DefaultRequestHandler = class {
377
+ agentCard;
378
+ taskStore;
379
+ agentExecutor;
380
+ eventBusManager;
381
+ // Store for push notification configurations (could be part of TaskStore or separate)
382
+ pushNotificationConfigs = /* @__PURE__ */ new Map();
383
+ constructor(agentCard, taskStore, agentExecutor, eventBusManager = new DefaultExecutionEventBusManager()) {
384
+ this.agentCard = agentCard;
385
+ this.taskStore = taskStore;
386
+ this.agentExecutor = agentExecutor;
387
+ this.eventBusManager = eventBusManager;
388
+ }
389
+ async getAgentCard() {
390
+ return this.agentCard;
391
+ }
392
+ async _createRequestContext(incomingMessage, taskId, isStream) {
393
+ let task;
394
+ let referenceTasks;
395
+ if (incomingMessage.taskId) {
396
+ task = await this.taskStore.load(incomingMessage.taskId);
397
+ if (!task) {
398
+ throw A2AError.taskNotFound(incomingMessage.taskId);
399
+ }
400
+ if (terminalStates.includes(task.status.state)) {
401
+ throw A2AError.invalidRequest(`Task ${task.id} is in a terminal state (${task.status.state}) and cannot be modified.`);
402
+ }
403
+ }
404
+ if (incomingMessage.referenceTaskIds && incomingMessage.referenceTaskIds.length > 0) {
405
+ referenceTasks = [];
406
+ for (const refId of incomingMessage.referenceTaskIds) {
407
+ const refTask = await this.taskStore.load(refId);
408
+ if (refTask) {
409
+ referenceTasks.push(refTask);
410
+ } else {
411
+ console.warn(`Reference task ${refId} not found.`);
412
+ }
413
+ }
414
+ }
415
+ const contextId = incomingMessage.contextId || task?.contextId || (0, import_uuid.v4)();
416
+ const messageForContext = {
417
+ ...incomingMessage,
418
+ contextId
419
+ };
420
+ return new RequestContext(
421
+ messageForContext,
422
+ taskId,
423
+ contextId,
424
+ task,
425
+ referenceTasks
426
+ );
427
+ }
428
+ async _processEvents(taskId, resultManager, eventQueue, options) {
429
+ let firstResultSent = false;
430
+ try {
431
+ for await (const event of eventQueue.events()) {
432
+ await resultManager.processEvent(event);
433
+ if (options?.firstResultResolver && !firstResultSent) {
434
+ if (event.kind === "message" || event.kind === "task") {
435
+ options.firstResultResolver(event);
436
+ firstResultSent = true;
437
+ }
438
+ }
439
+ }
440
+ if (options?.firstResultRejector && !firstResultSent) {
441
+ options.firstResultRejector(A2AError.internalError("Execution finished before a message or task was produced."));
442
+ }
443
+ } catch (error) {
444
+ console.error(`Event processing loop failed for task ${taskId}:`, error);
445
+ if (options?.firstResultRejector && !firstResultSent) {
446
+ options.firstResultRejector(error);
447
+ }
448
+ throw error;
449
+ } finally {
450
+ this.eventBusManager.cleanupByTaskId(taskId);
451
+ }
452
+ }
453
+ async sendMessage(params) {
454
+ const incomingMessage = params.message;
455
+ if (!incomingMessage.messageId) {
456
+ throw A2AError.invalidParams("message.messageId is required.");
457
+ }
458
+ const isBlocking = params.configuration?.blocking !== false;
459
+ const taskId = incomingMessage.taskId || (0, import_uuid.v4)();
460
+ const resultManager = new ResultManager(this.taskStore);
461
+ resultManager.setContext(incomingMessage);
462
+ const requestContext = await this._createRequestContext(incomingMessage, taskId, false);
463
+ const finalMessageForAgent = requestContext.userMessage;
464
+ const eventBus = this.eventBusManager.createOrGetByTaskId(taskId);
465
+ const eventQueue = new ExecutionEventQueue(eventBus);
466
+ this.agentExecutor.execute(requestContext, eventBus).catch((err) => {
467
+ console.error(`Agent execution failed for message ${finalMessageForAgent.messageId}:`, err);
468
+ const errorTask = {
469
+ id: requestContext.task?.id || (0, import_uuid.v4)(),
470
+ // Use existing task ID or generate new
471
+ contextId: finalMessageForAgent.contextId,
472
+ status: {
473
+ state: "failed",
474
+ message: {
475
+ kind: "message",
476
+ role: "agent",
477
+ messageId: (0, import_uuid.v4)(),
478
+ parts: [{ kind: "text", text: `Agent execution error: ${err.message}` }],
479
+ taskId: requestContext.task?.id,
480
+ contextId: finalMessageForAgent.contextId
481
+ },
482
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
483
+ },
484
+ history: requestContext.task?.history ? [...requestContext.task.history] : [],
485
+ kind: "task"
486
+ };
487
+ if (finalMessageForAgent) {
488
+ if (!errorTask.history?.find((m) => m.messageId === finalMessageForAgent.messageId)) {
489
+ errorTask.history?.push(finalMessageForAgent);
490
+ }
491
+ }
492
+ eventBus.publish(errorTask);
493
+ eventBus.publish({
494
+ // And publish a final status update
495
+ kind: "status-update",
496
+ taskId: errorTask.id,
497
+ contextId: errorTask.contextId,
498
+ status: errorTask.status,
499
+ final: true
500
+ });
501
+ eventBus.finished();
502
+ });
503
+ if (isBlocking) {
504
+ await this._processEvents(taskId, resultManager, eventQueue);
505
+ const finalResult = resultManager.getFinalResult();
506
+ if (!finalResult) {
507
+ throw A2AError.internalError("Agent execution finished without a result, and no task context found.");
508
+ }
509
+ return finalResult;
510
+ } else {
511
+ return new Promise((resolve, reject) => {
512
+ this._processEvents(taskId, resultManager, eventQueue, {
513
+ firstResultResolver: resolve,
514
+ firstResultRejector: reject
515
+ });
516
+ });
517
+ }
518
+ }
519
+ async *sendMessageStream(params) {
520
+ const incomingMessage = params.message;
521
+ if (!incomingMessage.messageId) {
522
+ throw A2AError.invalidParams("message.messageId is required for streaming.");
523
+ }
524
+ const taskId = incomingMessage.taskId || (0, import_uuid.v4)();
525
+ const resultManager = new ResultManager(this.taskStore);
526
+ resultManager.setContext(incomingMessage);
527
+ const requestContext = await this._createRequestContext(incomingMessage, taskId, true);
528
+ const finalMessageForAgent = requestContext.userMessage;
529
+ const eventBus = this.eventBusManager.createOrGetByTaskId(taskId);
530
+ const eventQueue = new ExecutionEventQueue(eventBus);
531
+ this.agentExecutor.execute(requestContext, eventBus).catch((err) => {
532
+ console.error(`Agent execution failed for stream message ${finalMessageForAgent.messageId}:`, err);
533
+ const errorTaskStatus = {
534
+ kind: "status-update",
535
+ taskId: requestContext.task?.id || (0, import_uuid.v4)(),
536
+ // Use existing or a placeholder
537
+ contextId: finalMessageForAgent.contextId,
538
+ status: {
539
+ state: "failed",
540
+ message: {
541
+ kind: "message",
542
+ role: "agent",
543
+ messageId: (0, import_uuid.v4)(),
544
+ parts: [{ kind: "text", text: `Agent execution error: ${err.message}` }],
545
+ taskId: requestContext.task?.id,
546
+ contextId: finalMessageForAgent.contextId
547
+ },
548
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
549
+ },
550
+ final: true
551
+ // This will terminate the stream for the client
552
+ };
553
+ eventBus.publish(errorTaskStatus);
554
+ });
555
+ try {
556
+ for await (const event of eventQueue.events()) {
557
+ await resultManager.processEvent(event);
558
+ yield event;
559
+ }
560
+ } finally {
561
+ this.eventBusManager.cleanupByTaskId(taskId);
562
+ }
563
+ }
564
+ async getTask(params) {
565
+ const task = await this.taskStore.load(params.id);
566
+ if (!task) {
567
+ throw A2AError.taskNotFound(params.id);
568
+ }
569
+ if (params.historyLength !== void 0 && params.historyLength >= 0) {
570
+ if (task.history) {
571
+ task.history = task.history.slice(-params.historyLength);
572
+ }
573
+ } else {
574
+ task.history = [];
575
+ }
576
+ return task;
577
+ }
578
+ async cancelTask(params) {
579
+ const task = await this.taskStore.load(params.id);
580
+ if (!task) {
581
+ throw A2AError.taskNotFound(params.id);
582
+ }
583
+ const nonCancelableStates = ["completed", "failed", "canceled", "rejected"];
584
+ if (nonCancelableStates.includes(task.status.state)) {
585
+ throw A2AError.taskNotCancelable(params.id);
586
+ }
587
+ const eventBus = this.eventBusManager.getByTaskId(params.id);
588
+ if (eventBus) {
589
+ await this.agentExecutor.cancelTask(params.id, eventBus);
590
+ } else {
591
+ task.status = {
592
+ state: "canceled",
593
+ message: {
594
+ // Optional: Add a system message indicating cancellation
595
+ kind: "message",
596
+ role: "agent",
597
+ messageId: (0, import_uuid.v4)(),
598
+ parts: [{ kind: "text", text: "Task cancellation requested by user." }],
599
+ taskId: task.id,
600
+ contextId: task.contextId
601
+ },
602
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
603
+ };
604
+ task.history = [...task.history || [], task.status.message];
605
+ await this.taskStore.save(task);
606
+ }
607
+ const latestTask = await this.taskStore.load(params.id);
608
+ return latestTask;
609
+ }
610
+ async setTaskPushNotificationConfig(params) {
611
+ if (!this.agentCard.capabilities.pushNotifications) {
612
+ throw A2AError.pushNotificationNotSupported();
613
+ }
614
+ const taskAndHistory = await this.taskStore.load(params.taskId);
615
+ if (!taskAndHistory) {
616
+ throw A2AError.taskNotFound(params.taskId);
617
+ }
618
+ this.pushNotificationConfigs.set(params.taskId, params.pushNotificationConfig);
619
+ return params;
620
+ }
621
+ async getTaskPushNotificationConfig(params) {
622
+ if (!this.agentCard.capabilities.pushNotifications) {
623
+ throw A2AError.pushNotificationNotSupported();
624
+ }
625
+ const taskAndHistory = await this.taskStore.load(params.id);
626
+ if (!taskAndHistory) {
627
+ throw A2AError.taskNotFound(params.id);
628
+ }
629
+ const config = this.pushNotificationConfigs.get(params.id);
630
+ if (!config) {
631
+ throw A2AError.internalError(`Push notification config not found for task ${params.id}.`);
632
+ }
633
+ return { taskId: params.id, pushNotificationConfig: config };
634
+ }
635
+ async *resubscribe(params) {
636
+ if (!this.agentCard.capabilities.streaming) {
637
+ throw A2AError.unsupportedOperation("Streaming (and thus resubscription) is not supported.");
638
+ }
639
+ const task = await this.taskStore.load(params.id);
640
+ if (!task) {
641
+ throw A2AError.taskNotFound(params.id);
642
+ }
643
+ yield task;
644
+ const finalStates = ["completed", "failed", "canceled", "rejected"];
645
+ if (finalStates.includes(task.status.state)) {
646
+ return;
647
+ }
648
+ const eventBus = this.eventBusManager.getByTaskId(params.id);
649
+ if (!eventBus) {
650
+ console.warn(`Resubscribe: No active event bus for task ${params.id}.`);
651
+ return;
652
+ }
653
+ const eventQueue = new ExecutionEventQueue(eventBus);
654
+ try {
655
+ for await (const event of eventQueue.events()) {
656
+ if (event.kind === "status-update" && event.taskId === params.id) {
657
+ yield event;
658
+ } else if (event.kind === "artifact-update" && event.taskId === params.id) {
659
+ yield event;
660
+ } else if (event.kind === "task" && event.id === params.id) {
661
+ yield event;
662
+ }
663
+ }
664
+ } finally {
665
+ eventQueue.stop();
666
+ }
667
+ }
668
+ };
669
+
670
+ // src/server/store.ts
671
+ var InMemoryTaskStore = class {
672
+ store = /* @__PURE__ */ new Map();
673
+ async load(taskId) {
674
+ const entry = this.store.get(taskId);
675
+ return entry ? { ...entry } : void 0;
676
+ }
677
+ async save(task) {
678
+ this.store.set(task.id, { ...task });
679
+ }
680
+ };
681
+
682
+ // src/server/transports/jsonrpc_transport_handler.ts
683
+ var JsonRpcTransportHandler = class {
684
+ requestHandler;
685
+ constructor(requestHandler) {
686
+ this.requestHandler = requestHandler;
687
+ }
688
+ /**
689
+ * Handles an incoming JSON-RPC request.
690
+ * For streaming methods, it returns an AsyncGenerator of JSONRPCResult.
691
+ * For non-streaming methods, it returns a Promise of a single JSONRPCMessage (Result or ErrorResponse).
692
+ */
693
+ async handle(requestBody) {
694
+ let rpcRequest;
695
+ try {
696
+ if (typeof requestBody === "string") {
697
+ rpcRequest = JSON.parse(requestBody);
698
+ } else if (typeof requestBody === "object" && requestBody !== null) {
699
+ rpcRequest = requestBody;
700
+ } else {
701
+ throw A2AError.parseError("Invalid request body type.");
702
+ }
703
+ if (rpcRequest.jsonrpc !== "2.0" || !rpcRequest.method || typeof rpcRequest.method !== "string") {
704
+ throw A2AError.invalidRequest(
705
+ "Invalid JSON-RPC request structure."
706
+ );
707
+ }
708
+ } catch (error) {
709
+ const a2aError = error instanceof A2AError ? error : A2AError.parseError(error.message || "Failed to parse JSON request.");
710
+ return {
711
+ jsonrpc: "2.0",
712
+ id: typeof rpcRequest?.id !== "undefined" ? rpcRequest.id : null,
713
+ error: a2aError.toJSONRPCError()
714
+ };
715
+ }
716
+ const { method, params = {}, id: requestId = null } = rpcRequest;
717
+ try {
718
+ if (method === "message/stream" || method === "tasks/resubscribe") {
719
+ const agentCard = await this.requestHandler.getAgentCard();
720
+ if (!agentCard.capabilities.streaming) {
721
+ throw A2AError.unsupportedOperation(`Method ${method} requires streaming capability.`);
722
+ }
723
+ const agentEventStream = method === "message/stream" ? this.requestHandler.sendMessageStream(params) : this.requestHandler.resubscribe(params);
724
+ return async function* jsonRpcEventStream() {
725
+ try {
726
+ for await (const event of agentEventStream) {
727
+ yield {
728
+ jsonrpc: "2.0",
729
+ id: requestId,
730
+ // Use the original request ID for all streamed responses
731
+ result: event
732
+ };
733
+ }
734
+ } catch (streamError) {
735
+ console.error(`Error in agent event stream for ${method} (request ${requestId}):`, streamError);
736
+ throw streamError;
737
+ }
738
+ }();
739
+ } else {
740
+ let result;
741
+ switch (method) {
742
+ case "message/send":
743
+ result = await this.requestHandler.sendMessage(params);
744
+ break;
745
+ case "tasks/get":
746
+ result = await this.requestHandler.getTask(params);
747
+ break;
748
+ case "tasks/cancel":
749
+ result = await this.requestHandler.cancelTask(params);
750
+ break;
751
+ case "tasks/pushNotificationConfig/set":
752
+ result = await this.requestHandler.setTaskPushNotificationConfig(
753
+ params
754
+ );
755
+ break;
756
+ case "tasks/pushNotificationConfig/get":
757
+ result = await this.requestHandler.getTaskPushNotificationConfig(
758
+ params
759
+ );
760
+ break;
761
+ default:
762
+ throw A2AError.methodNotFound(method);
763
+ }
764
+ return {
765
+ jsonrpc: "2.0",
766
+ id: requestId,
767
+ result
768
+ };
769
+ }
770
+ } catch (error) {
771
+ const a2aError = error instanceof A2AError ? error : A2AError.internalError(error.message || "An unexpected error occurred.");
772
+ return {
773
+ jsonrpc: "2.0",
774
+ id: requestId,
775
+ error: a2aError.toJSONRPCError()
776
+ };
777
+ }
778
+ }
779
+ };
780
+
781
+ // src/server/a2a_express_app.ts
782
+ var import_express = __toESM(require("express"), 1);
783
+ var A2AExpressApp = class {
784
+ requestHandler;
785
+ // Kept for getAgentCard
786
+ jsonRpcTransportHandler;
787
+ constructor(requestHandler) {
788
+ this.requestHandler = requestHandler;
789
+ this.jsonRpcTransportHandler = new JsonRpcTransportHandler(requestHandler);
790
+ }
791
+ /**
792
+ * Adds A2A routes to an existing Express app.
793
+ * @param app Optional existing Express app.
794
+ * @param baseUrl The base URL for A2A endpoints (e.g., "/a2a/api").
795
+ * @param middlewares Optional array of Express middlewares to apply to the A2A routes.
796
+ * @returns The Express app with A2A routes.
797
+ */
798
+ setupRoutes(app, baseUrl = "", middlewares) {
799
+ const router = import_express.default.Router();
800
+ router.use(import_express.default.json(), ...middlewares ?? []);
801
+ router.get("/.well-known/agent.json", async (req, res) => {
802
+ try {
803
+ const agentCard = await this.requestHandler.getAgentCard();
804
+ res.json(agentCard);
805
+ } catch (error) {
806
+ console.error("Error fetching agent card:", error);
807
+ res.status(500).json({ error: "Failed to retrieve agent card" });
808
+ }
809
+ });
810
+ router.post("/", async (req, res) => {
811
+ try {
812
+ const rpcResponseOrStream = await this.jsonRpcTransportHandler.handle(req.body);
813
+ if (typeof rpcResponseOrStream?.[Symbol.asyncIterator] === "function") {
814
+ const stream = rpcResponseOrStream;
815
+ res.setHeader("Content-Type", "text/event-stream");
816
+ res.setHeader("Cache-Control", "no-cache");
817
+ res.setHeader("Connection", "keep-alive");
818
+ res.flushHeaders();
819
+ try {
820
+ for await (const event of stream) {
821
+ res.write(`id: ${(/* @__PURE__ */ new Date()).getTime()}
822
+ `);
823
+ res.write(`data: ${JSON.stringify(event)}
824
+
825
+ `);
826
+ }
827
+ } catch (streamError) {
828
+ console.error(`Error during SSE streaming (request ${req.body?.id}):`, streamError);
829
+ const a2aError = streamError instanceof A2AError ? streamError : A2AError.internalError(streamError.message || "Streaming error.");
830
+ const errorResponse = {
831
+ jsonrpc: "2.0",
832
+ id: req.body?.id || null,
833
+ // Use original request ID if available
834
+ error: a2aError.toJSONRPCError()
835
+ };
836
+ if (!res.headersSent) {
837
+ res.status(500).json(errorResponse);
838
+ } else {
839
+ res.write(`id: ${(/* @__PURE__ */ new Date()).getTime()}
840
+ `);
841
+ res.write(`event: error
842
+ `);
843
+ res.write(`data: ${JSON.stringify(errorResponse)}
844
+
845
+ `);
846
+ }
847
+ } finally {
848
+ if (!res.writableEnded) {
849
+ res.end();
850
+ }
851
+ }
852
+ } else {
853
+ const rpcResponse = rpcResponseOrStream;
854
+ res.status(200).json(rpcResponse);
855
+ }
856
+ } catch (error) {
857
+ console.error("Unhandled error in A2AExpressApp POST handler:", error);
858
+ const a2aError = error instanceof A2AError ? error : A2AError.internalError("General processing error.");
859
+ const errorResponse = {
860
+ jsonrpc: "2.0",
861
+ id: req.body?.id || null,
862
+ error: a2aError.toJSONRPCError()
863
+ };
864
+ if (!res.headersSent) {
865
+ res.status(500).json(errorResponse);
866
+ } else if (!res.writableEnded) {
867
+ res.end();
868
+ }
869
+ }
870
+ });
871
+ app.use(baseUrl, router);
872
+ return app;
873
+ }
874
+ };
875
+ // Annotate the CommonJS export names for ESM import in node:
876
+ 0 && (module.exports = {
877
+ A2AError,
878
+ A2AExpressApp,
879
+ DefaultExecutionEventBus,
880
+ DefaultExecutionEventBusManager,
881
+ DefaultRequestHandler,
882
+ ExecutionEventQueue,
883
+ InMemoryTaskStore,
884
+ JsonRpcTransportHandler,
885
+ RequestContext,
886
+ ResultManager
887
+ });