@mastra/server 1.32.1 → 1.33.0-alpha.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/CHANGELOG.md +25 -0
- package/dist/{chunk-ALUAG74N.js → chunk-3KIFZFY7.js} +575 -23
- package/dist/chunk-3KIFZFY7.js.map +1 -0
- package/dist/{chunk-3TFM333T.cjs → chunk-CJ2LC5EE.cjs} +578 -22
- package/dist/chunk-CJ2LC5EE.cjs.map +1 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/server/a2a/push-notification-sender.d.ts +25 -0
- package/dist/server/a2a/push-notification-sender.d.ts.map +1 -0
- package/dist/server/a2a/push-notification-store.d.ts +22 -0
- package/dist/server/a2a/push-notification-store.d.ts.map +1 -0
- package/dist/server/handlers/a2a.cjs +26 -10
- package/dist/server/handlers/a2a.d.ts +44 -6
- package/dist/server/handlers/a2a.d.ts.map +1 -1
- package/dist/server/handlers/a2a.js +1 -1
- package/dist/server/handlers.cjs +2 -2
- package/dist/server/handlers.js +1 -1
- package/dist/server/server-adapter/index.cjs +2 -2
- package/dist/server/server-adapter/index.js +1 -1
- package/package.json +6 -5
- package/dist/chunk-3TFM333T.cjs.map +0 -1
- package/dist/chunk-ALUAG74N.js.map +0 -1
|
@@ -7,6 +7,10 @@ import { __export } from './chunk-PR4QN5HX.js';
|
|
|
7
7
|
import { isDeepStrictEqual } from 'util';
|
|
8
8
|
import { MastraA2AError } from '@mastra/core/a2a';
|
|
9
9
|
import { z } from 'zod/v4';
|
|
10
|
+
import { lookup } from 'dns/promises';
|
|
11
|
+
import { request as request$1 } from 'http';
|
|
12
|
+
import { request } from 'https';
|
|
13
|
+
import { isIP } from 'net';
|
|
10
14
|
|
|
11
15
|
// src/server/handlers/a2a.ts
|
|
12
16
|
var a2a_exports = {};
|
|
@@ -15,8 +19,12 @@ __export(a2a_exports, {
|
|
|
15
19
|
GET_AGENT_CARD_ROUTE: () => GET_AGENT_CARD_ROUTE,
|
|
16
20
|
getAgentCardByIdHandler: () => getAgentCardByIdHandler,
|
|
17
21
|
getAgentExecutionHandler: () => getAgentExecutionHandler,
|
|
22
|
+
handleDeleteTaskPushNotificationConfig: () => handleDeleteTaskPushNotificationConfig,
|
|
23
|
+
handleGetTaskPushNotificationConfig: () => handleGetTaskPushNotificationConfig,
|
|
24
|
+
handleListTaskPushNotificationConfig: () => handleListTaskPushNotificationConfig,
|
|
18
25
|
handleMessageSend: () => handleMessageSend,
|
|
19
26
|
handleMessageStream: () => handleMessageStream,
|
|
27
|
+
handleSetTaskPushNotificationConfig: () => handleSetTaskPushNotificationConfig,
|
|
20
28
|
handleTaskCancel: () => handleTaskCancel,
|
|
21
29
|
handleTaskGet: () => handleTaskGet,
|
|
22
30
|
handleTaskResubscribe: () => handleTaskResubscribe
|
|
@@ -77,6 +85,231 @@ function convertToCoreMessagePart(part) {
|
|
|
77
85
|
throw new Error("Data parts are not supported in core messages");
|
|
78
86
|
}
|
|
79
87
|
}
|
|
88
|
+
var DEFAULT_PUSH_NOTIFICATION_TOKEN_HEADER = "X-A2A-Notification-Token";
|
|
89
|
+
function isDisallowedHostname(hostname) {
|
|
90
|
+
const normalized = hostname.toLowerCase();
|
|
91
|
+
return normalized === "localhost" || normalized.endsWith(".localhost") || normalized.endsWith(".local") || normalized.endsWith(".internal") || !normalized.includes(".");
|
|
92
|
+
}
|
|
93
|
+
function isDisallowedIpv4(address) {
|
|
94
|
+
const [first = -1, second = -1] = address.split(".").map(Number);
|
|
95
|
+
return first === 10 || first === 127 || first === 169 && second === 254 || first === 172 && second >= 16 && second <= 31 || first === 192 && second === 168;
|
|
96
|
+
}
|
|
97
|
+
function isDisallowedIpv6(address) {
|
|
98
|
+
const normalized = address.toLowerCase();
|
|
99
|
+
return normalized === "::1" || normalized.startsWith("fe8") || normalized.startsWith("fe9") || normalized.startsWith("fea") || normalized.startsWith("feb") || normalized.startsWith("fc") || normalized.startsWith("fd");
|
|
100
|
+
}
|
|
101
|
+
function isDisallowedIpAddress(address) {
|
|
102
|
+
const version = isIP(address);
|
|
103
|
+
if (version === 4) {
|
|
104
|
+
return isDisallowedIpv4(address);
|
|
105
|
+
}
|
|
106
|
+
if (version === 6) {
|
|
107
|
+
return isDisallowedIpv6(address);
|
|
108
|
+
}
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
var DefaultPushNotificationSender = class {
|
|
112
|
+
constructor(pushNotificationStore, options = {}) {
|
|
113
|
+
this.pushNotificationStore = pushNotificationStore;
|
|
114
|
+
this.options = options;
|
|
115
|
+
}
|
|
116
|
+
pushNotificationStore;
|
|
117
|
+
options;
|
|
118
|
+
getStore() {
|
|
119
|
+
return this.pushNotificationStore;
|
|
120
|
+
}
|
|
121
|
+
async resolveValidatedDestination(rawUrl) {
|
|
122
|
+
const url = new URL(rawUrl);
|
|
123
|
+
if (url.protocol !== "https:" && url.protocol !== "http:") {
|
|
124
|
+
throw new Error(`Push notification URL must use http or https: ${url.protocol}`);
|
|
125
|
+
}
|
|
126
|
+
const hostname = url.hostname.toLowerCase();
|
|
127
|
+
if (this.options.allowedHosts && !this.options.allowedHosts.includes(hostname)) {
|
|
128
|
+
throw new Error(`Push notification host is not allowed: ${hostname}`);
|
|
129
|
+
}
|
|
130
|
+
if (isDisallowedHostname(hostname)) {
|
|
131
|
+
throw new Error(`Push notification URL must not target local or internal hosts: ${hostname}`);
|
|
132
|
+
}
|
|
133
|
+
if (isDisallowedIpAddress(hostname)) {
|
|
134
|
+
throw new Error(`Push notification URL must not target local or private IPs: ${hostname}`);
|
|
135
|
+
}
|
|
136
|
+
const resolvedAddresses = isIP(hostname) === 0 ? await (this.options.lookup ?? lookup)(hostname, { all: true, verbatim: true }) : [{ address: hostname, family: isIP(hostname) }];
|
|
137
|
+
if (resolvedAddresses.some((result) => isDisallowedIpAddress(result.address))) {
|
|
138
|
+
throw new Error(`Push notification URL resolved to a local or private IP: ${hostname}`);
|
|
139
|
+
}
|
|
140
|
+
const requestUrl = new URL(url.toString());
|
|
141
|
+
requestUrl.hostname = resolvedAddresses[0].address;
|
|
142
|
+
return {
|
|
143
|
+
originalUrl: url,
|
|
144
|
+
requestUrl,
|
|
145
|
+
hostHeader: url.host,
|
|
146
|
+
servername: isIP(hostname) === 0 ? hostname : void 0
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
async postTaskSnapshot({
|
|
150
|
+
requestUrl,
|
|
151
|
+
hostHeader,
|
|
152
|
+
servername,
|
|
153
|
+
headers,
|
|
154
|
+
body,
|
|
155
|
+
timeout
|
|
156
|
+
}) {
|
|
157
|
+
headers.set("host", hostHeader);
|
|
158
|
+
const signal = typeof AbortSignal.timeout === "function" ? AbortSignal.timeout(timeout) : void 0;
|
|
159
|
+
if (this.options.fetch) {
|
|
160
|
+
return this.options.fetch(requestUrl.toString(), {
|
|
161
|
+
method: "POST",
|
|
162
|
+
headers,
|
|
163
|
+
body,
|
|
164
|
+
signal
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
const transport = requestUrl.protocol === "https:" ? request : request$1;
|
|
168
|
+
return await new Promise((resolve, reject) => {
|
|
169
|
+
const request = transport(
|
|
170
|
+
{
|
|
171
|
+
protocol: requestUrl.protocol,
|
|
172
|
+
hostname: requestUrl.hostname,
|
|
173
|
+
port: requestUrl.port || void 0,
|
|
174
|
+
path: `${requestUrl.pathname}${requestUrl.search}`,
|
|
175
|
+
method: "POST",
|
|
176
|
+
headers: Object.fromEntries(headers.entries()),
|
|
177
|
+
servername
|
|
178
|
+
},
|
|
179
|
+
(response) => {
|
|
180
|
+
response.resume();
|
|
181
|
+
response.on("end", () => {
|
|
182
|
+
resolve({
|
|
183
|
+
ok: !!response.statusCode && response.statusCode >= 200 && response.statusCode < 300,
|
|
184
|
+
status: response.statusCode ?? 0,
|
|
185
|
+
statusText: response.statusMessage ?? ""
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
);
|
|
190
|
+
request.on("error", reject);
|
|
191
|
+
if (signal) {
|
|
192
|
+
signal.addEventListener(
|
|
193
|
+
"abort",
|
|
194
|
+
() => {
|
|
195
|
+
request.destroy(signal.reason instanceof Error ? signal.reason : new Error("Push notification timed out"));
|
|
196
|
+
},
|
|
197
|
+
{ once: true }
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
request.end(body);
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
async sendNotifications({
|
|
204
|
+
agentId,
|
|
205
|
+
task,
|
|
206
|
+
logger
|
|
207
|
+
}) {
|
|
208
|
+
const configs = this.pushNotificationStore.list({
|
|
209
|
+
agentId,
|
|
210
|
+
params: { id: task.id }
|
|
211
|
+
});
|
|
212
|
+
if (configs.length === 0) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
await Promise.allSettled(
|
|
216
|
+
configs.map(async (config) => {
|
|
217
|
+
const headers = new Headers({
|
|
218
|
+
"content-type": "application/json"
|
|
219
|
+
});
|
|
220
|
+
if (config.pushNotificationConfig.token) {
|
|
221
|
+
headers.set(
|
|
222
|
+
this.options.tokenHeaderName ?? DEFAULT_PUSH_NOTIFICATION_TOKEN_HEADER,
|
|
223
|
+
config.pushNotificationConfig.token
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
const auth = config.pushNotificationConfig.authentication;
|
|
227
|
+
if (auth?.credentials) {
|
|
228
|
+
if (auth.schemes.includes("Bearer")) {
|
|
229
|
+
headers.set("authorization", `Bearer ${auth.credentials}`);
|
|
230
|
+
} else if (auth.schemes.includes("Basic")) {
|
|
231
|
+
headers.set("authorization", `Basic ${auth.credentials}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
const { requestUrl, hostHeader, servername } = await this.resolveValidatedDestination(
|
|
235
|
+
config.pushNotificationConfig.url
|
|
236
|
+
);
|
|
237
|
+
const response = await this.postTaskSnapshot({
|
|
238
|
+
requestUrl,
|
|
239
|
+
hostHeader,
|
|
240
|
+
servername,
|
|
241
|
+
headers,
|
|
242
|
+
body: JSON.stringify(task),
|
|
243
|
+
timeout: this.options.timeout ?? 5e3
|
|
244
|
+
});
|
|
245
|
+
if (!response.ok) {
|
|
246
|
+
throw new Error(
|
|
247
|
+
`Push notification failed with status ${response.status} ${response.statusText ?? ""}`.trim()
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
})
|
|
251
|
+
).then((results) => {
|
|
252
|
+
for (const result of results) {
|
|
253
|
+
if (result.status === "rejected") {
|
|
254
|
+
logger?.error("Failed to deliver A2A push notification", result.reason);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
// src/server/a2a/push-notification-store.ts
|
|
262
|
+
function normalizeConfigId(taskId, configId) {
|
|
263
|
+
return configId || taskId;
|
|
264
|
+
}
|
|
265
|
+
var InMemoryPushNotificationStore = class {
|
|
266
|
+
store = /* @__PURE__ */ new Map();
|
|
267
|
+
getKey(agentId, taskId) {
|
|
268
|
+
return JSON.stringify([agentId, taskId]);
|
|
269
|
+
}
|
|
270
|
+
set({ agentId, config }) {
|
|
271
|
+
const key = this.getKey(agentId, config.taskId);
|
|
272
|
+
const configs = this.store.get(key) ?? /* @__PURE__ */ new Map();
|
|
273
|
+
const normalizedConfig = {
|
|
274
|
+
taskId: config.taskId,
|
|
275
|
+
pushNotificationConfig: {
|
|
276
|
+
...config.pushNotificationConfig,
|
|
277
|
+
id: normalizeConfigId(config.taskId, config.pushNotificationConfig.id)
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
configs.set(normalizedConfig.pushNotificationConfig.id, structuredClone(normalizedConfig));
|
|
281
|
+
this.store.set(key, configs);
|
|
282
|
+
return structuredClone(normalizedConfig);
|
|
283
|
+
}
|
|
284
|
+
get({
|
|
285
|
+
agentId,
|
|
286
|
+
params
|
|
287
|
+
}) {
|
|
288
|
+
const key = this.getKey(agentId, params.id);
|
|
289
|
+
const configId = normalizeConfigId(params.id, params.pushNotificationConfigId);
|
|
290
|
+
const config = this.store.get(key)?.get(configId);
|
|
291
|
+
return config ? structuredClone(config) : null;
|
|
292
|
+
}
|
|
293
|
+
list({
|
|
294
|
+
agentId,
|
|
295
|
+
params
|
|
296
|
+
}) {
|
|
297
|
+
const key = this.getKey(agentId, params.id);
|
|
298
|
+
return Array.from(this.store.get(key)?.values() ?? []).map((config) => structuredClone(config));
|
|
299
|
+
}
|
|
300
|
+
delete({ agentId, params }) {
|
|
301
|
+
const key = this.getKey(agentId, params.id);
|
|
302
|
+
const configs = this.store.get(key);
|
|
303
|
+
if (!configs) {
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
const deleted = configs.delete(params.pushNotificationConfigId);
|
|
307
|
+
if (configs.size === 0) {
|
|
308
|
+
this.store.delete(key);
|
|
309
|
+
}
|
|
310
|
+
return deleted;
|
|
311
|
+
}
|
|
312
|
+
};
|
|
80
313
|
|
|
81
314
|
// src/server/a2a/tasks.ts
|
|
82
315
|
function isTaskStatusUpdate(update) {
|
|
@@ -204,9 +437,27 @@ var messageSendParamsSchema = z.object({
|
|
|
204
437
|
referenceTaskIds: z.array(z.string()).optional(),
|
|
205
438
|
extensions: z.array(z.string()).optional(),
|
|
206
439
|
metadata: z.record(z.string(), z.any()).optional()
|
|
207
|
-
})
|
|
440
|
+
}),
|
|
441
|
+
configuration: z.object({
|
|
442
|
+
acceptedOutputModes: z.array(z.string()).optional(),
|
|
443
|
+
blocking: z.boolean().optional(),
|
|
444
|
+
historyLength: z.number().optional(),
|
|
445
|
+
pushNotificationConfig: z.object({
|
|
446
|
+
url: z.string(),
|
|
447
|
+
id: z.string().optional(),
|
|
448
|
+
token: z.string().optional(),
|
|
449
|
+
authentication: z.object({
|
|
450
|
+
schemes: z.array(z.string()),
|
|
451
|
+
credentials: z.string().optional()
|
|
452
|
+
}).optional()
|
|
453
|
+
}).optional()
|
|
454
|
+
}).optional()
|
|
208
455
|
});
|
|
209
|
-
|
|
456
|
+
var defaultPushNotificationStore = new InMemoryPushNotificationStore();
|
|
457
|
+
var defaultPushNotificationSender = new DefaultPushNotificationSender(defaultPushNotificationStore);
|
|
458
|
+
function createAgentCardDefaults({
|
|
459
|
+
pushNotifications = false
|
|
460
|
+
} = {}) {
|
|
210
461
|
return {
|
|
211
462
|
protocolVersion: "0.3.0",
|
|
212
463
|
additionalInterfaces: [],
|
|
@@ -215,7 +466,7 @@ function createAgentCardDefaults() {
|
|
|
215
466
|
securitySchemes: {},
|
|
216
467
|
capabilities: {
|
|
217
468
|
streaming: true,
|
|
218
|
-
pushNotifications
|
|
469
|
+
pushNotifications,
|
|
219
470
|
stateTransitionHistory: false,
|
|
220
471
|
extensions: []
|
|
221
472
|
},
|
|
@@ -232,6 +483,7 @@ async function getAgentCardByIdHandler({
|
|
|
232
483
|
url: "https://mastra.ai"
|
|
233
484
|
},
|
|
234
485
|
version = "1.0",
|
|
486
|
+
pushNotifications = false,
|
|
235
487
|
requestContext
|
|
236
488
|
}) {
|
|
237
489
|
const agent = await getAgentFromSystem({ mastra, agentId });
|
|
@@ -242,7 +494,7 @@ async function getAgentCardByIdHandler({
|
|
|
242
494
|
url: executionUrl,
|
|
243
495
|
provider,
|
|
244
496
|
version,
|
|
245
|
-
...createAgentCardDefaults(),
|
|
497
|
+
...createAgentCardDefaults({ pushNotifications }),
|
|
246
498
|
// Convert agent tools to skills format for A2A protocol
|
|
247
499
|
skills: Object.entries(tools).map(([toolId, tool]) => ({
|
|
248
500
|
id: toolId,
|
|
@@ -338,6 +590,63 @@ function createDataArtifactUpdate({
|
|
|
338
590
|
}
|
|
339
591
|
};
|
|
340
592
|
}
|
|
593
|
+
function resolvePushNotificationPair({
|
|
594
|
+
pushNotificationStore,
|
|
595
|
+
pushNotificationSender
|
|
596
|
+
}) {
|
|
597
|
+
if (pushNotificationSender) {
|
|
598
|
+
return {
|
|
599
|
+
pushNotificationStore: pushNotificationSender.getStore(),
|
|
600
|
+
pushNotificationSender
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
if (pushNotificationStore) {
|
|
604
|
+
return {
|
|
605
|
+
pushNotificationStore,
|
|
606
|
+
pushNotificationSender: new DefaultPushNotificationSender(pushNotificationStore)
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
return {
|
|
610
|
+
pushNotificationStore: defaultPushNotificationStore,
|
|
611
|
+
pushNotificationSender: defaultPushNotificationSender
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
function createTaskPushNotificationConfig(taskId, pushNotificationConfig) {
|
|
615
|
+
return {
|
|
616
|
+
taskId,
|
|
617
|
+
pushNotificationConfig: {
|
|
618
|
+
...pushNotificationConfig,
|
|
619
|
+
id: pushNotificationConfig.id ?? taskId
|
|
620
|
+
}
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
function shouldSendPushNotification(previousTask, nextTask) {
|
|
624
|
+
const pushTriggerStates = ["completed", "failed", "canceled", "input-required"];
|
|
625
|
+
if (!pushTriggerStates.includes(nextTask.status.state)) {
|
|
626
|
+
return false;
|
|
627
|
+
}
|
|
628
|
+
return previousTask?.status.state !== nextTask.status.state;
|
|
629
|
+
}
|
|
630
|
+
async function saveTaskAndMaybeSendPushNotification({
|
|
631
|
+
taskStore,
|
|
632
|
+
pushNotificationSender,
|
|
633
|
+
previousTask,
|
|
634
|
+
nextTask,
|
|
635
|
+
agentId,
|
|
636
|
+
logger
|
|
637
|
+
}) {
|
|
638
|
+
await taskStore.save({ agentId, data: nextTask });
|
|
639
|
+
if (!shouldSendPushNotification(previousTask, nextTask)) {
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
void pushNotificationSender.sendNotifications({
|
|
643
|
+
agentId,
|
|
644
|
+
task: nextTask,
|
|
645
|
+
logger
|
|
646
|
+
}).catch((error) => {
|
|
647
|
+
logger?.error("Failed to schedule A2A push notification", error);
|
|
648
|
+
});
|
|
649
|
+
}
|
|
341
650
|
function extractFullStreamTextDelta(value) {
|
|
342
651
|
if (typeof value !== "object" || value === null || !("type" in value)) {
|
|
343
652
|
return null;
|
|
@@ -442,6 +751,8 @@ async function handleMessageSend({
|
|
|
442
751
|
requestId,
|
|
443
752
|
params,
|
|
444
753
|
taskStore,
|
|
754
|
+
pushNotificationStore,
|
|
755
|
+
pushNotificationSender,
|
|
445
756
|
agent,
|
|
446
757
|
agentId,
|
|
447
758
|
logger,
|
|
@@ -451,6 +762,13 @@ async function handleMessageSend({
|
|
|
451
762
|
const { message, metadata } = params;
|
|
452
763
|
const { contextId } = message;
|
|
453
764
|
const taskId = message.taskId || crypto.randomUUID();
|
|
765
|
+
const {
|
|
766
|
+
pushNotificationStore: resolvedPushNotificationStore,
|
|
767
|
+
pushNotificationSender: resolvedPushNotificationSender
|
|
768
|
+
} = resolvePushNotificationPair({
|
|
769
|
+
pushNotificationStore,
|
|
770
|
+
pushNotificationSender
|
|
771
|
+
});
|
|
454
772
|
let currentData = await loadOrCreateTask({
|
|
455
773
|
taskId,
|
|
456
774
|
taskStore,
|
|
@@ -459,7 +777,13 @@ async function handleMessageSend({
|
|
|
459
777
|
contextId,
|
|
460
778
|
metadata
|
|
461
779
|
});
|
|
462
|
-
|
|
780
|
+
if (params.configuration?.pushNotificationConfig) {
|
|
781
|
+
resolvedPushNotificationStore.set({
|
|
782
|
+
agentId,
|
|
783
|
+
config: createTaskPushNotificationConfig(taskId, params.configuration.pushNotificationConfig)
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
const context = createTaskContext({
|
|
463
787
|
task: currentData,
|
|
464
788
|
userMessage: message,
|
|
465
789
|
history: currentData.history || [],
|
|
@@ -494,7 +818,15 @@ async function handleMessageSend({
|
|
|
494
818
|
finishReason: result.finishReason
|
|
495
819
|
}
|
|
496
820
|
};
|
|
497
|
-
await
|
|
821
|
+
await saveTaskAndMaybeSendPushNotification({
|
|
822
|
+
taskStore,
|
|
823
|
+
pushNotificationSender: resolvedPushNotificationSender,
|
|
824
|
+
previousTask: context.task,
|
|
825
|
+
nextTask: currentData,
|
|
826
|
+
agentId,
|
|
827
|
+
logger
|
|
828
|
+
});
|
|
829
|
+
context.task = currentData;
|
|
498
830
|
} catch (handlerError) {
|
|
499
831
|
const failureStatusUpdate = {
|
|
500
832
|
state: "failed",
|
|
@@ -512,7 +844,14 @@ async function handleMessageSend({
|
|
|
512
844
|
};
|
|
513
845
|
currentData = applyUpdateToTask(currentData, failureStatusUpdate);
|
|
514
846
|
try {
|
|
515
|
-
await
|
|
847
|
+
await saveTaskAndMaybeSendPushNotification({
|
|
848
|
+
taskStore,
|
|
849
|
+
pushNotificationSender: resolvedPushNotificationSender,
|
|
850
|
+
previousTask: context.task,
|
|
851
|
+
nextTask: currentData,
|
|
852
|
+
agentId,
|
|
853
|
+
logger
|
|
854
|
+
});
|
|
516
855
|
} catch (saveError) {
|
|
517
856
|
logger?.error(`Failed to save task ${currentData.id} after handler error:`, saveError?.message);
|
|
518
857
|
}
|
|
@@ -532,10 +871,115 @@ async function handleTaskGet({
|
|
|
532
871
|
}
|
|
533
872
|
return createSuccessResponse(requestId, task);
|
|
534
873
|
}
|
|
874
|
+
async function loadTaskOrThrow({
|
|
875
|
+
taskStore,
|
|
876
|
+
agentId,
|
|
877
|
+
taskId
|
|
878
|
+
}) {
|
|
879
|
+
const task = await taskStore.load({ agentId, taskId });
|
|
880
|
+
if (!task) {
|
|
881
|
+
throw MastraA2AError.taskNotFound(taskId);
|
|
882
|
+
}
|
|
883
|
+
return task;
|
|
884
|
+
}
|
|
885
|
+
async function handleSetTaskPushNotificationConfig({
|
|
886
|
+
requestId,
|
|
887
|
+
taskStore,
|
|
888
|
+
pushNotificationStore,
|
|
889
|
+
agentId,
|
|
890
|
+
params
|
|
891
|
+
}) {
|
|
892
|
+
await loadTaskOrThrow({
|
|
893
|
+
taskStore,
|
|
894
|
+
agentId,
|
|
895
|
+
taskId: params.taskId
|
|
896
|
+
});
|
|
897
|
+
const { pushNotificationStore: resolvedPushNotificationStore } = resolvePushNotificationPair({
|
|
898
|
+
pushNotificationStore
|
|
899
|
+
});
|
|
900
|
+
const config = resolvedPushNotificationStore.set({
|
|
901
|
+
agentId,
|
|
902
|
+
config: createTaskPushNotificationConfig(params.taskId, params.pushNotificationConfig)
|
|
903
|
+
});
|
|
904
|
+
return createSuccessResponse(requestId, config);
|
|
905
|
+
}
|
|
906
|
+
async function handleGetTaskPushNotificationConfig({
|
|
907
|
+
requestId,
|
|
908
|
+
taskStore,
|
|
909
|
+
pushNotificationStore,
|
|
910
|
+
agentId,
|
|
911
|
+
params
|
|
912
|
+
}) {
|
|
913
|
+
await loadTaskOrThrow({
|
|
914
|
+
taskStore,
|
|
915
|
+
agentId,
|
|
916
|
+
taskId: params.id
|
|
917
|
+
});
|
|
918
|
+
const { pushNotificationStore: resolvedPushNotificationStore } = resolvePushNotificationPair({
|
|
919
|
+
pushNotificationStore
|
|
920
|
+
});
|
|
921
|
+
const config = resolvedPushNotificationStore.get({
|
|
922
|
+
agentId,
|
|
923
|
+
params
|
|
924
|
+
});
|
|
925
|
+
if (!config) {
|
|
926
|
+
throw MastraA2AError.invalidParams(
|
|
927
|
+
`Push notification config not found: ${params.pushNotificationConfigId ?? params.id}`
|
|
928
|
+
);
|
|
929
|
+
}
|
|
930
|
+
return createSuccessResponse(requestId, config);
|
|
931
|
+
}
|
|
932
|
+
async function handleListTaskPushNotificationConfig({
|
|
933
|
+
requestId,
|
|
934
|
+
taskStore,
|
|
935
|
+
pushNotificationStore,
|
|
936
|
+
agentId,
|
|
937
|
+
params
|
|
938
|
+
}) {
|
|
939
|
+
await loadTaskOrThrow({
|
|
940
|
+
taskStore,
|
|
941
|
+
agentId,
|
|
942
|
+
taskId: params.id
|
|
943
|
+
});
|
|
944
|
+
const { pushNotificationStore: resolvedPushNotificationStore } = resolvePushNotificationPair({
|
|
945
|
+
pushNotificationStore
|
|
946
|
+
});
|
|
947
|
+
const configs = resolvedPushNotificationStore.list({
|
|
948
|
+
agentId,
|
|
949
|
+
params
|
|
950
|
+
});
|
|
951
|
+
return createSuccessResponse(requestId, configs);
|
|
952
|
+
}
|
|
953
|
+
async function handleDeleteTaskPushNotificationConfig({
|
|
954
|
+
requestId,
|
|
955
|
+
taskStore,
|
|
956
|
+
pushNotificationStore,
|
|
957
|
+
agentId,
|
|
958
|
+
params
|
|
959
|
+
}) {
|
|
960
|
+
await loadTaskOrThrow({
|
|
961
|
+
taskStore,
|
|
962
|
+
agentId,
|
|
963
|
+
taskId: params.id
|
|
964
|
+
});
|
|
965
|
+
const { pushNotificationStore: resolvedPushNotificationStore } = resolvePushNotificationPair({
|
|
966
|
+
pushNotificationStore
|
|
967
|
+
});
|
|
968
|
+
const deleted = resolvedPushNotificationStore.delete({
|
|
969
|
+
agentId,
|
|
970
|
+
params
|
|
971
|
+
});
|
|
972
|
+
if (!deleted) {
|
|
973
|
+
throw MastraA2AError.invalidParams(`Push notification config not found: ${params.pushNotificationConfigId}`);
|
|
974
|
+
}
|
|
975
|
+
return createSuccessResponse(requestId, null);
|
|
976
|
+
}
|
|
535
977
|
async function* handleMessageStream({
|
|
536
978
|
requestId,
|
|
537
979
|
params,
|
|
538
980
|
taskStore,
|
|
981
|
+
pushNotificationStore,
|
|
982
|
+
pushNotificationSender,
|
|
539
983
|
agent,
|
|
540
984
|
agentId,
|
|
541
985
|
logger,
|
|
@@ -545,6 +989,13 @@ async function* handleMessageStream({
|
|
|
545
989
|
const { message, metadata } = params;
|
|
546
990
|
const { contextId } = message;
|
|
547
991
|
const taskId = message.taskId || crypto.randomUUID();
|
|
992
|
+
const {
|
|
993
|
+
pushNotificationStore: resolvedPushNotificationStore,
|
|
994
|
+
pushNotificationSender: resolvedPushNotificationSender
|
|
995
|
+
} = resolvePushNotificationPair({
|
|
996
|
+
pushNotificationStore,
|
|
997
|
+
pushNotificationSender
|
|
998
|
+
});
|
|
548
999
|
let currentData = await loadOrCreateTask({
|
|
549
1000
|
taskId,
|
|
550
1001
|
taskStore,
|
|
@@ -553,6 +1004,12 @@ async function* handleMessageStream({
|
|
|
553
1004
|
contextId,
|
|
554
1005
|
metadata
|
|
555
1006
|
});
|
|
1007
|
+
if (params.configuration?.pushNotificationConfig) {
|
|
1008
|
+
resolvedPushNotificationStore.set({
|
|
1009
|
+
agentId,
|
|
1010
|
+
config: createTaskPushNotificationConfig(taskId, params.configuration.pushNotificationConfig)
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
556
1013
|
currentData = applyUpdateToTask(currentData, {
|
|
557
1014
|
state: "working",
|
|
558
1015
|
message: {
|
|
@@ -562,7 +1019,13 @@ async function* handleMessageStream({
|
|
|
562
1019
|
parts: [{ kind: "text", text: "Generating response..." }]
|
|
563
1020
|
}
|
|
564
1021
|
});
|
|
565
|
-
await
|
|
1022
|
+
await saveTaskAndMaybeSendPushNotification({
|
|
1023
|
+
taskStore,
|
|
1024
|
+
pushNotificationSender: resolvedPushNotificationSender,
|
|
1025
|
+
nextTask: currentData,
|
|
1026
|
+
agentId,
|
|
1027
|
+
logger
|
|
1028
|
+
});
|
|
566
1029
|
yield createSuccessResponse(requestId, currentData);
|
|
567
1030
|
try {
|
|
568
1031
|
const resourceId = metadata?.resourceId ?? message.metadata?.resourceId ?? agentId;
|
|
@@ -589,7 +1052,13 @@ async function* handleMessageStream({
|
|
|
589
1052
|
lastChunk: false
|
|
590
1053
|
});
|
|
591
1054
|
currentData = applyUpdateToTask(currentData, textUpdate);
|
|
592
|
-
await
|
|
1055
|
+
await saveTaskAndMaybeSendPushNotification({
|
|
1056
|
+
taskStore,
|
|
1057
|
+
pushNotificationSender: resolvedPushNotificationSender,
|
|
1058
|
+
nextTask: currentData,
|
|
1059
|
+
agentId,
|
|
1060
|
+
logger
|
|
1061
|
+
});
|
|
593
1062
|
yield createSuccessResponse(requestId, textUpdate);
|
|
594
1063
|
sawTextArtifact = true;
|
|
595
1064
|
pendingTextChunk = textDelta;
|
|
@@ -616,7 +1085,13 @@ async function* handleMessageStream({
|
|
|
616
1085
|
lastChunk: !structuredData
|
|
617
1086
|
});
|
|
618
1087
|
currentData = applyUpdateToTask(currentData, textUpdate);
|
|
619
|
-
await
|
|
1088
|
+
await saveTaskAndMaybeSendPushNotification({
|
|
1089
|
+
taskStore,
|
|
1090
|
+
pushNotificationSender: resolvedPushNotificationSender,
|
|
1091
|
+
nextTask: currentData,
|
|
1092
|
+
agentId,
|
|
1093
|
+
logger
|
|
1094
|
+
});
|
|
620
1095
|
yield createSuccessResponse(requestId, textUpdate);
|
|
621
1096
|
sawTextArtifact = true;
|
|
622
1097
|
pendingTextChunk = void 0;
|
|
@@ -629,15 +1104,22 @@ async function* handleMessageStream({
|
|
|
629
1104
|
lastChunk: true
|
|
630
1105
|
});
|
|
631
1106
|
currentData = applyUpdateToTask(currentData, dataUpdate);
|
|
632
|
-
await
|
|
1107
|
+
await saveTaskAndMaybeSendPushNotification({
|
|
1108
|
+
taskStore,
|
|
1109
|
+
pushNotificationSender: resolvedPushNotificationSender,
|
|
1110
|
+
nextTask: currentData,
|
|
1111
|
+
agentId,
|
|
1112
|
+
logger
|
|
1113
|
+
});
|
|
633
1114
|
yield createSuccessResponse(requestId, dataUpdate);
|
|
634
1115
|
}
|
|
635
|
-
|
|
1116
|
+
const previousTask = currentData;
|
|
1117
|
+
const completedTask = applyUpdateToTask(currentData, {
|
|
636
1118
|
state: "completed",
|
|
637
1119
|
message: void 0
|
|
638
1120
|
});
|
|
639
|
-
|
|
640
|
-
...
|
|
1121
|
+
completedTask.metadata = {
|
|
1122
|
+
...completedTask.metadata,
|
|
641
1123
|
execution: {
|
|
642
1124
|
toolCalls: await result.toolCalls,
|
|
643
1125
|
toolResults: await result.toolResults,
|
|
@@ -645,8 +1127,17 @@ async function* handleMessageStream({
|
|
|
645
1127
|
finishReason: await result.finishReason
|
|
646
1128
|
}
|
|
647
1129
|
};
|
|
648
|
-
|
|
1130
|
+
currentData = completedTask;
|
|
1131
|
+
await saveTaskAndMaybeSendPushNotification({
|
|
1132
|
+
taskStore,
|
|
1133
|
+
pushNotificationSender: resolvedPushNotificationSender,
|
|
1134
|
+
previousTask,
|
|
1135
|
+
nextTask: currentData,
|
|
1136
|
+
agentId,
|
|
1137
|
+
logger
|
|
1138
|
+
});
|
|
649
1139
|
} catch (handlerError) {
|
|
1140
|
+
const previousTask = currentData;
|
|
650
1141
|
currentData = applyUpdateToTask(currentData, {
|
|
651
1142
|
state: "failed",
|
|
652
1143
|
message: {
|
|
@@ -662,7 +1153,14 @@ async function* handleMessageStream({
|
|
|
662
1153
|
}
|
|
663
1154
|
});
|
|
664
1155
|
try {
|
|
665
|
-
await
|
|
1156
|
+
await saveTaskAndMaybeSendPushNotification({
|
|
1157
|
+
taskStore,
|
|
1158
|
+
pushNotificationSender: resolvedPushNotificationSender,
|
|
1159
|
+
previousTask,
|
|
1160
|
+
nextTask: currentData,
|
|
1161
|
+
agentId,
|
|
1162
|
+
logger
|
|
1163
|
+
});
|
|
666
1164
|
} catch (saveError) {
|
|
667
1165
|
logger?.error(`Failed to save task ${currentData.id} after handler error:`, saveError?.message);
|
|
668
1166
|
}
|
|
@@ -769,6 +1267,7 @@ function createA2ASSEResponse(payload) {
|
|
|
769
1267
|
async function handleTaskCancel({
|
|
770
1268
|
requestId,
|
|
771
1269
|
taskStore,
|
|
1270
|
+
pushNotificationSender,
|
|
772
1271
|
agentId,
|
|
773
1272
|
taskId,
|
|
774
1273
|
logger
|
|
@@ -795,8 +1294,16 @@ async function handleTaskCancel({
|
|
|
795
1294
|
messageId: crypto.randomUUID()
|
|
796
1295
|
}
|
|
797
1296
|
};
|
|
1297
|
+
const previousTask = data;
|
|
798
1298
|
data = applyUpdateToTask(data, cancelUpdate);
|
|
799
|
-
await
|
|
1299
|
+
await saveTaskAndMaybeSendPushNotification({
|
|
1300
|
+
taskStore,
|
|
1301
|
+
pushNotificationSender: resolvePushNotificationPair({ pushNotificationSender }).pushNotificationSender,
|
|
1302
|
+
previousTask,
|
|
1303
|
+
nextTask: data,
|
|
1304
|
+
agentId,
|
|
1305
|
+
logger
|
|
1306
|
+
});
|
|
800
1307
|
taskStore.activeCancellations.delete(taskId);
|
|
801
1308
|
return createSuccessResponse(requestId, data);
|
|
802
1309
|
}
|
|
@@ -808,10 +1315,19 @@ async function getAgentExecutionHandler({
|
|
|
808
1315
|
method,
|
|
809
1316
|
params,
|
|
810
1317
|
taskStore,
|
|
1318
|
+
pushNotificationStore,
|
|
1319
|
+
pushNotificationSender,
|
|
811
1320
|
logger,
|
|
812
1321
|
abortSignal
|
|
813
1322
|
}) {
|
|
814
1323
|
const agent = await getAgentFromSystem({ mastra, agentId });
|
|
1324
|
+
const {
|
|
1325
|
+
pushNotificationStore: resolvedPushNotificationStore,
|
|
1326
|
+
pushNotificationSender: resolvedPushNotificationSender
|
|
1327
|
+
} = resolvePushNotificationPair({
|
|
1328
|
+
pushNotificationStore,
|
|
1329
|
+
pushNotificationSender
|
|
1330
|
+
});
|
|
815
1331
|
let taskId;
|
|
816
1332
|
try {
|
|
817
1333
|
taskId = getTaskIdFromParams(params);
|
|
@@ -821,8 +1337,11 @@ async function getAgentExecutionHandler({
|
|
|
821
1337
|
requestId,
|
|
822
1338
|
params,
|
|
823
1339
|
taskStore,
|
|
1340
|
+
pushNotificationStore: resolvedPushNotificationStore,
|
|
1341
|
+
pushNotificationSender: resolvedPushNotificationSender,
|
|
824
1342
|
agent,
|
|
825
1343
|
agentId,
|
|
1344
|
+
logger,
|
|
826
1345
|
requestContext
|
|
827
1346
|
});
|
|
828
1347
|
return result;
|
|
@@ -832,8 +1351,11 @@ async function getAgentExecutionHandler({
|
|
|
832
1351
|
requestId,
|
|
833
1352
|
taskStore,
|
|
834
1353
|
params,
|
|
1354
|
+
pushNotificationStore: resolvedPushNotificationStore,
|
|
1355
|
+
pushNotificationSender: resolvedPushNotificationSender,
|
|
835
1356
|
agent,
|
|
836
1357
|
agentId,
|
|
1358
|
+
logger,
|
|
837
1359
|
requestContext
|
|
838
1360
|
});
|
|
839
1361
|
return result;
|
|
@@ -851,8 +1373,10 @@ async function getAgentExecutionHandler({
|
|
|
851
1373
|
const result = await handleTaskCancel({
|
|
852
1374
|
requestId,
|
|
853
1375
|
taskStore,
|
|
1376
|
+
pushNotificationSender: resolvedPushNotificationSender,
|
|
854
1377
|
agentId,
|
|
855
|
-
taskId: taskId || "No task ID provided"
|
|
1378
|
+
taskId: taskId || "No task ID provided",
|
|
1379
|
+
logger
|
|
856
1380
|
});
|
|
857
1381
|
return result;
|
|
858
1382
|
}
|
|
@@ -865,10 +1389,37 @@ async function getAgentExecutionHandler({
|
|
|
865
1389
|
abortSignal
|
|
866
1390
|
});
|
|
867
1391
|
case "tasks/pushNotificationConfig/set":
|
|
1392
|
+
return await handleSetTaskPushNotificationConfig({
|
|
1393
|
+
requestId,
|
|
1394
|
+
taskStore,
|
|
1395
|
+
pushNotificationStore: resolvedPushNotificationStore,
|
|
1396
|
+
agentId,
|
|
1397
|
+
params
|
|
1398
|
+
});
|
|
868
1399
|
case "tasks/pushNotificationConfig/get":
|
|
1400
|
+
return await handleGetTaskPushNotificationConfig({
|
|
1401
|
+
requestId,
|
|
1402
|
+
taskStore,
|
|
1403
|
+
pushNotificationStore: resolvedPushNotificationStore,
|
|
1404
|
+
agentId,
|
|
1405
|
+
params
|
|
1406
|
+
});
|
|
869
1407
|
case "tasks/pushNotificationConfig/list":
|
|
1408
|
+
return await handleListTaskPushNotificationConfig({
|
|
1409
|
+
requestId,
|
|
1410
|
+
taskStore,
|
|
1411
|
+
pushNotificationStore: resolvedPushNotificationStore,
|
|
1412
|
+
agentId,
|
|
1413
|
+
params
|
|
1414
|
+
});
|
|
870
1415
|
case "tasks/pushNotificationConfig/delete":
|
|
871
|
-
|
|
1416
|
+
return await handleDeleteTaskPushNotificationConfig({
|
|
1417
|
+
requestId,
|
|
1418
|
+
taskStore,
|
|
1419
|
+
pushNotificationStore: resolvedPushNotificationStore,
|
|
1420
|
+
agentId,
|
|
1421
|
+
params
|
|
1422
|
+
});
|
|
872
1423
|
case "agent/getAuthenticatedExtendedCard":
|
|
873
1424
|
throw MastraA2AError.extendedAgentCardNotConfigured();
|
|
874
1425
|
default:
|
|
@@ -901,7 +1452,8 @@ var GET_AGENT_CARD_ROUTE = createRoute({
|
|
|
901
1452
|
mastra: ctx.mastra,
|
|
902
1453
|
requestContext: ctx.requestContext,
|
|
903
1454
|
agentId: ctx.agentId,
|
|
904
|
-
executionUrl
|
|
1455
|
+
executionUrl,
|
|
1456
|
+
pushNotifications: true
|
|
905
1457
|
});
|
|
906
1458
|
}
|
|
907
1459
|
});
|
|
@@ -936,6 +1488,6 @@ var AGENT_EXECUTION_ROUTE = createRoute({
|
|
|
936
1488
|
}
|
|
937
1489
|
});
|
|
938
1490
|
|
|
939
|
-
export { AGENT_EXECUTION_ROUTE, GET_AGENT_CARD_ROUTE, a2a_exports, getAgentCardByIdHandler, getAgentExecutionHandler, handleMessageSend, handleMessageStream, handleTaskCancel, handleTaskGet, handleTaskResubscribe };
|
|
940
|
-
//# sourceMappingURL=chunk-
|
|
941
|
-
//# sourceMappingURL=chunk-
|
|
1491
|
+
export { AGENT_EXECUTION_ROUTE, GET_AGENT_CARD_ROUTE, a2a_exports, getAgentCardByIdHandler, getAgentExecutionHandler, handleDeleteTaskPushNotificationConfig, handleGetTaskPushNotificationConfig, handleListTaskPushNotificationConfig, handleMessageSend, handleMessageStream, handleSetTaskPushNotificationConfig, handleTaskCancel, handleTaskGet, handleTaskResubscribe };
|
|
1492
|
+
//# sourceMappingURL=chunk-3KIFZFY7.js.map
|
|
1493
|
+
//# sourceMappingURL=chunk-3KIFZFY7.js.map
|