@a2a-js/sdk 0.3.5 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +223 -185
- package/dist/a2a_request_handler-B3LxMq3P.d.cts +49 -0
- package/dist/a2a_request_handler-BuP9LgXH.d.ts +49 -0
- package/dist/chunk-3QDLXHKS.js +8 -0
- package/dist/{chunk-SY3G7ITG.js → chunk-LTPINR5K.js} +81 -56
- package/dist/chunk-ZX6KNMCP.js +38 -0
- package/dist/client/index.cjs +1057 -256
- package/dist/client/index.d.cts +419 -48
- package/dist/client/index.d.ts +419 -48
- package/dist/client/index.js +1015 -257
- package/dist/{types-DNKcmF0f.d.cts → extensions-DvruCIzw.d.cts} +28 -1
- package/dist/{types-DNKcmF0f.d.ts → extensions-DvruCIzw.d.ts} +28 -1
- package/dist/index.cjs +42 -2
- package/dist/index.d.cts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +9 -3
- package/dist/server/express/index.cjs +754 -146
- package/dist/server/express/index.d.cts +83 -6
- package/dist/server/express/index.d.ts +83 -6
- package/dist/server/express/index.js +649 -92
- package/dist/server/index.cjs +302 -136
- package/dist/server/index.d.cts +33 -26
- package/dist/server/index.d.ts +33 -26
- package/dist/server/index.js +195 -82
- package/package.json +16 -11
- package/dist/a2a_request_handler-B5t-IxgA.d.ts +0 -17
- package/dist/a2a_request_handler-DUvKWfix.d.cts +0 -17
- package/dist/chunk-67JNQ6TZ.js +0 -6
package/dist/server/index.js
CHANGED
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
import {
|
|
2
2
|
A2AError,
|
|
3
|
-
JsonRpcTransportHandler
|
|
4
|
-
|
|
3
|
+
JsonRpcTransportHandler,
|
|
4
|
+
ServerCallContext,
|
|
5
|
+
UnauthenticatedUser
|
|
6
|
+
} from "../chunk-LTPINR5K.js";
|
|
7
|
+
import "../chunk-ZX6KNMCP.js";
|
|
5
8
|
|
|
6
9
|
// src/server/agent_execution/request_context.ts
|
|
7
10
|
var RequestContext = class {
|
|
8
11
|
userMessage;
|
|
9
|
-
task;
|
|
10
|
-
referenceTasks;
|
|
11
12
|
taskId;
|
|
12
13
|
contextId;
|
|
13
|
-
|
|
14
|
+
task;
|
|
15
|
+
referenceTasks;
|
|
16
|
+
context;
|
|
17
|
+
constructor(userMessage, taskId, contextId, task, referenceTasks, context) {
|
|
14
18
|
this.userMessage = userMessage;
|
|
15
19
|
this.taskId = taskId;
|
|
16
20
|
this.contextId = contextId;
|
|
17
21
|
this.task = task;
|
|
18
22
|
this.referenceTasks = referenceTasks;
|
|
23
|
+
this.context = context;
|
|
19
24
|
}
|
|
20
25
|
};
|
|
21
26
|
|
|
@@ -39,7 +44,7 @@ var DefaultExecutionEventBusManager = class {
|
|
|
39
44
|
/**
|
|
40
45
|
* Creates or retrieves an existing ExecutionEventBus based on the taskId.
|
|
41
46
|
* @param taskId The ID of the task.
|
|
42
|
-
* @returns An instance of
|
|
47
|
+
* @returns An instance of ExecutionEventBus.
|
|
43
48
|
*/
|
|
44
49
|
createOrGetByTaskId(taskId) {
|
|
45
50
|
if (!this.taskIdToBus.has(taskId)) {
|
|
@@ -50,7 +55,7 @@ var DefaultExecutionEventBusManager = class {
|
|
|
50
55
|
/**
|
|
51
56
|
* Retrieves an existing ExecutionEventBus based on the taskId.
|
|
52
57
|
* @param taskId The ID of the task.
|
|
53
|
-
* @returns An instance of
|
|
58
|
+
* @returns An instance of ExecutionEventBus or undefined if not found.
|
|
54
59
|
*/
|
|
55
60
|
getByTaskId(taskId) {
|
|
56
61
|
return this.taskIdToBus.get(taskId);
|
|
@@ -132,13 +137,15 @@ import { v4 as uuidv4 } from "uuid";
|
|
|
132
137
|
// src/server/result_manager.ts
|
|
133
138
|
var ResultManager = class {
|
|
134
139
|
taskStore;
|
|
140
|
+
serverCallContext;
|
|
135
141
|
currentTask;
|
|
136
142
|
latestUserMessage;
|
|
137
143
|
// To add to history if a new task is created
|
|
138
144
|
finalMessageResult;
|
|
139
145
|
// Stores the message if it's the final result
|
|
140
|
-
constructor(taskStore) {
|
|
146
|
+
constructor(taskStore, serverCallContext) {
|
|
141
147
|
this.taskStore = taskStore;
|
|
148
|
+
this.serverCallContext = serverCallContext;
|
|
142
149
|
}
|
|
143
150
|
setContext(latestUserMessage) {
|
|
144
151
|
this.latestUserMessage = latestUserMessage;
|
|
@@ -154,7 +161,9 @@ var ResultManager = class {
|
|
|
154
161
|
const taskEvent = event;
|
|
155
162
|
this.currentTask = { ...taskEvent };
|
|
156
163
|
if (this.latestUserMessage) {
|
|
157
|
-
if (!this.currentTask.history?.find(
|
|
164
|
+
if (!this.currentTask.history?.find(
|
|
165
|
+
(msg) => msg.messageId === this.latestUserMessage.messageId
|
|
166
|
+
)) {
|
|
158
167
|
this.currentTask.history = [this.latestUserMessage, ...this.currentTask.history || []];
|
|
159
168
|
}
|
|
160
169
|
}
|
|
@@ -164,24 +173,36 @@ var ResultManager = class {
|
|
|
164
173
|
if (this.currentTask && this.currentTask.id === updateEvent.taskId) {
|
|
165
174
|
this.currentTask.status = updateEvent.status;
|
|
166
175
|
if (updateEvent.status.message) {
|
|
167
|
-
if (!this.currentTask.history?.find(
|
|
168
|
-
|
|
176
|
+
if (!this.currentTask.history?.find(
|
|
177
|
+
(msg) => msg.messageId === updateEvent.status.message.messageId
|
|
178
|
+
)) {
|
|
179
|
+
this.currentTask.history = [
|
|
180
|
+
...this.currentTask.history || [],
|
|
181
|
+
updateEvent.status.message
|
|
182
|
+
];
|
|
169
183
|
}
|
|
170
184
|
}
|
|
171
185
|
await this.saveCurrentTask();
|
|
172
186
|
} else if (!this.currentTask && updateEvent.taskId) {
|
|
173
|
-
const loaded = await this.taskStore.load(updateEvent.taskId);
|
|
187
|
+
const loaded = await this.taskStore.load(updateEvent.taskId, this.serverCallContext);
|
|
174
188
|
if (loaded) {
|
|
175
189
|
this.currentTask = loaded;
|
|
176
190
|
this.currentTask.status = updateEvent.status;
|
|
177
191
|
if (updateEvent.status.message) {
|
|
178
|
-
if (!this.currentTask.history?.find(
|
|
179
|
-
|
|
192
|
+
if (!this.currentTask.history?.find(
|
|
193
|
+
(msg) => msg.messageId === updateEvent.status.message.messageId
|
|
194
|
+
)) {
|
|
195
|
+
this.currentTask.history = [
|
|
196
|
+
...this.currentTask.history || [],
|
|
197
|
+
updateEvent.status.message
|
|
198
|
+
];
|
|
180
199
|
}
|
|
181
200
|
}
|
|
182
201
|
await this.saveCurrentTask();
|
|
183
202
|
} else {
|
|
184
|
-
console.warn(
|
|
203
|
+
console.warn(
|
|
204
|
+
`ResultManager: Received status update for unknown task ${updateEvent.taskId}`
|
|
205
|
+
);
|
|
185
206
|
}
|
|
186
207
|
}
|
|
187
208
|
} else if (event.kind === "artifact-update") {
|
|
@@ -197,9 +218,14 @@ var ResultManager = class {
|
|
|
197
218
|
if (artifactEvent.append) {
|
|
198
219
|
const existingArtifact = this.currentTask.artifacts[existingArtifactIndex];
|
|
199
220
|
existingArtifact.parts.push(...artifactEvent.artifact.parts);
|
|
200
|
-
if (artifactEvent.artifact.description)
|
|
221
|
+
if (artifactEvent.artifact.description)
|
|
222
|
+
existingArtifact.description = artifactEvent.artifact.description;
|
|
201
223
|
if (artifactEvent.artifact.name) existingArtifact.name = artifactEvent.artifact.name;
|
|
202
|
-
if (artifactEvent.artifact.metadata)
|
|
224
|
+
if (artifactEvent.artifact.metadata)
|
|
225
|
+
existingArtifact.metadata = {
|
|
226
|
+
...existingArtifact.metadata,
|
|
227
|
+
...artifactEvent.artifact.metadata
|
|
228
|
+
};
|
|
203
229
|
} else {
|
|
204
230
|
this.currentTask.artifacts[existingArtifactIndex] = artifactEvent.artifact;
|
|
205
231
|
}
|
|
@@ -208,7 +234,7 @@ var ResultManager = class {
|
|
|
208
234
|
}
|
|
209
235
|
await this.saveCurrentTask();
|
|
210
236
|
} else if (!this.currentTask && artifactEvent.taskId) {
|
|
211
|
-
const loaded = await this.taskStore.load(artifactEvent.taskId);
|
|
237
|
+
const loaded = await this.taskStore.load(artifactEvent.taskId, this.serverCallContext);
|
|
212
238
|
if (loaded) {
|
|
213
239
|
this.currentTask = loaded;
|
|
214
240
|
if (!this.currentTask.artifacts) this.currentTask.artifacts = [];
|
|
@@ -217,7 +243,9 @@ var ResultManager = class {
|
|
|
217
243
|
);
|
|
218
244
|
if (existingArtifactIndex !== -1) {
|
|
219
245
|
if (artifactEvent.append) {
|
|
220
|
-
this.currentTask.artifacts[existingArtifactIndex].parts.push(
|
|
246
|
+
this.currentTask.artifacts[existingArtifactIndex].parts.push(
|
|
247
|
+
...artifactEvent.artifact.parts
|
|
248
|
+
);
|
|
221
249
|
} else {
|
|
222
250
|
this.currentTask.artifacts[existingArtifactIndex] = artifactEvent.artifact;
|
|
223
251
|
}
|
|
@@ -226,14 +254,16 @@ var ResultManager = class {
|
|
|
226
254
|
}
|
|
227
255
|
await this.saveCurrentTask();
|
|
228
256
|
} else {
|
|
229
|
-
console.warn(
|
|
257
|
+
console.warn(
|
|
258
|
+
`ResultManager: Received artifact update for unknown task ${artifactEvent.taskId}`
|
|
259
|
+
);
|
|
230
260
|
}
|
|
231
261
|
}
|
|
232
262
|
}
|
|
233
263
|
}
|
|
234
264
|
async saveCurrentTask() {
|
|
235
265
|
if (this.currentTask) {
|
|
236
|
-
await this.taskStore.save(this.currentTask);
|
|
266
|
+
await this.taskStore.save(this.currentTask, this.serverCallContext);
|
|
237
267
|
}
|
|
238
268
|
}
|
|
239
269
|
/**
|
|
@@ -321,7 +351,10 @@ var DefaultPushNotificationSender = class {
|
|
|
321
351
|
try {
|
|
322
352
|
await this._dispatchNotification(task, pushConfig);
|
|
323
353
|
} catch (error) {
|
|
324
|
-
console.error(
|
|
354
|
+
console.error(
|
|
355
|
+
`Error sending push notification for task_id=${task.id} to URL: ${pushConfig.url}. Error:`,
|
|
356
|
+
error
|
|
357
|
+
);
|
|
325
358
|
}
|
|
326
359
|
});
|
|
327
360
|
await Promise.all(dispatches);
|
|
@@ -364,18 +397,18 @@ var DefaultPushNotificationSender = class {
|
|
|
364
397
|
var terminalStates = ["completed", "failed", "canceled", "rejected"];
|
|
365
398
|
var DefaultRequestHandler = class {
|
|
366
399
|
agentCard;
|
|
367
|
-
extendedAgentCard;
|
|
368
400
|
taskStore;
|
|
369
401
|
agentExecutor;
|
|
370
402
|
eventBusManager;
|
|
371
403
|
pushNotificationStore;
|
|
372
404
|
pushNotificationSender;
|
|
373
|
-
|
|
405
|
+
extendedAgentCardProvider;
|
|
406
|
+
constructor(agentCard, taskStore, agentExecutor, eventBusManager = new DefaultExecutionEventBusManager(), pushNotificationStore, pushNotificationSender, extendedAgentCardProvider) {
|
|
374
407
|
this.agentCard = agentCard;
|
|
375
408
|
this.taskStore = taskStore;
|
|
376
409
|
this.agentExecutor = agentExecutor;
|
|
377
410
|
this.eventBusManager = eventBusManager;
|
|
378
|
-
this.
|
|
411
|
+
this.extendedAgentCardProvider = extendedAgentCardProvider;
|
|
379
412
|
if (agentCard.capabilities.pushNotifications) {
|
|
380
413
|
this.pushNotificationStore = pushNotificationStore || new InMemoryPushNotificationStore();
|
|
381
414
|
this.pushNotificationSender = pushNotificationSender || new DefaultPushNotificationSender(this.pushNotificationStore);
|
|
@@ -384,30 +417,42 @@ var DefaultRequestHandler = class {
|
|
|
384
417
|
async getAgentCard() {
|
|
385
418
|
return this.agentCard;
|
|
386
419
|
}
|
|
387
|
-
async getAuthenticatedExtendedAgentCard() {
|
|
388
|
-
if (!this.
|
|
420
|
+
async getAuthenticatedExtendedAgentCard(context) {
|
|
421
|
+
if (!this.agentCard.supportsAuthenticatedExtendedCard) {
|
|
422
|
+
throw A2AError.unsupportedOperation("Agent does not support authenticated extended card.");
|
|
423
|
+
}
|
|
424
|
+
if (!this.extendedAgentCardProvider) {
|
|
389
425
|
throw A2AError.authenticatedExtendedCardNotConfigured();
|
|
390
426
|
}
|
|
391
|
-
|
|
427
|
+
if (typeof this.extendedAgentCardProvider === "function") {
|
|
428
|
+
return this.extendedAgentCardProvider(context);
|
|
429
|
+
}
|
|
430
|
+
if (context?.user?.isAuthenticated) {
|
|
431
|
+
return this.extendedAgentCardProvider;
|
|
432
|
+
}
|
|
433
|
+
return this.agentCard;
|
|
392
434
|
}
|
|
393
|
-
async _createRequestContext(incomingMessage,
|
|
435
|
+
async _createRequestContext(incomingMessage, context) {
|
|
394
436
|
let task;
|
|
395
437
|
let referenceTasks;
|
|
396
438
|
if (incomingMessage.taskId) {
|
|
397
|
-
task = await this.taskStore.load(incomingMessage.taskId);
|
|
439
|
+
task = await this.taskStore.load(incomingMessage.taskId, context);
|
|
398
440
|
if (!task) {
|
|
399
441
|
throw A2AError.taskNotFound(incomingMessage.taskId);
|
|
400
442
|
}
|
|
401
443
|
if (terminalStates.includes(task.status.state)) {
|
|
402
|
-
throw A2AError.invalidRequest(
|
|
444
|
+
throw A2AError.invalidRequest(
|
|
445
|
+
`Task ${task.id} is in a terminal state (${task.status.state}) and cannot be modified.`
|
|
446
|
+
);
|
|
403
447
|
}
|
|
404
448
|
task.history = [...task.history || [], incomingMessage];
|
|
405
|
-
await this.taskStore.save(task);
|
|
449
|
+
await this.taskStore.save(task, context);
|
|
406
450
|
}
|
|
451
|
+
const taskId = incomingMessage.taskId || uuidv4();
|
|
407
452
|
if (incomingMessage.referenceTaskIds && incomingMessage.referenceTaskIds.length > 0) {
|
|
408
453
|
referenceTasks = [];
|
|
409
454
|
for (const refId of incomingMessage.referenceTaskIds) {
|
|
410
|
-
const refTask = await this.taskStore.load(refId);
|
|
455
|
+
const refTask = await this.taskStore.load(refId, context);
|
|
411
456
|
if (refTask) {
|
|
412
457
|
referenceTasks.push(refTask);
|
|
413
458
|
} else {
|
|
@@ -416,24 +461,33 @@ var DefaultRequestHandler = class {
|
|
|
416
461
|
}
|
|
417
462
|
}
|
|
418
463
|
const contextId = incomingMessage.contextId || task?.contextId || uuidv4();
|
|
464
|
+
if (context?.requestedExtensions) {
|
|
465
|
+
const agentCard = await this.getAgentCard();
|
|
466
|
+
const exposedExtensions = new Set(
|
|
467
|
+
agentCard.capabilities.extensions?.map((ext) => ext.uri) || []
|
|
468
|
+
);
|
|
469
|
+
const validExtensions = context.requestedExtensions.filter(
|
|
470
|
+
(extension) => exposedExtensions.has(extension)
|
|
471
|
+
);
|
|
472
|
+
context = new ServerCallContext(validExtensions, context.user);
|
|
473
|
+
}
|
|
419
474
|
const messageForContext = {
|
|
420
475
|
...incomingMessage,
|
|
421
|
-
contextId
|
|
422
|
-
};
|
|
423
|
-
return new RequestContext(
|
|
424
|
-
messageForContext,
|
|
425
|
-
taskId,
|
|
426
476
|
contextId,
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
);
|
|
477
|
+
taskId
|
|
478
|
+
};
|
|
479
|
+
return new RequestContext(messageForContext, taskId, contextId, task, referenceTasks, context);
|
|
430
480
|
}
|
|
431
|
-
async _processEvents(taskId, resultManager, eventQueue, options) {
|
|
481
|
+
async _processEvents(taskId, resultManager, eventQueue, context, options) {
|
|
432
482
|
let firstResultSent = false;
|
|
433
483
|
try {
|
|
434
484
|
for await (const event of eventQueue.events()) {
|
|
435
485
|
await resultManager.processEvent(event);
|
|
436
|
-
|
|
486
|
+
try {
|
|
487
|
+
await this._sendPushNotificationIfNeeded(event, context);
|
|
488
|
+
} catch (error) {
|
|
489
|
+
console.error(`Error sending push notification: ${error}`);
|
|
490
|
+
}
|
|
437
491
|
if (options?.firstResultResolver && !firstResultSent) {
|
|
438
492
|
let firstResult;
|
|
439
493
|
if (event.kind === "message") {
|
|
@@ -448,28 +502,33 @@ var DefaultRequestHandler = class {
|
|
|
448
502
|
}
|
|
449
503
|
}
|
|
450
504
|
if (options?.firstResultRejector && !firstResultSent) {
|
|
451
|
-
options.firstResultRejector(
|
|
505
|
+
options.firstResultRejector(
|
|
506
|
+
A2AError.internalError("Execution finished before a message or task was produced.")
|
|
507
|
+
);
|
|
452
508
|
}
|
|
453
509
|
} catch (error) {
|
|
454
510
|
console.error(`Event processing loop failed for task ${taskId}:`, error);
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
511
|
+
this._handleProcessingError(
|
|
512
|
+
error,
|
|
513
|
+
resultManager,
|
|
514
|
+
firstResultSent,
|
|
515
|
+
taskId,
|
|
516
|
+
options?.firstResultRejector
|
|
517
|
+
);
|
|
459
518
|
} finally {
|
|
460
519
|
this.eventBusManager.cleanupByTaskId(taskId);
|
|
461
520
|
}
|
|
462
521
|
}
|
|
463
|
-
async sendMessage(params) {
|
|
522
|
+
async sendMessage(params, context) {
|
|
464
523
|
const incomingMessage = params.message;
|
|
465
524
|
if (!incomingMessage.messageId) {
|
|
466
525
|
throw A2AError.invalidParams("message.messageId is required.");
|
|
467
526
|
}
|
|
468
527
|
const isBlocking = params.configuration?.blocking !== false;
|
|
469
|
-
const
|
|
470
|
-
const resultManager = new ResultManager(this.taskStore);
|
|
528
|
+
const resultManager = new ResultManager(this.taskStore, context);
|
|
471
529
|
resultManager.setContext(incomingMessage);
|
|
472
|
-
const requestContext = await this._createRequestContext(incomingMessage,
|
|
530
|
+
const requestContext = await this._createRequestContext(incomingMessage, context);
|
|
531
|
+
const taskId = requestContext.taskId;
|
|
473
532
|
const finalMessageForAgent = requestContext.userMessage;
|
|
474
533
|
if (params.configuration?.pushNotificationConfig && this.agentCard.capabilities.pushNotifications) {
|
|
475
534
|
await this.pushNotificationStore?.save(taskId, params.configuration.pushNotificationConfig);
|
|
@@ -514,30 +573,32 @@ var DefaultRequestHandler = class {
|
|
|
514
573
|
eventBus.finished();
|
|
515
574
|
});
|
|
516
575
|
if (isBlocking) {
|
|
517
|
-
await this._processEvents(taskId, resultManager, eventQueue);
|
|
576
|
+
await this._processEvents(taskId, resultManager, eventQueue, context);
|
|
518
577
|
const finalResult = resultManager.getFinalResult();
|
|
519
578
|
if (!finalResult) {
|
|
520
|
-
throw A2AError.internalError(
|
|
579
|
+
throw A2AError.internalError(
|
|
580
|
+
"Agent execution finished without a result, and no task context found."
|
|
581
|
+
);
|
|
521
582
|
}
|
|
522
583
|
return finalResult;
|
|
523
584
|
} else {
|
|
524
585
|
return new Promise((resolve, reject) => {
|
|
525
|
-
this._processEvents(taskId, resultManager, eventQueue, {
|
|
586
|
+
this._processEvents(taskId, resultManager, eventQueue, context, {
|
|
526
587
|
firstResultResolver: resolve,
|
|
527
588
|
firstResultRejector: reject
|
|
528
589
|
});
|
|
529
590
|
});
|
|
530
591
|
}
|
|
531
592
|
}
|
|
532
|
-
async *sendMessageStream(params) {
|
|
593
|
+
async *sendMessageStream(params, context) {
|
|
533
594
|
const incomingMessage = params.message;
|
|
534
595
|
if (!incomingMessage.messageId) {
|
|
535
596
|
throw A2AError.invalidParams("message.messageId is required for streaming.");
|
|
536
597
|
}
|
|
537
|
-
const
|
|
538
|
-
const resultManager = new ResultManager(this.taskStore);
|
|
598
|
+
const resultManager = new ResultManager(this.taskStore, context);
|
|
539
599
|
resultManager.setContext(incomingMessage);
|
|
540
|
-
const requestContext = await this._createRequestContext(incomingMessage,
|
|
600
|
+
const requestContext = await this._createRequestContext(incomingMessage, context);
|
|
601
|
+
const taskId = requestContext.taskId;
|
|
541
602
|
const finalMessageForAgent = requestContext.userMessage;
|
|
542
603
|
const eventBus = this.eventBusManager.createOrGetByTaskId(taskId);
|
|
543
604
|
const eventQueue = new ExecutionEventQueue(eventBus);
|
|
@@ -545,7 +606,10 @@ var DefaultRequestHandler = class {
|
|
|
545
606
|
await this.pushNotificationStore?.save(taskId, params.configuration.pushNotificationConfig);
|
|
546
607
|
}
|
|
547
608
|
this.agentExecutor.execute(requestContext, eventBus).catch((err) => {
|
|
548
|
-
console.error(
|
|
609
|
+
console.error(
|
|
610
|
+
`Agent execution failed for stream message ${finalMessageForAgent.messageId}:`,
|
|
611
|
+
err
|
|
612
|
+
);
|
|
549
613
|
const errorTaskStatus = {
|
|
550
614
|
kind: "status-update",
|
|
551
615
|
taskId: requestContext.task?.id || uuidv4(),
|
|
@@ -571,15 +635,15 @@ var DefaultRequestHandler = class {
|
|
|
571
635
|
try {
|
|
572
636
|
for await (const event of eventQueue.events()) {
|
|
573
637
|
await resultManager.processEvent(event);
|
|
574
|
-
await this._sendPushNotificationIfNeeded(event);
|
|
638
|
+
await this._sendPushNotificationIfNeeded(event, context);
|
|
575
639
|
yield event;
|
|
576
640
|
}
|
|
577
641
|
} finally {
|
|
578
642
|
this.eventBusManager.cleanupByTaskId(taskId);
|
|
579
643
|
}
|
|
580
644
|
}
|
|
581
|
-
async getTask(params) {
|
|
582
|
-
const task = await this.taskStore.load(params.id);
|
|
645
|
+
async getTask(params, context) {
|
|
646
|
+
const task = await this.taskStore.load(params.id, context);
|
|
583
647
|
if (!task) {
|
|
584
648
|
throw A2AError.taskNotFound(params.id);
|
|
585
649
|
}
|
|
@@ -592,8 +656,8 @@ var DefaultRequestHandler = class {
|
|
|
592
656
|
}
|
|
593
657
|
return task;
|
|
594
658
|
}
|
|
595
|
-
async cancelTask(params) {
|
|
596
|
-
const task = await this.taskStore.load(params.id);
|
|
659
|
+
async cancelTask(params, context) {
|
|
660
|
+
const task = await this.taskStore.load(params.id, context);
|
|
597
661
|
if (!task) {
|
|
598
662
|
throw A2AError.taskNotFound(params.id);
|
|
599
663
|
}
|
|
@@ -605,7 +669,12 @@ var DefaultRequestHandler = class {
|
|
|
605
669
|
if (eventBus) {
|
|
606
670
|
const eventQueue = new ExecutionEventQueue(eventBus);
|
|
607
671
|
await this.agentExecutor.cancelTask(params.id, eventBus);
|
|
608
|
-
await this._processEvents(
|
|
672
|
+
await this._processEvents(
|
|
673
|
+
params.id,
|
|
674
|
+
new ResultManager(this.taskStore, context),
|
|
675
|
+
eventQueue,
|
|
676
|
+
context
|
|
677
|
+
);
|
|
609
678
|
} else {
|
|
610
679
|
task.status = {
|
|
611
680
|
state: "canceled",
|
|
@@ -621,9 +690,9 @@ var DefaultRequestHandler = class {
|
|
|
621
690
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
622
691
|
};
|
|
623
692
|
task.history = [...task.history || [], task.status.message];
|
|
624
|
-
await this.taskStore.save(task);
|
|
693
|
+
await this.taskStore.save(task, context);
|
|
625
694
|
}
|
|
626
|
-
const latestTask = await this.taskStore.load(params.id);
|
|
695
|
+
const latestTask = await this.taskStore.load(params.id, context);
|
|
627
696
|
if (!latestTask) {
|
|
628
697
|
throw A2AError.internalError(`Task ${params.id} not found after cancellation.`);
|
|
629
698
|
}
|
|
@@ -632,11 +701,11 @@ var DefaultRequestHandler = class {
|
|
|
632
701
|
}
|
|
633
702
|
return latestTask;
|
|
634
703
|
}
|
|
635
|
-
async setTaskPushNotificationConfig(params) {
|
|
704
|
+
async setTaskPushNotificationConfig(params, context) {
|
|
636
705
|
if (!this.agentCard.capabilities.pushNotifications) {
|
|
637
706
|
throw A2AError.pushNotificationNotSupported();
|
|
638
707
|
}
|
|
639
|
-
const task = await this.taskStore.load(params.taskId);
|
|
708
|
+
const task = await this.taskStore.load(params.taskId, context);
|
|
640
709
|
if (!task) {
|
|
641
710
|
throw A2AError.taskNotFound(params.taskId);
|
|
642
711
|
}
|
|
@@ -647,11 +716,11 @@ var DefaultRequestHandler = class {
|
|
|
647
716
|
await this.pushNotificationStore?.save(taskId, pushNotificationConfig);
|
|
648
717
|
return params;
|
|
649
718
|
}
|
|
650
|
-
async getTaskPushNotificationConfig(params) {
|
|
719
|
+
async getTaskPushNotificationConfig(params, context) {
|
|
651
720
|
if (!this.agentCard.capabilities.pushNotifications) {
|
|
652
721
|
throw A2AError.pushNotificationNotSupported();
|
|
653
722
|
}
|
|
654
|
-
const task = await this.taskStore.load(params.id);
|
|
723
|
+
const task = await this.taskStore.load(params.id, context);
|
|
655
724
|
if (!task) {
|
|
656
725
|
throw A2AError.taskNotFound(params.id);
|
|
657
726
|
}
|
|
@@ -667,15 +736,17 @@ var DefaultRequestHandler = class {
|
|
|
667
736
|
}
|
|
668
737
|
const config = configs.find((c) => c.id === configId);
|
|
669
738
|
if (!config) {
|
|
670
|
-
throw A2AError.internalError(
|
|
739
|
+
throw A2AError.internalError(
|
|
740
|
+
`Push notification config with id '${configId}' not found for task ${params.id}.`
|
|
741
|
+
);
|
|
671
742
|
}
|
|
672
743
|
return { taskId: params.id, pushNotificationConfig: config };
|
|
673
744
|
}
|
|
674
|
-
async listTaskPushNotificationConfigs(params) {
|
|
745
|
+
async listTaskPushNotificationConfigs(params, context) {
|
|
675
746
|
if (!this.agentCard.capabilities.pushNotifications) {
|
|
676
747
|
throw A2AError.pushNotificationNotSupported();
|
|
677
748
|
}
|
|
678
|
-
const task = await this.taskStore.load(params.id);
|
|
749
|
+
const task = await this.taskStore.load(params.id, context);
|
|
679
750
|
if (!task) {
|
|
680
751
|
throw A2AError.taskNotFound(params.id);
|
|
681
752
|
}
|
|
@@ -685,22 +756,22 @@ var DefaultRequestHandler = class {
|
|
|
685
756
|
pushNotificationConfig: config
|
|
686
757
|
}));
|
|
687
758
|
}
|
|
688
|
-
async deleteTaskPushNotificationConfig(params) {
|
|
759
|
+
async deleteTaskPushNotificationConfig(params, context) {
|
|
689
760
|
if (!this.agentCard.capabilities.pushNotifications) {
|
|
690
761
|
throw A2AError.pushNotificationNotSupported();
|
|
691
762
|
}
|
|
692
|
-
const task = await this.taskStore.load(params.id);
|
|
763
|
+
const task = await this.taskStore.load(params.id, context);
|
|
693
764
|
if (!task) {
|
|
694
765
|
throw A2AError.taskNotFound(params.id);
|
|
695
766
|
}
|
|
696
767
|
const { id: taskId, pushNotificationConfigId } = params;
|
|
697
768
|
await this.pushNotificationStore?.delete(taskId, pushNotificationConfigId);
|
|
698
769
|
}
|
|
699
|
-
async *resubscribe(params) {
|
|
770
|
+
async *resubscribe(params, context) {
|
|
700
771
|
if (!this.agentCard.capabilities.streaming) {
|
|
701
772
|
throw A2AError.unsupportedOperation("Streaming (and thus resubscription) is not supported.");
|
|
702
773
|
}
|
|
703
|
-
const task = await this.taskStore.load(params.id);
|
|
774
|
+
const task = await this.taskStore.load(params.id, context);
|
|
704
775
|
if (!task) {
|
|
705
776
|
throw A2AError.taskNotFound(params.id);
|
|
706
777
|
}
|
|
@@ -729,7 +800,7 @@ var DefaultRequestHandler = class {
|
|
|
729
800
|
eventQueue.stop();
|
|
730
801
|
}
|
|
731
802
|
}
|
|
732
|
-
async _sendPushNotificationIfNeeded(event) {
|
|
803
|
+
async _sendPushNotificationIfNeeded(event, context) {
|
|
733
804
|
if (!this.agentCard.capabilities.pushNotifications) {
|
|
734
805
|
return;
|
|
735
806
|
}
|
|
@@ -744,13 +815,53 @@ var DefaultRequestHandler = class {
|
|
|
744
815
|
console.error(`Task ID not found for event ${event.kind}.`);
|
|
745
816
|
return;
|
|
746
817
|
}
|
|
747
|
-
const task = await this.taskStore.load(taskId);
|
|
818
|
+
const task = await this.taskStore.load(taskId, context);
|
|
748
819
|
if (!task) {
|
|
749
820
|
console.error(`Task ${taskId} not found.`);
|
|
750
821
|
return;
|
|
751
822
|
}
|
|
752
823
|
this.pushNotificationSender?.send(task);
|
|
753
824
|
}
|
|
825
|
+
async _handleProcessingError(error, resultManager, firstResultSent, taskId, firstResultRejector) {
|
|
826
|
+
if (firstResultRejector && !firstResultSent) {
|
|
827
|
+
firstResultRejector(error);
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
if (!firstResultRejector) {
|
|
831
|
+
throw error;
|
|
832
|
+
}
|
|
833
|
+
const currentTask = resultManager.getCurrentTask();
|
|
834
|
+
const errorMessage = error instanceof Error && error.message || "Unknown error";
|
|
835
|
+
if (currentTask) {
|
|
836
|
+
const statusUpdateFailed = {
|
|
837
|
+
taskId: currentTask.id,
|
|
838
|
+
contextId: currentTask.contextId,
|
|
839
|
+
status: {
|
|
840
|
+
state: "failed",
|
|
841
|
+
message: {
|
|
842
|
+
kind: "message",
|
|
843
|
+
role: "agent",
|
|
844
|
+
messageId: uuidv4(),
|
|
845
|
+
parts: [{ kind: "text", text: `Event processing loop failed: ${errorMessage}` }],
|
|
846
|
+
taskId: currentTask.id,
|
|
847
|
+
contextId: currentTask.contextId
|
|
848
|
+
},
|
|
849
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
850
|
+
},
|
|
851
|
+
kind: "status-update",
|
|
852
|
+
final: true
|
|
853
|
+
};
|
|
854
|
+
try {
|
|
855
|
+
await resultManager.processEvent(statusUpdateFailed);
|
|
856
|
+
} catch (error2) {
|
|
857
|
+
console.error(
|
|
858
|
+
`Event processing loop failed for task ${taskId}: ${error2 instanceof Error && error2.message || "Unknown error"}`
|
|
859
|
+
);
|
|
860
|
+
}
|
|
861
|
+
} else {
|
|
862
|
+
console.error(`Event processing loop failed for task ${taskId}: ${errorMessage}`);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
754
865
|
};
|
|
755
866
|
|
|
756
867
|
// src/server/store.ts
|
|
@@ -775,5 +886,7 @@ export {
|
|
|
775
886
|
InMemoryTaskStore,
|
|
776
887
|
JsonRpcTransportHandler,
|
|
777
888
|
RequestContext,
|
|
778
|
-
ResultManager
|
|
889
|
+
ResultManager,
|
|
890
|
+
ServerCallContext,
|
|
891
|
+
UnauthenticatedUser
|
|
779
892
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@a2a-js/sdk",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"description": "Server & Client SDK for Agent2Agent protocol",
|
|
5
|
+
"license": "Apache-2.0",
|
|
5
6
|
"repository": {
|
|
6
7
|
"type": "git",
|
|
7
8
|
"url": "git+https://github.com/a2aproject/a2a-js.git"
|
|
@@ -40,8 +41,7 @@
|
|
|
40
41
|
"README.md"
|
|
41
42
|
],
|
|
42
43
|
"devDependencies": {
|
|
43
|
-
"@
|
|
44
|
-
"@genkit-ai/vertexai": "^1.8.0",
|
|
44
|
+
"@eslint/js": "^9.39.1",
|
|
45
45
|
"@types/chai": "^5.2.2",
|
|
46
46
|
"@types/express": "^5.0.3",
|
|
47
47
|
"@types/mocha": "^10.0.10",
|
|
@@ -50,27 +50,32 @@
|
|
|
50
50
|
"@types/supertest": "^6.0.3",
|
|
51
51
|
"c8": "^10.1.3",
|
|
52
52
|
"chai": "^5.2.0",
|
|
53
|
+
"esbuild": "^0.27.0",
|
|
54
|
+
"eslint": "^9.39.1",
|
|
55
|
+
"eslint-config-prettier": "^10.1.8",
|
|
56
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
53
57
|
"express": "^5.1.0",
|
|
54
|
-
"genkit": "^1.8.0",
|
|
55
58
|
"gts": "^6.0.2",
|
|
56
59
|
"json-schema-to-typescript": "^15.0.4",
|
|
57
60
|
"mocha": "^11.6.0",
|
|
61
|
+
"prettier": "^3.6.2",
|
|
58
62
|
"sinon": "^20.0.0",
|
|
59
63
|
"supertest": "^7.1.4",
|
|
60
64
|
"tsup": "^8.5.0",
|
|
61
65
|
"tsx": "^4.19.3",
|
|
62
|
-
"typescript": "^5.
|
|
66
|
+
"typescript": "^5.9.3",
|
|
67
|
+
"typescript-eslint": "^8.46.4"
|
|
63
68
|
},
|
|
64
69
|
"scripts": {
|
|
65
70
|
"clean": "gts clean",
|
|
66
71
|
"build": "tsup",
|
|
67
|
-
"
|
|
68
|
-
"
|
|
72
|
+
"test": "mocha \"test/**/*.spec.ts\"",
|
|
73
|
+
"lint": "tsc --noEmit && npx eslint .",
|
|
74
|
+
"format:readme": "prettier --write ./README.md",
|
|
75
|
+
"lint:fix": "npx eslint . --fix",
|
|
69
76
|
"coverage": "c8 npm run test",
|
|
70
77
|
"generate": "curl https://raw.githubusercontent.com/google-a2a/A2A/refs/heads/main/specification/json/a2a.json > spec.json && node scripts/generateTypes.js && rm spec.json",
|
|
71
|
-
"
|
|
72
|
-
"agents:movie-agent": "tsx src/samples/agents/movie-agent/index.ts",
|
|
73
|
-
"agents:sample-agent": "tsx src/samples/agents/sample-agent/index.ts"
|
|
78
|
+
"test-build:browser": "esbuild ./dist/client/index.js ./dist/index.js --bundle --platform=browser --outdir=dist/tmp-checks --outbase=./dist"
|
|
74
79
|
},
|
|
75
80
|
"dependencies": {
|
|
76
81
|
"uuid": "^11.1.0"
|
|
@@ -86,4 +91,4 @@
|
|
|
86
91
|
"mocha": {
|
|
87
92
|
"require": "tsx"
|
|
88
93
|
}
|
|
89
|
-
}
|
|
94
|
+
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { ac as AgentCard, w as MessageSendParams, B as Message, aw as Task, aO as TaskStatusUpdateEvent, aQ as TaskArtifactUpdateEvent, V as TaskQueryParams, X as TaskIdParams, Z as TaskPushNotificationConfig, a1 as GetTaskPushNotificationConfigParams, a5 as ListTaskPushNotificationConfigParams, a7 as DeleteTaskPushNotificationConfigParams } from './types-DNKcmF0f.js';
|
|
2
|
-
|
|
3
|
-
interface A2ARequestHandler {
|
|
4
|
-
getAgentCard(): Promise<AgentCard>;
|
|
5
|
-
getAuthenticatedExtendedAgentCard(): Promise<AgentCard>;
|
|
6
|
-
sendMessage(params: MessageSendParams): Promise<Message | Task>;
|
|
7
|
-
sendMessageStream(params: MessageSendParams): AsyncGenerator<Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent, void, undefined>;
|
|
8
|
-
getTask(params: TaskQueryParams): Promise<Task>;
|
|
9
|
-
cancelTask(params: TaskIdParams): Promise<Task>;
|
|
10
|
-
setTaskPushNotificationConfig(params: TaskPushNotificationConfig): Promise<TaskPushNotificationConfig>;
|
|
11
|
-
getTaskPushNotificationConfig(params: TaskIdParams | GetTaskPushNotificationConfigParams): Promise<TaskPushNotificationConfig>;
|
|
12
|
-
listTaskPushNotificationConfigs(params: ListTaskPushNotificationConfigParams): Promise<TaskPushNotificationConfig[]>;
|
|
13
|
-
deleteTaskPushNotificationConfig(params: DeleteTaskPushNotificationConfigParams): Promise<void>;
|
|
14
|
-
resubscribe(params: TaskIdParams): AsyncGenerator<Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent, void, undefined>;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export type { A2ARequestHandler as A };
|