@alvin0/ai-agent-sdk-a2a 0.1.0
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/LICENSE +21 -0
- package/README.md +29 -0
- package/dist/cleanup-report-CTjMJ9EU.mjs +146 -0
- package/dist/cleanup-report-CTjMJ9EU.mjs.map +1 -0
- package/dist/client-2bhYYreC.mjs +651 -0
- package/dist/client-2bhYYreC.mjs.map +1 -0
- package/dist/client-DmkHTq-_.d.mts +84 -0
- package/dist/client-DmkHTq-_.d.mts.map +1 -0
- package/dist/client.d.mts +2 -0
- package/dist/client.mjs +3 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +4 -0
- package/dist/server-BX1bnVUG.mjs +577 -0
- package/dist/server-BX1bnVUG.mjs.map +1 -0
- package/dist/server-ejQSEjqI.d.mts +116 -0
- package/dist/server-ejQSEjqI.d.mts.map +1 -0
- package/dist/server.d.mts +2 -0
- package/dist/server.mjs +3 -0
- package/package.json +86 -0
|
@@ -0,0 +1,577 @@
|
|
|
1
|
+
import { i as beginA2AIntegrationOperation, n as a2aErrorCode, r as a2aIntegrationChildLogger, t as cleanupFailure } from "./cleanup-report-CTjMJ9EU.mjs";
|
|
2
|
+
import { A2A_PROTOCOL_VERSION, A2A_PROTOCOL_VERSION as A2A_PROTOCOL_VERSION$1, Role, Role as Role$1, TaskState, TaskState as TaskState$1 } from "@a2a-js/sdk";
|
|
3
|
+
import { createUserMessage, waitForSettlement } from "@alvin0/ai-agent-sdk-core";
|
|
4
|
+
import { AgentEvent, AgentEvent as AgentEvent$1, DefaultExecutionEventBus, DefaultExecutionEventBusManager, DefaultRequestHandler, DefaultRequestHandler as DefaultRequestHandler$1, InMemoryTaskStore, InMemoryTaskStore as InMemoryTaskStore$1, JsonRpcTransportHandler, ServerCallContext } from "@a2a-js/sdk/server";
|
|
5
|
+
import { AgentSession } from "@alvin0/ai-agent-sdk-core/agent";
|
|
6
|
+
|
|
7
|
+
//#region src/common/timeout.ts
|
|
8
|
+
var A2ATeardownTimeoutError = class extends Error {};
|
|
9
|
+
function withTimeout(promise, timeoutMs, message) {
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
const timer = setTimeout(() => reject(new A2ATeardownTimeoutError(message)), timeoutMs);
|
|
12
|
+
promise.then(resolve, reject).finally(() => clearTimeout(timer));
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/server/agent-card.ts
|
|
18
|
+
function createAgentCardFromDefinition(agent, options) {
|
|
19
|
+
const url = endpointUrl(options.url, options.requireHttps === true);
|
|
20
|
+
const securitySchemes = structuredClone(options.securitySchemes ?? {});
|
|
21
|
+
const securityRequirements = structuredClone([...options.securityRequirements ?? []]);
|
|
22
|
+
assertSecurityRequirements(securitySchemes, securityRequirements);
|
|
23
|
+
const description = agent.description ?? `${agent.name} powered by ai-agent-sdk`;
|
|
24
|
+
const skill = {
|
|
25
|
+
id: agent.id,
|
|
26
|
+
name: agent.name,
|
|
27
|
+
description,
|
|
28
|
+
tags: [...options.tags ?? [agent.id]],
|
|
29
|
+
examples: [...options.examples ?? []],
|
|
30
|
+
inputModes: [
|
|
31
|
+
"text/plain",
|
|
32
|
+
"image/*",
|
|
33
|
+
"application/json"
|
|
34
|
+
],
|
|
35
|
+
outputModes: ["text/plain"],
|
|
36
|
+
securityRequirements: structuredClone(securityRequirements)
|
|
37
|
+
};
|
|
38
|
+
return {
|
|
39
|
+
name: agent.name,
|
|
40
|
+
description,
|
|
41
|
+
supportedInterfaces: [{
|
|
42
|
+
url: url.href,
|
|
43
|
+
protocolBinding: options.protocolBinding ?? "JSONRPC",
|
|
44
|
+
tenant: "",
|
|
45
|
+
protocolVersion: A2A_PROTOCOL_VERSION
|
|
46
|
+
}],
|
|
47
|
+
provider: options.provider,
|
|
48
|
+
version: options.version ?? "1.0.0",
|
|
49
|
+
...options.documentationUrl === void 0 ? {} : { documentationUrl: options.documentationUrl },
|
|
50
|
+
capabilities: {
|
|
51
|
+
streaming: true,
|
|
52
|
+
pushNotifications: false,
|
|
53
|
+
extensions: [],
|
|
54
|
+
extendedAgentCard: false
|
|
55
|
+
},
|
|
56
|
+
securitySchemes,
|
|
57
|
+
securityRequirements,
|
|
58
|
+
defaultInputModes: [
|
|
59
|
+
"text/plain",
|
|
60
|
+
"image/*",
|
|
61
|
+
"application/json"
|
|
62
|
+
],
|
|
63
|
+
defaultOutputModes: ["text/plain"],
|
|
64
|
+
skills: [skill],
|
|
65
|
+
signatures: [],
|
|
66
|
+
...options.iconUrl === void 0 ? {} : { iconUrl: options.iconUrl }
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function assertSecurityRequirements(schemes, requirements) {
|
|
70
|
+
for (const requirement of requirements) for (const name of Object.keys(requirement.schemes)) {
|
|
71
|
+
if (schemes[name] === void 0) throw new TypeError(`A2A security requirement references unknown scheme '${name}'`);
|
|
72
|
+
if (schemes[name]?.scheme === void 0) throw new TypeError(`A2A security scheme '${name}' has no concrete definition`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function endpointUrl(value, requireHttps) {
|
|
76
|
+
const url = new URL(value);
|
|
77
|
+
if (url.username.length > 0 || url.password.length > 0) throw new TypeError("A2A interface URL must not contain credentials");
|
|
78
|
+
if (url.protocol !== "https:" && url.protocol !== "http:") throw new TypeError("A2A interface URL must use http or https");
|
|
79
|
+
if (requireHttps && url.protocol !== "https:") throw new TypeError("A2A interface URL must use https under the configured policy");
|
|
80
|
+
return url;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/server/content.ts
|
|
85
|
+
function partsToContent(parts) {
|
|
86
|
+
const blocks = [];
|
|
87
|
+
for (const part of parts) {
|
|
88
|
+
const content = part.content;
|
|
89
|
+
if (content?.$case === "text") blocks.push({
|
|
90
|
+
type: "text",
|
|
91
|
+
text: content.value
|
|
92
|
+
});
|
|
93
|
+
else if (content?.$case === "url" && isImageMediaType(part.mediaType)) blocks.push({
|
|
94
|
+
type: "image",
|
|
95
|
+
source: {
|
|
96
|
+
kind: "url",
|
|
97
|
+
url: content.value
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
else if (content?.$case === "raw" && isImageMediaType(part.mediaType)) blocks.push({
|
|
101
|
+
type: "image",
|
|
102
|
+
source: {
|
|
103
|
+
kind: "base64",
|
|
104
|
+
mediaType: part.mediaType,
|
|
105
|
+
data: bytesToBase64(content.value)
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
else if (content?.$case === "data") blocks.push({
|
|
109
|
+
type: "text",
|
|
110
|
+
text: JSON.stringify(content.value)
|
|
111
|
+
});
|
|
112
|
+
else if (content !== void 0) {
|
|
113
|
+
const location = content.$case === "url" ? `: ${content.value}` : "";
|
|
114
|
+
blocks.push({
|
|
115
|
+
type: "text",
|
|
116
|
+
text: `[A2A attachment${part.mediaType.length === 0 ? "" : ` ${part.mediaType}`}${location}]`
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return blocks.length === 0 ? [{
|
|
121
|
+
type: "text",
|
|
122
|
+
text: ""
|
|
123
|
+
}] : blocks;
|
|
124
|
+
}
|
|
125
|
+
function isImageMediaType(value) {
|
|
126
|
+
return value === "image/jpeg" || value === "image/png" || value === "image/gif" || value === "image/webp";
|
|
127
|
+
}
|
|
128
|
+
function bytesToBase64(value) {
|
|
129
|
+
let binary = "";
|
|
130
|
+
for (let offset = 0; offset < value.length; offset += 32768) binary += String.fromCharCode(...value.subarray(offset, offset + 32768));
|
|
131
|
+
return btoa(binary);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region src/server/session-options.ts
|
|
136
|
+
function snapshotSessionOptions(options) {
|
|
137
|
+
return Object.freeze({
|
|
138
|
+
...options,
|
|
139
|
+
...options.historyLimits === void 0 ? {} : { historyLimits: Object.freeze({ ...options.historyLimits }) },
|
|
140
|
+
...options.runtimeLimits === void 0 ? {} : { runtimeLimits: Object.freeze({ ...options.runtimeLimits }) },
|
|
141
|
+
...Array.isArray(options.tools) ? { tools: Object.freeze([...options.tools]) } : {},
|
|
142
|
+
...options.skills === void 0 ? {} : { skills: Object.freeze([...options.skills]) },
|
|
143
|
+
...options.interceptors === void 0 ? {} : { interceptors: Object.freeze([...options.interceptors]) },
|
|
144
|
+
...options.hooks === void 0 ? {} : { hooks: Object.freeze({ ...options.hooks }) },
|
|
145
|
+
...options.compaction === void 0 || options.compaction === false ? {} : { compaction: Object.freeze({ ...options.compaction }) },
|
|
146
|
+
...options.trace === void 0 ? {} : { trace: Object.freeze({ ...options.trace }) },
|
|
147
|
+
...options.team === void 0 ? {} : { team: Object.freeze({ ...options.team }) }
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
//#endregion
|
|
152
|
+
//#region src/server.ts
|
|
153
|
+
/**
|
|
154
|
+
* Adapt a provider-neutral DefinedAgent to the official A2A AgentExecutor contract.
|
|
155
|
+
* Sessions are retained by A2A contextId, so protocol follow-ups preserve history.
|
|
156
|
+
*/
|
|
157
|
+
var DefinedAgentA2AExecutor = class {
|
|
158
|
+
options;
|
|
159
|
+
sessions = /* @__PURE__ */ new Map();
|
|
160
|
+
running = /* @__PURE__ */ new Map();
|
|
161
|
+
maxSessions;
|
|
162
|
+
maxRunningTasks;
|
|
163
|
+
maxTasksPerSession;
|
|
164
|
+
sessionTtlMs;
|
|
165
|
+
maxInputBytes;
|
|
166
|
+
maxOutputBytes;
|
|
167
|
+
disposeTimeoutMs;
|
|
168
|
+
taskTimeoutMs;
|
|
169
|
+
observerTimeoutMs;
|
|
170
|
+
disposed = false;
|
|
171
|
+
disposeTask;
|
|
172
|
+
disposeReport;
|
|
173
|
+
constructor(options) {
|
|
174
|
+
if (options.registry === void 0 && options.createSession === void 0) throw new TypeError("A2A executor requires registry or createSession");
|
|
175
|
+
this.options = Object.freeze({
|
|
176
|
+
...options,
|
|
177
|
+
...options.sessionOptions === void 0 ? {} : { sessionOptions: snapshotSessionOptions(options.sessionOptions) }
|
|
178
|
+
});
|
|
179
|
+
this.maxSessions = positiveInteger(options.maxSessions ?? 1e3, "maxSessions");
|
|
180
|
+
this.maxRunningTasks = positiveInteger(options.maxRunningTasks ?? 1e3, "maxRunningTasks");
|
|
181
|
+
this.maxTasksPerSession = positiveInteger(options.maxTasksPerSession ?? 16, "maxTasksPerSession");
|
|
182
|
+
this.sessionTtlMs = positiveInteger(options.sessionTtlMs ?? 18e5, "sessionTtlMs");
|
|
183
|
+
this.maxInputBytes = positiveInteger(options.maxInputBytes ?? 1048576, "maxInputBytes");
|
|
184
|
+
this.maxOutputBytes = positiveInteger(options.maxOutputBytes ?? 1048576, "maxOutputBytes");
|
|
185
|
+
this.disposeTimeoutMs = positiveInteger(options.disposeTimeoutMs ?? 3e4, "disposeTimeoutMs");
|
|
186
|
+
this.taskTimeoutMs = positiveInteger(options.taskTimeoutMs ?? 6e5, "taskTimeoutMs");
|
|
187
|
+
this.observerTimeoutMs = positiveInteger(options.observerTimeoutMs ?? 5e3, "observerTimeoutMs");
|
|
188
|
+
}
|
|
189
|
+
async execute(context, eventBus) {
|
|
190
|
+
const requestLogger = a2aIntegrationChildLogger(this.options.logger, "a2a-server-request");
|
|
191
|
+
const requestOperation = beginA2AIntegrationOperation(requestLogger, "a2a-server", "request");
|
|
192
|
+
const requestAttempt = requestOperation.attempt(1);
|
|
193
|
+
const executeOperation = beginA2AIntegrationOperation(requestLogger, "a2a-server", "execute");
|
|
194
|
+
const executeAttempt = executeOperation.attempt(1);
|
|
195
|
+
const task = initialTask(context);
|
|
196
|
+
try {
|
|
197
|
+
eventBus.publish(AgentEvent.task(task));
|
|
198
|
+
} catch (error) {
|
|
199
|
+
const code = a2aErrorCode(error);
|
|
200
|
+
requestAttempt.fail(code);
|
|
201
|
+
requestOperation.fail(code);
|
|
202
|
+
executeAttempt.fail(code);
|
|
203
|
+
executeOperation.fail(code);
|
|
204
|
+
throw error;
|
|
205
|
+
}
|
|
206
|
+
if (this.disposed) {
|
|
207
|
+
requestAttempt.fail("A2A_EXECUTOR_DISPOSED");
|
|
208
|
+
requestOperation.fail("A2A_EXECUTOR_DISPOSED");
|
|
209
|
+
executeAttempt.fail("A2A_EXECUTOR_DISPOSED");
|
|
210
|
+
executeOperation.fail("A2A_EXECUTOR_DISPOSED");
|
|
211
|
+
this.publishFailure(context, eventBus, /* @__PURE__ */ new Error("A2A executor is disposed"));
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
if (this.running.has(context.taskId)) {
|
|
215
|
+
requestAttempt.fail("A2A_TASK_DUPLICATE");
|
|
216
|
+
requestOperation.fail("A2A_TASK_DUPLICATE");
|
|
217
|
+
executeAttempt.fail("A2A_TASK_DUPLICATE");
|
|
218
|
+
executeOperation.fail("A2A_TASK_DUPLICATE");
|
|
219
|
+
this.publishFailure(context, eventBus, /* @__PURE__ */ new Error(`A2A task '${context.taskId}' is already running`));
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (this.running.size >= this.maxRunningTasks) {
|
|
223
|
+
requestAttempt.fail("A2A_TASK_LIMIT");
|
|
224
|
+
requestOperation.fail("A2A_TASK_LIMIT");
|
|
225
|
+
executeAttempt.fail("A2A_TASK_LIMIT");
|
|
226
|
+
executeOperation.fail("A2A_TASK_LIMIT");
|
|
227
|
+
this.publishFailure(context, eventBus, /* @__PURE__ */ new Error(`A2A executor reached its ${this.maxRunningTasks}-running-task limit`));
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
const running = {
|
|
231
|
+
controller: new AbortController(),
|
|
232
|
+
contextId: context.contextId,
|
|
233
|
+
eventBus,
|
|
234
|
+
canceled: false
|
|
235
|
+
};
|
|
236
|
+
const taskSignal = AbortSignal.any([running.controller.signal, AbortSignal.timeout(this.taskTimeoutMs)]);
|
|
237
|
+
this.running.set(context.taskId, running);
|
|
238
|
+
let release;
|
|
239
|
+
let acquired;
|
|
240
|
+
try {
|
|
241
|
+
this.assertAccess(context);
|
|
242
|
+
this.assertInputBudget(context);
|
|
243
|
+
acquired = await this.acquireContextSession(context, taskSignal);
|
|
244
|
+
const state = acquired.state;
|
|
245
|
+
const previous = state.tail;
|
|
246
|
+
state.tail = new Promise((resolve) => {
|
|
247
|
+
release = resolve;
|
|
248
|
+
});
|
|
249
|
+
await abortable(previous, taskSignal);
|
|
250
|
+
taskSignal.throwIfAborted();
|
|
251
|
+
eventBus.publish(AgentEvent.statusUpdate({
|
|
252
|
+
taskId: context.taskId,
|
|
253
|
+
contextId: context.contextId,
|
|
254
|
+
status: status(TaskState.TASK_STATE_WORKING),
|
|
255
|
+
metadata: void 0
|
|
256
|
+
}));
|
|
257
|
+
const input = createUserMessage({
|
|
258
|
+
content: partsToContent(context.userMessage.parts),
|
|
259
|
+
source: {
|
|
260
|
+
kind: "a2a-message",
|
|
261
|
+
contextId: context.contextId,
|
|
262
|
+
messageId: context.userMessage.messageId,
|
|
263
|
+
taskId: context.taskId
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
const response = await abortable(state.session.run(input, { signal: taskSignal }), taskSignal);
|
|
267
|
+
taskSignal.throwIfAborted();
|
|
268
|
+
if (!response.outcome.completed) {
|
|
269
|
+
const reason = response.outcome.reason;
|
|
270
|
+
const detail = reason.kind === "error" ? reason.failure.message : `agent run ended with ${reason.kind}`;
|
|
271
|
+
throw new Error(detail);
|
|
272
|
+
}
|
|
273
|
+
if (utf8Bytes(response.text) > this.maxOutputBytes) throw new Error(`A2A response exceeds the ${this.maxOutputBytes}-byte limit`);
|
|
274
|
+
const reply = agentMessage(context, response.text);
|
|
275
|
+
eventBus.publish(AgentEvent.artifactUpdate({
|
|
276
|
+
taskId: context.taskId,
|
|
277
|
+
contextId: context.contextId,
|
|
278
|
+
artifact: {
|
|
279
|
+
artifactId: crypto.randomUUID(),
|
|
280
|
+
name: `${this.options.agent.name} result`,
|
|
281
|
+
description: `Final result produced by ${this.options.agent.name}`,
|
|
282
|
+
parts: [{
|
|
283
|
+
content: {
|
|
284
|
+
$case: "text",
|
|
285
|
+
value: response.text
|
|
286
|
+
},
|
|
287
|
+
mediaType: "text/plain",
|
|
288
|
+
filename: "",
|
|
289
|
+
metadata: void 0
|
|
290
|
+
}],
|
|
291
|
+
metadata: void 0,
|
|
292
|
+
extensions: []
|
|
293
|
+
},
|
|
294
|
+
append: false,
|
|
295
|
+
lastChunk: true,
|
|
296
|
+
metadata: void 0
|
|
297
|
+
}));
|
|
298
|
+
eventBus.publish(AgentEvent.statusUpdate({
|
|
299
|
+
taskId: context.taskId,
|
|
300
|
+
contextId: context.contextId,
|
|
301
|
+
status: status(TaskState.TASK_STATE_COMPLETED, reply),
|
|
302
|
+
metadata: void 0
|
|
303
|
+
}));
|
|
304
|
+
requestAttempt.success();
|
|
305
|
+
requestOperation.success();
|
|
306
|
+
executeAttempt.success();
|
|
307
|
+
executeOperation.success();
|
|
308
|
+
} catch (error) {
|
|
309
|
+
if (taskSignal.aborted) {
|
|
310
|
+
requestAttempt.abort();
|
|
311
|
+
requestOperation.abort();
|
|
312
|
+
executeAttempt.abort();
|
|
313
|
+
executeOperation.abort();
|
|
314
|
+
} else {
|
|
315
|
+
const code = a2aErrorCode(error);
|
|
316
|
+
requestAttempt.fail(code);
|
|
317
|
+
requestOperation.fail(code);
|
|
318
|
+
executeAttempt.fail(code);
|
|
319
|
+
executeOperation.fail(code);
|
|
320
|
+
}
|
|
321
|
+
if (!running.canceled) {
|
|
322
|
+
await this.reportError(error, context);
|
|
323
|
+
this.publishFailure(context, eventBus, error);
|
|
324
|
+
}
|
|
325
|
+
} finally {
|
|
326
|
+
release?.();
|
|
327
|
+
if (acquired !== void 0) this.releaseContextSession(acquired.key, acquired.slot);
|
|
328
|
+
if (this.running.get(context.taskId) === running) this.running.delete(context.taskId);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
async cancelTask(taskId, eventBus) {
|
|
332
|
+
const running = this.running.get(taskId);
|
|
333
|
+
if (running === void 0 || running.canceled) return;
|
|
334
|
+
const operation = beginA2AIntegrationOperation(this.options.logger, "a2a-server", "cancel");
|
|
335
|
+
const attempt = operation.attempt(1);
|
|
336
|
+
try {
|
|
337
|
+
running.canceled = true;
|
|
338
|
+
running.controller.abort(/* @__PURE__ */ new Error(`A2A task '${taskId}' was canceled`));
|
|
339
|
+
eventBus.publish(AgentEvent.statusUpdate({
|
|
340
|
+
taskId,
|
|
341
|
+
contextId: running.contextId,
|
|
342
|
+
status: status(TaskState.TASK_STATE_CANCELED),
|
|
343
|
+
metadata: void 0
|
|
344
|
+
}));
|
|
345
|
+
attempt.success();
|
|
346
|
+
operation.success();
|
|
347
|
+
} catch (error) {
|
|
348
|
+
const code = a2aErrorCode(error);
|
|
349
|
+
attempt.fail(code);
|
|
350
|
+
operation.fail(code);
|
|
351
|
+
throw error;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
/** Cancel active work and permanently release retained context sessions. */
|
|
355
|
+
async dispose(reason = /* @__PURE__ */ new Error("A2A executor disposed")) {
|
|
356
|
+
if (this.disposeTask !== void 0) return this.disposeTask;
|
|
357
|
+
const operation = beginA2AIntegrationOperation(this.options.logger, "a2a-server", "dispose");
|
|
358
|
+
const attempt = operation.attempt(1);
|
|
359
|
+
this.disposed = true;
|
|
360
|
+
for (const [taskId, running] of this.running) {
|
|
361
|
+
running.canceled = true;
|
|
362
|
+
running.controller.abort(reason);
|
|
363
|
+
try {
|
|
364
|
+
running.eventBus.publish(AgentEvent.statusUpdate({
|
|
365
|
+
taskId,
|
|
366
|
+
contextId: running.contextId,
|
|
367
|
+
status: status(TaskState.TASK_STATE_CANCELED),
|
|
368
|
+
metadata: void 0
|
|
369
|
+
}));
|
|
370
|
+
} catch {}
|
|
371
|
+
}
|
|
372
|
+
const settling = Promise.allSettled([...this.sessions.values()].map((slot) => slot.pending.then((state) => state.tail))).then(() => {
|
|
373
|
+
this.sessions.clear();
|
|
374
|
+
});
|
|
375
|
+
this.disposeTask = withTimeout(settling, this.disposeTimeoutMs, `A2A executor did not dispose within ${this.disposeTimeoutMs}ms`).then(() => {
|
|
376
|
+
attempt.success();
|
|
377
|
+
operation.success();
|
|
378
|
+
}, (error) => {
|
|
379
|
+
const code = a2aErrorCode(error);
|
|
380
|
+
attempt.fail(code);
|
|
381
|
+
operation.fail(code);
|
|
382
|
+
throw error;
|
|
383
|
+
}).finally(() => {
|
|
384
|
+
this.sessions.clear();
|
|
385
|
+
this.running.clear();
|
|
386
|
+
});
|
|
387
|
+
return this.disposeTask;
|
|
388
|
+
}
|
|
389
|
+
/** Return bounded support evidence while retaining dispose() compatibility. */
|
|
390
|
+
async disposeWithReport(reason) {
|
|
391
|
+
if (this.disposeReport !== void 0) return disposeReport(this.disposeReport.status, true, this.disposeReport.error);
|
|
392
|
+
const alreadyDisposed = this.disposeTask !== void 0;
|
|
393
|
+
try {
|
|
394
|
+
await this.dispose(reason);
|
|
395
|
+
return this.disposeReport = disposeReport("disposed", alreadyDisposed);
|
|
396
|
+
} catch (error) {
|
|
397
|
+
const timedOut = error instanceof A2ATeardownTimeoutError;
|
|
398
|
+
return this.disposeReport = disposeReport(timedOut ? "timed-out" : "failed", alreadyDisposed);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
async acquireContextSession(context, signal) {
|
|
402
|
+
const key = await abortable(this.resolveSessionKey(context, signal), signal);
|
|
403
|
+
const now = Date.now();
|
|
404
|
+
this.pruneSessions(now);
|
|
405
|
+
let slot = this.sessions.get(key);
|
|
406
|
+
if (slot === void 0) {
|
|
407
|
+
if (this.sessions.size >= this.maxSessions) throw new Error(`A2A executor reached its ${this.maxSessions}-session limit`);
|
|
408
|
+
const pending = this.createContextSession(context, key, signal);
|
|
409
|
+
slot = {
|
|
410
|
+
pending,
|
|
411
|
+
active: 0,
|
|
412
|
+
lastAccess: now
|
|
413
|
+
};
|
|
414
|
+
this.sessions.set(key, slot);
|
|
415
|
+
pending.catch(() => {
|
|
416
|
+
if (this.sessions.get(key) === slot) this.sessions.delete(key);
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
if (slot.active >= this.maxTasksPerSession) throw new Error(`A2A session reached its ${this.maxTasksPerSession}-task limit`);
|
|
420
|
+
slot.active++;
|
|
421
|
+
slot.lastAccess = now;
|
|
422
|
+
try {
|
|
423
|
+
return {
|
|
424
|
+
key,
|
|
425
|
+
slot,
|
|
426
|
+
state: await abortable(slot.pending, signal)
|
|
427
|
+
};
|
|
428
|
+
} catch (error) {
|
|
429
|
+
slot.active--;
|
|
430
|
+
if (slot.active === 0 && signal.aborted && this.sessions.get(key) === slot) this.sessions.delete(key);
|
|
431
|
+
throw error;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
releaseContextSession(key, slot) {
|
|
435
|
+
slot.active--;
|
|
436
|
+
slot.lastAccess = Date.now();
|
|
437
|
+
if (slot.active < 0 && this.sessions.get(key) === slot) {
|
|
438
|
+
this.sessions.delete(key);
|
|
439
|
+
throw new Error("A2A session reference count underflow");
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
pruneSessions(now) {
|
|
443
|
+
for (const [key, slot] of this.sessions) if (slot.active === 0 && now - slot.lastAccess >= this.sessionTtlMs) this.sessions.delete(key);
|
|
444
|
+
}
|
|
445
|
+
async resolveSessionKey(context, signal) {
|
|
446
|
+
const custom = this.options.sessionOwner;
|
|
447
|
+
const user = context.context.user;
|
|
448
|
+
const owner = custom === void 0 ? user?.isAuthenticated === true ? boundedKey(user.userName, "A2A principal") : "anonymous" : boundedKey(await custom(context, signal), "A2A session owner");
|
|
449
|
+
return JSON.stringify([owner, boundedKey(context.contextId, "A2A context id")]);
|
|
450
|
+
}
|
|
451
|
+
assertAccess(context) {
|
|
452
|
+
const user = context.context.user;
|
|
453
|
+
if (this.options.requireAuthenticated === true && user?.isAuthenticated !== true) throw new Error("A2A authentication is required");
|
|
454
|
+
}
|
|
455
|
+
assertInputBudget(context) {
|
|
456
|
+
if (byteLength(context.userMessage) > this.maxInputBytes) throw new Error(`A2A input exceeds the ${this.maxInputBytes}-byte limit`);
|
|
457
|
+
}
|
|
458
|
+
publishFailure(context, eventBus, error) {
|
|
459
|
+
const text = this.options.exposeInternalErrors === true ? errorMessage(error) : "Agent execution failed";
|
|
460
|
+
eventBus.publish(AgentEvent.statusUpdate({
|
|
461
|
+
taskId: context.taskId,
|
|
462
|
+
contextId: context.contextId,
|
|
463
|
+
status: status(TaskState.TASK_STATE_FAILED, agentMessage(context, text)),
|
|
464
|
+
metadata: void 0
|
|
465
|
+
}));
|
|
466
|
+
}
|
|
467
|
+
async reportError(error, context) {
|
|
468
|
+
if (this.options.onError === void 0) return;
|
|
469
|
+
const observer = Promise.resolve().then(() => this.options.onError?.(error, context));
|
|
470
|
+
await waitForSettlement(observer, this.observerTimeoutMs);
|
|
471
|
+
}
|
|
472
|
+
async createContextSession(context, key, signal) {
|
|
473
|
+
const custom = this.options.createSession;
|
|
474
|
+
return {
|
|
475
|
+
session: custom === void 0 ? this.options.agent.createSession({
|
|
476
|
+
...this.options.sessionOptions,
|
|
477
|
+
registry: requiredRegistry(this.options.registry),
|
|
478
|
+
conversationId: await scopedConversationId(key)
|
|
479
|
+
}) : await custom(context, signal),
|
|
480
|
+
tail: Promise.resolve()
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
/** Assemble the transport-neutral official A2A server components. */
|
|
485
|
+
function createDefinedAgentA2AServer(options) {
|
|
486
|
+
assertSecurityRequirements(options.agentCard.securitySchemes, options.agentCard.securityRequirements);
|
|
487
|
+
const taskStore = options.taskStore ?? new InMemoryTaskStore();
|
|
488
|
+
const executor = new DefinedAgentA2AExecutor(options);
|
|
489
|
+
return {
|
|
490
|
+
agentCard: options.agentCard,
|
|
491
|
+
executor,
|
|
492
|
+
taskStore,
|
|
493
|
+
requestHandler: new DefaultRequestHandler(options.agentCard, taskStore, executor)
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
function initialTask(context) {
|
|
497
|
+
return context.task ?? {
|
|
498
|
+
id: context.taskId,
|
|
499
|
+
contextId: context.contextId,
|
|
500
|
+
status: status(TaskState.TASK_STATE_SUBMITTED),
|
|
501
|
+
artifacts: [],
|
|
502
|
+
history: [structuredClone(context.userMessage)],
|
|
503
|
+
metadata: context.request.metadata
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
function status(state, message) {
|
|
507
|
+
return {
|
|
508
|
+
state,
|
|
509
|
+
message,
|
|
510
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
function agentMessage(context, text) {
|
|
514
|
+
return {
|
|
515
|
+
messageId: crypto.randomUUID(),
|
|
516
|
+
contextId: context.contextId,
|
|
517
|
+
taskId: context.taskId,
|
|
518
|
+
role: Role.ROLE_AGENT,
|
|
519
|
+
parts: [{
|
|
520
|
+
content: {
|
|
521
|
+
$case: "text",
|
|
522
|
+
value: text
|
|
523
|
+
},
|
|
524
|
+
mediaType: "text/plain",
|
|
525
|
+
filename: "",
|
|
526
|
+
metadata: void 0
|
|
527
|
+
}],
|
|
528
|
+
metadata: void 0,
|
|
529
|
+
extensions: [],
|
|
530
|
+
referenceTaskIds: []
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
function requiredRegistry(registry) {
|
|
534
|
+
if (registry === void 0) throw new TypeError("A2A executor requires registry");
|
|
535
|
+
return registry;
|
|
536
|
+
}
|
|
537
|
+
function errorMessage(error) {
|
|
538
|
+
return error instanceof Error ? error.message : String(error);
|
|
539
|
+
}
|
|
540
|
+
function boundedKey(value, label) {
|
|
541
|
+
if (typeof value !== "string" || value.trim().length === 0) throw new TypeError(`${label} must be a non-empty string`);
|
|
542
|
+
if (utf8Bytes(value) > 1024) throw new TypeError(`${label} must not exceed 1024 bytes`);
|
|
543
|
+
return value;
|
|
544
|
+
}
|
|
545
|
+
function positiveInteger(value, label) {
|
|
546
|
+
if (!Number.isSafeInteger(value) || value < 1) throw new TypeError(`${label} must be a positive integer`);
|
|
547
|
+
return value;
|
|
548
|
+
}
|
|
549
|
+
function utf8Bytes(value) {
|
|
550
|
+
return new TextEncoder().encode(value).byteLength;
|
|
551
|
+
}
|
|
552
|
+
function byteLength(value) {
|
|
553
|
+
return utf8Bytes(JSON.stringify(value));
|
|
554
|
+
}
|
|
555
|
+
async function scopedConversationId(sessionKey) {
|
|
556
|
+
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(sessionKey));
|
|
557
|
+
return `a2a-${[...new Uint8Array(digest)].map((value) => value.toString(16).padStart(2, "0")).join("")}`;
|
|
558
|
+
}
|
|
559
|
+
async function abortable(promise, signal) {
|
|
560
|
+
signal.throwIfAborted();
|
|
561
|
+
return new Promise((resolve, reject) => {
|
|
562
|
+
const abort = () => reject(signal.reason);
|
|
563
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
564
|
+
promise.then(resolve, reject).finally(() => signal.removeEventListener("abort", abort));
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
function disposeReport(status, alreadyDisposed, error = status === "disposed" ? void 0 : cleanupFailure(status === "timed-out" ? "A2A_DISPOSE_TIMEOUT" : "A2A_DISPOSE_FAILED", "a2a-dispose", status === "timed-out" ? "A2A executor cleanup timed out" : "A2A executor cleanup failed")) {
|
|
568
|
+
return Object.freeze({
|
|
569
|
+
status,
|
|
570
|
+
alreadyDisposed,
|
|
571
|
+
...error === void 0 ? {} : { error }
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
//#endregion
|
|
576
|
+
export { DefaultRequestHandler$1 as a, JsonRpcTransportHandler as c, TaskState$1 as d, createDefinedAgentA2AServer as f, DefaultExecutionEventBusManager as i, Role$1 as l, AgentEvent$1 as n, DefinedAgentA2AExecutor as o, createAgentCardFromDefinition as p, DefaultExecutionEventBus as r, InMemoryTaskStore$1 as s, A2A_PROTOCOL_VERSION$1 as t, ServerCallContext as u };
|
|
577
|
+
//# sourceMappingURL=server-BX1bnVUG.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-BX1bnVUG.mjs","names":[],"sources":["../src/common/timeout.ts","../src/server/agent-card.ts","../src/server/content.ts","../src/server/session-options.ts","../src/server.ts"],"sourcesContent":["export class A2ATeardownTimeoutError extends Error {}\n\nexport function withTimeout<T>(promise: Promise<T>, timeoutMs: number, message: string): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => reject(new A2ATeardownTimeoutError(message)), timeoutMs)\n promise.then(resolve, reject).finally(() => clearTimeout(timer))\n })\n}\n","import { A2A_PROTOCOL_VERSION, type AgentCard, type AgentProvider,\n type AgentSkill, type SecurityRequirement, type SecurityScheme } from '@a2a-js/sdk'\nimport type { DefinedAgent } from '@alvin0/ai-agent-sdk-core/agent'\n\nexport interface AgentCardFromDefinitionOptions {\n readonly url: string\n readonly protocolBinding?: 'JSONRPC' | 'HTTP+JSON' | 'GRPC' | (string & {})\n readonly version?: string\n readonly provider?: AgentProvider\n readonly documentationUrl?: string\n readonly iconUrl?: string\n readonly tags?: readonly string[]\n readonly examples?: readonly string[]\n readonly securitySchemes?: Readonly<Record<string, SecurityScheme>>\n readonly securityRequirements?: readonly SecurityRequirement[]\n readonly requireHttps?: boolean\n}\n\nexport function createAgentCardFromDefinition(\n agent: DefinedAgent,\n options: AgentCardFromDefinitionOptions,\n): AgentCard {\n const url = endpointUrl(options.url, options.requireHttps === true)\n const securitySchemes = structuredClone(options.securitySchemes ?? {})\n const securityRequirements: SecurityRequirement[] = structuredClone([\n ...options.securityRequirements ?? [],\n ])\n assertSecurityRequirements(securitySchemes, securityRequirements)\n const description = agent.description ?? `${agent.name} powered by ai-agent-sdk`\n const skill: AgentSkill = {\n id: agent.id, name: agent.name, description,\n tags: [...options.tags ?? [agent.id]], examples: [...options.examples ?? []],\n inputModes: ['text/plain', 'image/*', 'application/json'], outputModes: ['text/plain'],\n securityRequirements: structuredClone(securityRequirements),\n }\n return {\n name: agent.name, description,\n supportedInterfaces: [{ url: url.href, protocolBinding: options.protocolBinding ?? 'JSONRPC',\n tenant: '', protocolVersion: A2A_PROTOCOL_VERSION }],\n provider: options.provider, version: options.version ?? '1.0.0',\n ...(options.documentationUrl === undefined ? {} : { documentationUrl: options.documentationUrl }),\n capabilities: { streaming: true, pushNotifications: false, extensions: [], extendedAgentCard: false },\n securitySchemes, securityRequirements,\n defaultInputModes: ['text/plain', 'image/*', 'application/json'], defaultOutputModes: ['text/plain'],\n skills: [skill], signatures: [],\n ...(options.iconUrl === undefined ? {} : { iconUrl: options.iconUrl }),\n }\n}\n\nexport function assertSecurityRequirements(\n schemes: Record<string, SecurityScheme>,\n requirements: readonly SecurityRequirement[],\n): void {\n for (const requirement of requirements) {\n for (const name of Object.keys(requirement.schemes)) {\n if (schemes[name] === undefined) {\n throw new TypeError(`A2A security requirement references unknown scheme '${name}'`)\n }\n if (schemes[name]?.scheme === undefined) {\n throw new TypeError(`A2A security scheme '${name}' has no concrete definition`)\n }\n }\n }\n}\n\nfunction endpointUrl(value: string, requireHttps: boolean): URL {\n const url = new URL(value)\n if (url.username.length > 0 || url.password.length > 0) {\n throw new TypeError('A2A interface URL must not contain credentials')\n }\n if (url.protocol !== 'https:' && url.protocol !== 'http:') {\n throw new TypeError('A2A interface URL must use http or https')\n }\n if (requireHttps && url.protocol !== 'https:') {\n throw new TypeError('A2A interface URL must use https under the configured policy')\n }\n return url\n}\n","import type { Part } from '@a2a-js/sdk'\nimport type { ContentBlock, ImageMediaType } from '@alvin0/ai-agent-sdk-core'\n\nexport function partsToContent(parts: readonly Part[]): ContentBlock[] {\n const blocks: ContentBlock[] = []\n for (const part of parts) {\n const content = part.content\n if (content?.$case === 'text') {\n blocks.push({ type: 'text', text: content.value })\n } else if (content?.$case === 'url' && isImageMediaType(part.mediaType)) {\n blocks.push({ type: 'image', source: { kind: 'url', url: content.value } })\n } else if (content?.$case === 'raw' && isImageMediaType(part.mediaType)) {\n blocks.push({ type: 'image', source: { kind: 'base64', mediaType: part.mediaType,\n data: bytesToBase64(content.value) } })\n } else if (content?.$case === 'data') {\n blocks.push({ type: 'text', text: JSON.stringify(content.value) })\n } else if (content !== undefined) {\n const location = content.$case === 'url' ? `: ${content.value}` : ''\n blocks.push({ type: 'text',\n text: `[A2A attachment${part.mediaType.length === 0 ? '' : ` ${part.mediaType}`}${location}]` })\n }\n }\n return blocks.length === 0 ? [{ type: 'text', text: '' }] : blocks\n}\n\nfunction isImageMediaType(value: string): value is ImageMediaType {\n return value === 'image/jpeg' || value === 'image/png'\n || value === 'image/gif' || value === 'image/webp'\n}\n\nfunction bytesToBase64(value: Uint8Array): string {\n let binary = ''\n for (let offset = 0; offset < value.length; offset += 0x8000) {\n binary += String.fromCharCode(...value.subarray(offset, offset + 0x8000))\n }\n return btoa(binary)\n}\n","import type { AgentSessionOptions } from '@alvin0/ai-agent-sdk-core/agent'\n\nexport function snapshotSessionOptions(\n options: Omit<AgentSessionOptions, 'conversationId' | 'registry'>,\n): Omit<AgentSessionOptions, 'conversationId' | 'registry'> {\n return Object.freeze({\n ...options,\n ...(options.historyLimits === undefined ? {} : {\n historyLimits: Object.freeze({ ...options.historyLimits }),\n }),\n ...(options.runtimeLimits === undefined ? {} : {\n runtimeLimits: Object.freeze({ ...options.runtimeLimits }),\n }),\n ...(Array.isArray(options.tools) ? { tools: Object.freeze([...options.tools]) } : {}),\n ...(options.skills === undefined ? {} : { skills: Object.freeze([...options.skills]) }),\n ...(options.interceptors === undefined ? {} : { interceptors: Object.freeze([...options.interceptors]) }),\n ...(options.hooks === undefined ? {} : { hooks: Object.freeze({ ...options.hooks }) }),\n ...(options.compaction === undefined || options.compaction === false\n ? {} : { compaction: Object.freeze({ ...options.compaction }) }),\n ...(options.trace === undefined ? {} : { trace: Object.freeze({ ...options.trace }) }),\n ...(options.team === undefined ? {} : { team: Object.freeze({ ...options.team }) }),\n })\n}\n","import {\n Role,\n TaskState,\n type AgentCard,\n type Message as A2AMessage,\n type Task,\n} from '@a2a-js/sdk'\nimport {\n AgentEvent,\n DefaultRequestHandler,\n InMemoryTaskStore,\n type AgentExecutor,\n type ExecutionEventBus,\n type RequestContext,\n type TaskStore,\n} from '@a2a-js/sdk/server'\nimport type { SdkLogger, SupportSafeError } from '@alvin0/ai-agent-sdk-core'\nimport { createUserMessage } from '@alvin0/ai-agent-sdk-core'\nimport type { ModelRegistry } from '@alvin0/ai-agent-sdk-core'\nimport { waitForSettlement } from '@alvin0/ai-agent-sdk-core'\nimport {\n AgentSession,\n type DefinedAgent,\n type AgentSessionOptions,\n} from '@alvin0/ai-agent-sdk-core/agent'\nimport { cleanupFailure } from './common/cleanup-report.ts'\nimport { a2aErrorCode, a2aIntegrationChildLogger,\n beginA2AIntegrationOperation } from './common/integration-operation.ts'\nimport { A2ATeardownTimeoutError, withTimeout } from './common/timeout.ts'\nimport { assertSecurityRequirements } from './server/agent-card.ts'\nimport { partsToContent } from './server/content.ts'\nimport { snapshotSessionOptions } from './server/session-options.ts'\n\nexport { createAgentCardFromDefinition,\n type AgentCardFromDefinitionOptions } from './server/agent-card.ts'\n\nexport interface DefinedAgentA2AExecutorOptions {\n readonly agent: DefinedAgent\n readonly logger?: SdkLogger\n /** Required unless createSession supplies a fully configured session. */\n readonly registry?: ModelRegistry\n readonly sessionOptions?: Omit<AgentSessionOptions, 'conversationId' | 'registry'>\n /** Customize session construction for request-specific registries, tools, or policy. */\n readonly createSession?: (\n context: RequestContext,\n signal?: AbortSignal,\n ) => AgentSession | Promise<AgentSession>\n /** Opt-in host policy: reject calls without an authenticated A2A principal. */\n readonly requireAuthenticated?: boolean\n /**\n * Map a request to the host's ownership boundary (user, device, workspace,\n * API client, etc.). Defaults to the authenticated A2A principal.\n */\n readonly sessionOwner?: (context: RequestContext, signal?: AbortSignal) => string | Promise<string>\n /** Maximum retained context sessions. Defaults to 1,000. */\n readonly maxSessions?: number\n /** Maximum tasks executing or queued across the executor. Defaults to 1,000. */\n readonly maxRunningTasks?: number\n /** Maximum tasks executing or queued against one retained session. Defaults to 16. */\n readonly maxTasksPerSession?: number\n /** Idle session retention. Defaults to 30 minutes. */\n readonly sessionTtlMs?: number\n /** Maximum serialized inbound A2A message size. Defaults to 1 MiB. */\n readonly maxInputBytes?: number\n /** Maximum UTF-8 response size published to A2A. Defaults to 1 MiB. */\n readonly maxOutputBytes?: number\n /** Maximum time dispose waits for cooperative providers. Defaults to 30 seconds. */\n readonly disposeTimeoutMs?: number\n /** End-to-end bound for session creation, queueing, and agent execution. Defaults to 10 minutes. */\n readonly taskTimeoutMs?: number\n /** Maximum wait for the private error observer. Defaults to 5 seconds. */\n readonly observerTimeoutMs?: number\n /** Return raw internal error text to callers. Unsafe and disabled by default. */\n readonly exposeInternalErrors?: boolean\n /** Receives the original error for private logging/telemetry. */\n readonly onError?: (error: unknown, context: RequestContext) => void | Promise<void>\n}\n\nexport interface A2ADisposeReport {\n readonly status: 'disposed' | 'failed' | 'timed-out'\n readonly alreadyDisposed: boolean\n readonly error?: SupportSafeError\n}\n\ninterface ContextSession {\n readonly session: AgentSession\n tail: Promise<void>\n}\n\ninterface SessionSlot {\n readonly pending: Promise<ContextSession>\n active: number\n lastAccess: number\n}\n\ninterface RunningTask {\n readonly controller: AbortController\n readonly contextId: string\n readonly eventBus: ExecutionEventBus\n canceled: boolean\n}\n\n/**\n * Adapt a provider-neutral DefinedAgent to the official A2A AgentExecutor contract.\n * Sessions are retained by A2A contextId, so protocol follow-ups preserve history.\n */\nexport class DefinedAgentA2AExecutor implements AgentExecutor {\n private readonly options: DefinedAgentA2AExecutorOptions\n private readonly sessions = new Map<string, SessionSlot>()\n private readonly running = new Map<string, RunningTask>()\n private readonly maxSessions: number\n private readonly maxRunningTasks: number\n private readonly maxTasksPerSession: number\n private readonly sessionTtlMs: number\n private readonly maxInputBytes: number\n private readonly maxOutputBytes: number\n private readonly disposeTimeoutMs: number\n private readonly taskTimeoutMs: number\n private readonly observerTimeoutMs: number\n private disposed = false\n private disposeTask: Promise<void> | undefined\n private disposeReport: A2ADisposeReport | undefined\n\n constructor(options: DefinedAgentA2AExecutorOptions) {\n if (options.registry === undefined && options.createSession === undefined) {\n throw new TypeError('A2A executor requires registry or createSession')\n }\n this.options = Object.freeze({\n ...options,\n ...(options.sessionOptions === undefined ? {} : {\n sessionOptions: snapshotSessionOptions(options.sessionOptions),\n }),\n })\n this.maxSessions = positiveInteger(options.maxSessions ?? 1_000, 'maxSessions')\n this.maxRunningTasks = positiveInteger(options.maxRunningTasks ?? 1_000, 'maxRunningTasks')\n this.maxTasksPerSession = positiveInteger(options.maxTasksPerSession ?? 16, 'maxTasksPerSession')\n this.sessionTtlMs = positiveInteger(options.sessionTtlMs ?? 30 * 60_000, 'sessionTtlMs')\n this.maxInputBytes = positiveInteger(options.maxInputBytes ?? 1024 * 1024, 'maxInputBytes')\n this.maxOutputBytes = positiveInteger(options.maxOutputBytes ?? 1024 * 1024, 'maxOutputBytes')\n this.disposeTimeoutMs = positiveInteger(options.disposeTimeoutMs ?? 30_000, 'disposeTimeoutMs')\n this.taskTimeoutMs = positiveInteger(options.taskTimeoutMs ?? 10 * 60_000, 'taskTimeoutMs')\n this.observerTimeoutMs = positiveInteger(options.observerTimeoutMs ?? 5_000, 'observerTimeoutMs')\n }\n\n async execute(context: RequestContext, eventBus: ExecutionEventBus): Promise<void> {\n const requestLogger = a2aIntegrationChildLogger(this.options.logger, 'a2a-server-request')\n const requestOperation = beginA2AIntegrationOperation(requestLogger, 'a2a-server', 'request')\n const requestAttempt = requestOperation.attempt(1)\n const executeOperation = beginA2AIntegrationOperation(requestLogger, 'a2a-server', 'execute')\n const executeAttempt = executeOperation.attempt(1)\n const task = initialTask(context)\n try { eventBus.publish(AgentEvent.task(task)) }\n catch (error: unknown) {\n const code = a2aErrorCode(error)\n requestAttempt.fail(code); requestOperation.fail(code)\n executeAttempt.fail(code); executeOperation.fail(code)\n throw error\n }\n\n if (this.disposed) {\n requestAttempt.fail('A2A_EXECUTOR_DISPOSED'); requestOperation.fail('A2A_EXECUTOR_DISPOSED')\n executeAttempt.fail('A2A_EXECUTOR_DISPOSED'); executeOperation.fail('A2A_EXECUTOR_DISPOSED')\n this.publishFailure(context, eventBus, new Error('A2A executor is disposed'))\n return\n }\n if (this.running.has(context.taskId)) {\n requestAttempt.fail('A2A_TASK_DUPLICATE'); requestOperation.fail('A2A_TASK_DUPLICATE')\n executeAttempt.fail('A2A_TASK_DUPLICATE'); executeOperation.fail('A2A_TASK_DUPLICATE')\n this.publishFailure(context, eventBus, new Error(`A2A task '${context.taskId}' is already running`))\n return\n }\n if (this.running.size >= this.maxRunningTasks) {\n requestAttempt.fail('A2A_TASK_LIMIT'); requestOperation.fail('A2A_TASK_LIMIT')\n executeAttempt.fail('A2A_TASK_LIMIT'); executeOperation.fail('A2A_TASK_LIMIT')\n this.publishFailure(\n context, eventBus,\n new Error(`A2A executor reached its ${this.maxRunningTasks}-running-task limit`),\n )\n return\n }\n\n const running: RunningTask = {\n controller: new AbortController(),\n contextId: context.contextId,\n eventBus,\n canceled: false,\n }\n const taskSignal = AbortSignal.any([\n running.controller.signal,\n AbortSignal.timeout(this.taskTimeoutMs),\n ])\n this.running.set(context.taskId, running)\n let release: (() => void) | undefined\n let acquired: { readonly key: string; readonly slot: SessionSlot; readonly state: ContextSession } | undefined\n try {\n this.assertAccess(context)\n this.assertInputBudget(context)\n acquired = await this.acquireContextSession(context, taskSignal)\n const state = acquired.state\n const previous = state.tail\n state.tail = new Promise<void>(resolve => { release = resolve })\n await abortable(previous, taskSignal)\n taskSignal.throwIfAborted()\n\n eventBus.publish(AgentEvent.statusUpdate({\n taskId: context.taskId,\n contextId: context.contextId,\n status: status(TaskState.TASK_STATE_WORKING),\n metadata: undefined,\n }))\n\n const input = createUserMessage({\n content: partsToContent(context.userMessage.parts),\n source: {\n kind: 'a2a-message',\n contextId: context.contextId,\n messageId: context.userMessage.messageId,\n taskId: context.taskId,\n },\n })\n const response = await abortable(state.session.run(input, { signal: taskSignal }), taskSignal)\n taskSignal.throwIfAborted()\n if (!response.outcome.completed) {\n const reason = response.outcome.reason\n const detail = reason.kind === 'error'\n ? reason.failure.message\n : `agent run ended with ${reason.kind}`\n throw new Error(detail)\n }\n if (utf8Bytes(response.text) > this.maxOutputBytes) {\n throw new Error(`A2A response exceeds the ${this.maxOutputBytes}-byte limit`)\n }\n\n const reply = agentMessage(context, response.text)\n eventBus.publish(AgentEvent.artifactUpdate({\n taskId: context.taskId,\n contextId: context.contextId,\n artifact: {\n artifactId: crypto.randomUUID(),\n name: `${this.options.agent.name} result`,\n description: `Final result produced by ${this.options.agent.name}`,\n parts: [{\n content: { $case: 'text', value: response.text },\n mediaType: 'text/plain',\n filename: '',\n metadata: undefined,\n }],\n metadata: undefined,\n extensions: [],\n },\n append: false,\n lastChunk: true,\n metadata: undefined,\n }))\n eventBus.publish(AgentEvent.statusUpdate({\n taskId: context.taskId,\n contextId: context.contextId,\n status: status(TaskState.TASK_STATE_COMPLETED, reply),\n metadata: undefined,\n }))\n requestAttempt.success(); requestOperation.success()\n executeAttempt.success(); executeOperation.success()\n } catch (error: unknown) {\n if (taskSignal.aborted) {\n requestAttempt.abort(); requestOperation.abort()\n executeAttempt.abort(); executeOperation.abort()\n } else {\n const code = a2aErrorCode(error)\n requestAttempt.fail(code); requestOperation.fail(code)\n executeAttempt.fail(code); executeOperation.fail(code)\n }\n if (!running.canceled) {\n await this.reportError(error, context)\n this.publishFailure(context, eventBus, error)\n }\n } finally {\n release?.()\n if (acquired !== undefined) this.releaseContextSession(acquired.key, acquired.slot)\n if (this.running.get(context.taskId) === running) this.running.delete(context.taskId)\n }\n }\n\n async cancelTask(taskId: string, eventBus: ExecutionEventBus): Promise<void> {\n const running = this.running.get(taskId)\n if (running === undefined || running.canceled) return\n const operation = beginA2AIntegrationOperation(this.options.logger, 'a2a-server', 'cancel')\n const attempt = operation.attempt(1)\n try {\n running.canceled = true\n running.controller.abort(new Error(`A2A task '${taskId}' was canceled`))\n eventBus.publish(AgentEvent.statusUpdate({\n taskId,\n contextId: running.contextId,\n status: status(TaskState.TASK_STATE_CANCELED),\n metadata: undefined,\n }))\n attempt.success(); operation.success()\n } catch (error: unknown) {\n const code = a2aErrorCode(error)\n attempt.fail(code); operation.fail(code)\n throw error\n }\n }\n\n /** Cancel active work and permanently release retained context sessions. */\n async dispose(reason: unknown = new Error('A2A executor disposed')): Promise<void> {\n if (this.disposeTask !== undefined) return this.disposeTask\n const operation = beginA2AIntegrationOperation(this.options.logger, 'a2a-server', 'dispose')\n const attempt = operation.attempt(1)\n this.disposed = true\n for (const [taskId, running] of this.running) {\n running.canceled = true\n running.controller.abort(reason)\n try {\n running.eventBus.publish(AgentEvent.statusUpdate({\n taskId,\n contextId: running.contextId,\n status: status(TaskState.TASK_STATE_CANCELED),\n metadata: undefined,\n }))\n } catch { /* shutdown continues even if a transport observer has failed */ }\n }\n const settling = Promise.allSettled(\n [...this.sessions.values()].map(slot => slot.pending.then(state => state.tail)),\n ).then(() => { this.sessions.clear() })\n this.disposeTask = withTimeout(\n settling,\n this.disposeTimeoutMs,\n `A2A executor did not dispose within ${this.disposeTimeoutMs}ms`,\n ).then(() => {\n attempt.success(); operation.success()\n }, error => {\n const code = a2aErrorCode(error)\n attempt.fail(code); operation.fail(code)\n throw error\n }).finally(() => {\n this.sessions.clear()\n this.running.clear()\n })\n return this.disposeTask\n }\n\n /** Return bounded support evidence while retaining dispose() compatibility. */\n async disposeWithReport(reason?: unknown): Promise<A2ADisposeReport> {\n if (this.disposeReport !== undefined) return disposeReport(this.disposeReport.status, true,\n this.disposeReport.error)\n const alreadyDisposed = this.disposeTask !== undefined\n try {\n await this.dispose(reason)\n return this.disposeReport = disposeReport('disposed', alreadyDisposed)\n } catch (error) {\n const timedOut = error instanceof A2ATeardownTimeoutError\n return this.disposeReport = disposeReport(timedOut ? 'timed-out' : 'failed', alreadyDisposed)\n }\n }\n\n private async acquireContextSession(\n context: RequestContext,\n signal: AbortSignal,\n ): Promise<{ readonly key: string; readonly slot: SessionSlot; readonly state: ContextSession }> {\n const key = await abortable(this.resolveSessionKey(context, signal), signal)\n const now = Date.now()\n this.pruneSessions(now)\n let slot = this.sessions.get(key)\n if (slot === undefined) {\n if (this.sessions.size >= this.maxSessions) {\n throw new Error(`A2A executor reached its ${this.maxSessions}-session limit`)\n }\n const pending = this.createContextSession(context, key, signal)\n slot = { pending, active: 0, lastAccess: now }\n this.sessions.set(key, slot)\n pending.catch(() => {\n if (this.sessions.get(key) === slot) this.sessions.delete(key)\n })\n }\n if (slot.active >= this.maxTasksPerSession) {\n throw new Error(`A2A session reached its ${this.maxTasksPerSession}-task limit`)\n }\n slot.active++\n slot.lastAccess = now\n try {\n return { key, slot, state: await abortable(slot.pending, signal) }\n } catch (error: unknown) {\n slot.active--\n if (slot.active === 0 && signal.aborted && this.sessions.get(key) === slot) {\n this.sessions.delete(key)\n }\n throw error\n }\n }\n\n private releaseContextSession(key: string, slot: SessionSlot): void {\n slot.active--\n slot.lastAccess = Date.now()\n if (slot.active < 0 && this.sessions.get(key) === slot) {\n this.sessions.delete(key)\n throw new Error('A2A session reference count underflow')\n }\n }\n\n private pruneSessions(now: number): void {\n for (const [key, slot] of this.sessions) {\n if (slot.active === 0 && now - slot.lastAccess >= this.sessionTtlMs) this.sessions.delete(key)\n }\n }\n\n private async resolveSessionKey(context: RequestContext, signal: AbortSignal): Promise<string> {\n const custom = this.options.sessionOwner\n const user = context.context.user\n const owner = custom === undefined\n ? user?.isAuthenticated === true\n ? boundedKey(user.userName, 'A2A principal')\n : 'anonymous'\n : boundedKey(await custom(context, signal), 'A2A session owner')\n return JSON.stringify([owner, boundedKey(context.contextId, 'A2A context id')])\n }\n\n private assertAccess(context: RequestContext): void {\n const user = context.context.user\n if (this.options.requireAuthenticated === true && user?.isAuthenticated !== true) {\n throw new Error('A2A authentication is required')\n }\n }\n\n private assertInputBudget(context: RequestContext): void {\n if (byteLength(context.userMessage) > this.maxInputBytes) {\n throw new Error(`A2A input exceeds the ${this.maxInputBytes}-byte limit`)\n }\n }\n\n private publishFailure(\n context: RequestContext,\n eventBus: ExecutionEventBus,\n error: unknown,\n ): void {\n const text = this.options.exposeInternalErrors === true\n ? errorMessage(error)\n : 'Agent execution failed'\n eventBus.publish(AgentEvent.statusUpdate({\n taskId: context.taskId,\n contextId: context.contextId,\n status: status(TaskState.TASK_STATE_FAILED, agentMessage(context, text)),\n metadata: undefined,\n }))\n }\n\n private async reportError(error: unknown, context: RequestContext): Promise<void> {\n if (this.options.onError === undefined) return\n const observer = Promise.resolve().then(() => this.options.onError?.(error, context))\n await waitForSettlement(observer, this.observerTimeoutMs)\n }\n\n private async createContextSession(\n context: RequestContext,\n key: string,\n signal: AbortSignal,\n ): Promise<ContextSession> {\n const custom = this.options.createSession\n const session = custom === undefined\n ? this.options.agent.createSession({\n ...this.options.sessionOptions,\n registry: requiredRegistry(this.options.registry),\n conversationId: await scopedConversationId(key),\n })\n : await custom(context, signal)\n return { session, tail: Promise.resolve() }\n }\n}\n\nexport interface DefinedAgentA2AServerOptions extends DefinedAgentA2AExecutorOptions {\n readonly agentCard: AgentCard\n readonly taskStore?: TaskStore\n}\n\nexport interface DefinedAgentA2AServer {\n readonly agentCard: AgentCard\n readonly executor: DefinedAgentA2AExecutor\n readonly taskStore: TaskStore\n readonly requestHandler: DefaultRequestHandler\n}\n\n/** Assemble the transport-neutral official A2A server components. */\nexport function createDefinedAgentA2AServer(\n options: DefinedAgentA2AServerOptions,\n): DefinedAgentA2AServer {\n assertSecurityRequirements(\n options.agentCard.securitySchemes,\n options.agentCard.securityRequirements,\n )\n const taskStore = options.taskStore ?? new InMemoryTaskStore()\n const executor = new DefinedAgentA2AExecutor(options)\n return {\n agentCard: options.agentCard,\n executor,\n taskStore,\n requestHandler: new DefaultRequestHandler(options.agentCard, taskStore, executor),\n }\n}\n\nfunction initialTask(context: RequestContext): Task {\n return context.task ?? {\n id: context.taskId,\n contextId: context.contextId,\n status: status(TaskState.TASK_STATE_SUBMITTED),\n artifacts: [],\n history: [structuredClone(context.userMessage)],\n metadata: context.request.metadata,\n }\n}\n\nfunction status(state: TaskState, message?: A2AMessage): NonNullable<Task['status']> {\n return {\n state,\n message,\n timestamp: new Date().toISOString(),\n }\n}\n\nfunction agentMessage(context: RequestContext, text: string): A2AMessage {\n return {\n messageId: crypto.randomUUID(),\n contextId: context.contextId,\n taskId: context.taskId,\n role: Role.ROLE_AGENT,\n parts: [{\n content: { $case: 'text', value: text },\n mediaType: 'text/plain',\n filename: '',\n metadata: undefined,\n }],\n metadata: undefined,\n extensions: [],\n referenceTaskIds: [],\n }\n}\n\nfunction requiredRegistry(registry: ModelRegistry | undefined): ModelRegistry {\n if (registry === undefined) throw new TypeError('A2A executor requires registry')\n return registry\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nfunction boundedKey(value: unknown, label: string): string {\n if (typeof value !== 'string' || value.trim().length === 0) {\n throw new TypeError(`${label} must be a non-empty string`)\n }\n if (utf8Bytes(value) > 1024) throw new TypeError(`${label} must not exceed 1024 bytes`)\n return value\n}\n\nfunction positiveInteger(value: number, label: string): number {\n if (!Number.isSafeInteger(value) || value < 1) throw new TypeError(`${label} must be a positive integer`)\n return value\n}\n\nfunction utf8Bytes(value: string): number {\n return new TextEncoder().encode(value).byteLength\n}\n\nfunction byteLength(value: unknown): number {\n return utf8Bytes(JSON.stringify(value))\n}\n\nasync function scopedConversationId(sessionKey: string): Promise<string> {\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(sessionKey))\n const hex = [...new Uint8Array(digest)]\n .map(value => value.toString(16).padStart(2, '0'))\n .join('')\n return `a2a-${hex}`\n}\n\nasync function abortable<T>(promise: Promise<T>, signal: AbortSignal): Promise<T> {\n signal.throwIfAborted()\n return new Promise<T>((resolve, reject) => {\n const abort = (): void => reject(signal.reason)\n signal.addEventListener('abort', abort, { once: true })\n promise.then(resolve, reject).finally(() => signal.removeEventListener('abort', abort))\n })\n}\n\nfunction disposeReport(status: A2ADisposeReport['status'], alreadyDisposed: boolean,\n error: SupportSafeError | undefined = status === 'disposed' ? undefined\n : cleanupFailure(status === 'timed-out' ? 'A2A_DISPOSE_TIMEOUT' : 'A2A_DISPOSE_FAILED',\n 'a2a-dispose', status === 'timed-out' ? 'A2A executor cleanup timed out' : 'A2A executor cleanup failed')):\n A2ADisposeReport {\n return Object.freeze({ status, alreadyDisposed, ...(error === undefined ? {} : { error }) })\n}\n\nexport {\n AgentEvent,\n DefaultExecutionEventBus,\n DefaultExecutionEventBusManager,\n DefaultRequestHandler,\n InMemoryTaskStore,\n JsonRpcTransportHandler,\n ServerCallContext,\n type AgentExecutor,\n type ExecutionEventBus,\n type RequestContext,\n type TaskStore,\n} from '@a2a-js/sdk/server'\nexport {\n A2A_PROTOCOL_VERSION,\n Role,\n TaskState,\n type AgentCard,\n type Message,\n type Part,\n type Task,\n} from '@a2a-js/sdk'\n"],"mappings":"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"}
|