@artinet/sdk 0.6.0-preview.3 → 0.6.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.
Files changed (153) hide show
  1. package/README.md +100 -50
  2. package/dist/browser/browser.d.ts +2 -7
  3. package/dist/browser/browser.js +2 -7
  4. package/dist/browser/config/observability.d.ts +1 -1
  5. package/dist/browser/create/message-builder.d.ts +1 -1
  6. package/dist/browser/create/message-builder.js +19 -7
  7. package/dist/browser/create/task-builder.js +1 -1
  8. package/dist/browser/messenger/index.d.ts +1 -0
  9. package/dist/browser/messenger/index.js +1 -0
  10. package/dist/browser/messenger/messenger.d.ts +119 -0
  11. package/dist/browser/messenger/messenger.js +245 -0
  12. package/dist/browser/types/a2a/a2a.d.ts +38 -20
  13. package/dist/browser/types/a2a/a2a.js +0 -1
  14. package/dist/browser/types/core/core.d.ts +4 -2
  15. package/dist/browser/types/index.d.ts +0 -1
  16. package/dist/browser/types/index.js +0 -1
  17. package/dist/browser/types/storage.d.ts +2 -14
  18. package/dist/browser/types/storage.js +0 -4
  19. package/dist/browser/utils/{common/constants.d.ts → constants.d.ts} +1 -1
  20. package/dist/{utils/common → browser/utils}/constants.js +1 -1
  21. package/dist/browser/utils/{common/errors.d.ts → errors.d.ts} +17 -36
  22. package/dist/browser/utils/errors.js +76 -0
  23. package/dist/browser/utils/index.d.ts +6 -0
  24. package/dist/browser/utils/index.js +6 -0
  25. package/dist/{utils/common → browser/utils}/parse.js +1 -1
  26. package/dist/{utils/common → browser/utils}/schema-validation.js +2 -2
  27. package/dist/config/index.d.ts +1 -1
  28. package/dist/config/observability.d.ts +1 -1
  29. package/dist/create/agent-builder.d.ts +1 -1
  30. package/dist/create/create.d.ts +19 -20
  31. package/dist/create/create.js +33 -101
  32. package/dist/create/message-builder.d.ts +1 -1
  33. package/dist/create/message-builder.js +19 -7
  34. package/dist/create/task-builder.js +1 -1
  35. package/dist/index.d.ts +3 -3
  36. package/dist/index.js +3 -3
  37. package/dist/messenger/index.d.ts +1 -0
  38. package/dist/messenger/index.js +1 -0
  39. package/dist/messenger/messenger.d.ts +119 -0
  40. package/dist/messenger/messenger.js +251 -0
  41. package/dist/server/adapters/a2a_request_handler.d.ts +889 -0
  42. package/dist/server/adapters/a2a_request_handler.js +241 -0
  43. package/dist/server/adapters/loadable.d.ts +7 -0
  44. package/dist/server/adapters/loadable.js +73 -0
  45. package/dist/server/adapters/notifications.d.ts +26 -0
  46. package/dist/server/adapters/notifications.js +77 -0
  47. package/dist/server/express/server.d.ts +11 -19
  48. package/dist/server/express/server.js +29 -64
  49. package/dist/server/express/utils.d.ts +14 -0
  50. package/dist/server/express/{errors.js → utils.js} +22 -0
  51. package/dist/server/index.d.ts +4 -1
  52. package/dist/server/index.js +4 -1
  53. package/dist/server/params.d.ts +115 -0
  54. package/dist/server/params.js +21 -0
  55. package/dist/services/a2a/factory/context.d.ts +2 -1
  56. package/dist/services/a2a/factory/context.js +4 -3
  57. package/dist/services/a2a/factory/handler.d.ts +1 -1
  58. package/dist/services/a2a/factory/handler.js +7 -6
  59. package/dist/services/a2a/factory/service.d.ts +1 -1
  60. package/dist/services/a2a/factory/service.js +2 -2
  61. package/dist/services/a2a/factory/state-machine.js +9 -6
  62. package/dist/services/a2a/handlers/cancel-task.d.ts +1 -1
  63. package/dist/services/a2a/handlers/get-task.d.ts +1 -1
  64. package/dist/services/a2a/handlers/resubscribe-task.d.ts +2 -2
  65. package/dist/services/a2a/handlers/send-message.d.ts +1 -1
  66. package/dist/services/a2a/handlers/stream-message.d.ts +2 -2
  67. package/dist/services/a2a/handlers/update.js +2 -2
  68. package/dist/services/a2a/index.d.ts +0 -1
  69. package/dist/services/a2a/index.js +0 -1
  70. package/dist/services/a2a/managers.js +2 -1
  71. package/dist/services/a2a/messenger.d.ts +1 -1
  72. package/dist/services/a2a/messenger.js +1 -1
  73. package/dist/services/a2a/service.d.ts +26 -21
  74. package/dist/services/a2a/service.js +160 -92
  75. package/dist/services/a2a/state-machine.d.ts +1 -1
  76. package/dist/services/a2a/state-machine.js +2 -1
  77. package/dist/services/a2a/streams.js +1 -1
  78. package/dist/services/core/manager.d.ts +5 -0
  79. package/dist/services/core/manager.js +6 -0
  80. package/dist/services/mcp/service.js +1 -1
  81. package/dist/{utils/storage → storage}/file.d.ts +4 -2
  82. package/dist/{utils/storage → storage}/file.js +5 -4
  83. package/dist/storage/index.d.ts +1 -0
  84. package/dist/storage/index.js +2 -0
  85. package/dist/storage/sqlite.d.ts +353 -0
  86. package/dist/storage/sqlite.js +85 -0
  87. package/dist/transport/trpc/a2a/factory/router.d.ts +16 -16
  88. package/dist/transport/trpc/a2a/routes/info.d.ts +2 -2
  89. package/dist/transport/trpc/a2a/routes/message/route.d.ts +3 -3
  90. package/dist/transport/trpc/a2a/routes/message/route.js +2 -2
  91. package/dist/transport/trpc/a2a/routes/tasks/route.d.ts +4 -4
  92. package/dist/transport/trpc/a2a/routes/tasks/route.js +3 -3
  93. package/dist/types/a2a/a2a.d.ts +38 -20
  94. package/dist/types/a2a/a2a.js +0 -1
  95. package/dist/types/core/core.d.ts +4 -2
  96. package/dist/types/index.d.ts +0 -1
  97. package/dist/types/index.js +0 -1
  98. package/dist/types/storage.d.ts +2 -14
  99. package/dist/types/storage.js +0 -4
  100. package/dist/utils/{common/constants.d.ts → constants.d.ts} +1 -1
  101. package/dist/{browser/utils/common → utils}/constants.js +1 -1
  102. package/dist/utils/{common/errors.d.ts → errors.d.ts} +17 -36
  103. package/dist/utils/errors.js +80 -0
  104. package/dist/utils/index.d.ts +6 -10
  105. package/dist/utils/index.js +6 -10
  106. package/dist/utils/parse.d.ts +7 -0
  107. package/dist/utils/parse.js +14 -0
  108. package/dist/utils/schema-validation.d.ts +2 -0
  109. package/dist/utils/schema-validation.js +12 -0
  110. package/package.json +35 -22
  111. package/dist/browser/client/a2a-client.d.ts +0 -127
  112. package/dist/browser/client/a2a-client.js +0 -233
  113. package/dist/browser/client/index.d.ts +0 -1
  114. package/dist/browser/client/index.js +0 -1
  115. package/dist/browser/transport/rpc/parser.d.ts +0 -15
  116. package/dist/browser/transport/rpc/parser.js +0 -49
  117. package/dist/browser/transport/rpc/rpc-client.d.ts +0 -80
  118. package/dist/browser/transport/rpc/rpc-client.js +0 -189
  119. package/dist/browser/transport/streaming/event-stream.d.ts +0 -25
  120. package/dist/browser/transport/streaming/event-stream.js +0 -100
  121. package/dist/browser/types/client.d.ts +0 -133
  122. package/dist/browser/types/client.js +0 -5
  123. package/dist/browser/utils/common/errors.js +0 -95
  124. package/dist/client/a2a-client.d.ts +0 -127
  125. package/dist/client/a2a-client.js +0 -237
  126. package/dist/client/index.d.ts +0 -1
  127. package/dist/client/index.js +0 -1
  128. package/dist/server/express/errors.d.ts +0 -9
  129. package/dist/server/express/index.d.ts +0 -3
  130. package/dist/server/express/index.js +0 -3
  131. package/dist/server/express/middeware.d.ts +0 -7
  132. package/dist/server/express/middeware.js +0 -121
  133. package/dist/transport/index.d.ts +0 -3
  134. package/dist/transport/index.js +0 -4
  135. package/dist/transport/rpc/parser.d.ts +0 -15
  136. package/dist/transport/rpc/parser.js +0 -49
  137. package/dist/transport/rpc/rpc-client.d.ts +0 -80
  138. package/dist/transport/rpc/rpc-client.js +0 -189
  139. package/dist/transport/streaming/event-stream.d.ts +0 -25
  140. package/dist/transport/streaming/event-stream.js +0 -100
  141. package/dist/types/client.d.ts +0 -133
  142. package/dist/types/client.js +0 -5
  143. package/dist/utils/common/errors.js +0 -98
  144. /package/dist/{utils/common → browser/utils}/parse.d.ts +0 -0
  145. /package/dist/{utils/common → browser/utils}/schema-validation.d.ts +0 -0
  146. /package/dist/browser/utils/{common/utils.d.ts → utils.d.ts} +0 -0
  147. /package/dist/browser/utils/{common/utils.js → utils.js} +0 -0
  148. /package/dist/utils/{common/utils.d.ts → utils.d.ts} +0 -0
  149. /package/dist/utils/{common/utils.js → utils.js} +0 -0
  150. /package/dist/utils/{common/zAsyncIterable-v3.d.ts → zAsyncIterable-v3.d.ts} +0 -0
  151. /package/dist/utils/{common/zAsyncIterable-v3.js → zAsyncIterable-v3.js} +0 -0
  152. /package/dist/utils/{common/zAsyncIterable.d.ts → zAsyncIterable.d.ts} +0 -0
  153. /package/dist/utils/{common/zAsyncIterable.js → zAsyncIterable.js} +0 -0
@@ -0,0 +1,241 @@
1
+ /**
2
+ * Copyright 2025 The Artinet Project
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { A2AError, DefaultPushNotificationSender, } from "@a2a-js/sdk/server";
6
+ import { A2A } from "../../types/index.js";
7
+ import { PushNotifications } from "./notifications.js";
8
+ import { logger } from "../../config/index.js";
9
+ import { SystemError, validateSchema } from "../../utils/index.js";
10
+ /**We want to avoid pulling @a2a-js/sdk logic into our business logic. */
11
+ const toServiceOptions = (context, notify) => {
12
+ return {
13
+ userId: context?.user?.userName,
14
+ extensions: context?.activatedExtensions?.map((extension) => ({
15
+ uri: extension,
16
+ })) ?? [],
17
+ notifier: notify,
18
+ };
19
+ };
20
+ const toA2AError = (error) => {
21
+ if (error instanceof A2AError) {
22
+ return error;
23
+ }
24
+ if (error instanceof SystemError) {
25
+ return new A2AError(error.code, error.message, error.data, error.taskId);
26
+ }
27
+ return error;
28
+ };
29
+ const isGetTaskPushNotificationConfigParam = (params) => {
30
+ return A2A.GetTaskPushNotificationConfigParamSchema.safeParse(params).success;
31
+ };
32
+ const paramsRequired = (params) => {
33
+ if (!params || Object.keys(params).length === 0) {
34
+ throw A2AError.invalidParams("Params Required");
35
+ }
36
+ };
37
+ const validateParams = async (schema, params) => {
38
+ paramsRequired(params);
39
+ return await validateSchema(schema, params);
40
+ };
41
+ export class Native {
42
+ _service;
43
+ _pushNotifications;
44
+ _extendAgentCard;
45
+ constructor(_service, _pushNotifications, _extendAgentCard) {
46
+ this._service = _service;
47
+ this._pushNotifications = _pushNotifications;
48
+ this._extendAgentCard = _extendAgentCard;
49
+ }
50
+ get service() {
51
+ return this._service;
52
+ }
53
+ async getAgentCard() {
54
+ return await this.service.getAgentCard();
55
+ }
56
+ async getTask(params, context) {
57
+ if (!params || Object.keys(params).length === 0) {
58
+ throw A2AError.invalidParams("Params Required");
59
+ }
60
+ return await this.service
61
+ .getTask(params, toServiceOptions(context))
62
+ .catch((error) => {
63
+ throw toA2AError(error);
64
+ });
65
+ }
66
+ async cancelTask(params, context) {
67
+ paramsRequired(params);
68
+ return await this.service
69
+ .cancelTask(params, toServiceOptions(context))
70
+ .catch((error) => {
71
+ throw toA2AError(error);
72
+ });
73
+ }
74
+ async sendMessage(params, context) {
75
+ paramsRequired(params);
76
+ return await this.service
77
+ .sendMessage(params, toServiceOptions(context, {
78
+ notify: this.notify,
79
+ register: this.registerConfig,
80
+ }))
81
+ .catch((error) => {
82
+ throw toA2AError(error);
83
+ });
84
+ }
85
+ async *sendMessageStream(params, context) {
86
+ paramsRequired(params);
87
+ try {
88
+ yield* this.service.sendMessageStream(params, toServiceOptions(context, {
89
+ notify: this.notify,
90
+ register: this.registerConfig,
91
+ }));
92
+ }
93
+ catch (error) {
94
+ throw toA2AError(error);
95
+ }
96
+ }
97
+ async *resubscribe(params, context) {
98
+ paramsRequired(params);
99
+ try {
100
+ yield* this.service.resubscribe(params, toServiceOptions(context, {
101
+ notify: this.notify,
102
+ register: this.registerConfig,
103
+ }));
104
+ }
105
+ catch (error) {
106
+ throw toA2AError(error);
107
+ }
108
+ }
109
+ get pushNotifications() {
110
+ return this._pushNotifications;
111
+ }
112
+ async pushNotificationsEnabled(taskId) {
113
+ if (!(await this._service.getAgentCard())?.capabilities?.pushNotifications ||
114
+ !this.pushNotifications) {
115
+ throw A2AError.pushNotificationNotSupported();
116
+ }
117
+ if (taskId && !(await this._service.tasks.has(taskId))) {
118
+ throw A2AError.taskNotFound(taskId ?? "Unknown task");
119
+ }
120
+ return;
121
+ }
122
+ async setTaskPushNotificationConfig(_params, _context) {
123
+ const params = await validateParams(A2A.TaskPushNotificationConfigSchema, _params);
124
+ await this.pushNotificationsEnabled(params.taskId);
125
+ const { taskId, pushNotificationConfig } = params;
126
+ pushNotificationConfig.id = pushNotificationConfig.id ?? taskId;
127
+ await this.pushNotifications.save(taskId, pushNotificationConfig);
128
+ logger.debug("Setting push notification config for task: ", {
129
+ taskId,
130
+ pushNotificationConfigId: pushNotificationConfig.id,
131
+ });
132
+ return {
133
+ taskId,
134
+ pushNotificationConfig,
135
+ };
136
+ }
137
+ async getTaskPushNotificationConfig(_params, _context) {
138
+ const params = await validateParams(A2A.GetTaskPushNotificationConfigParamsSchema, _params);
139
+ await this.pushNotificationsEnabled(params.id);
140
+ const { id: taskId } = params;
141
+ const configs = await this.pushNotifications.load(taskId);
142
+ if (!configs) {
143
+ throw A2AError.internalError(`Push notification config not found for task: ${taskId}`);
144
+ }
145
+ let configId = taskId;
146
+ if (isGetTaskPushNotificationConfigParam(params) &&
147
+ params.pushNotificationConfigId) {
148
+ configId = params.pushNotificationConfigId;
149
+ }
150
+ const pushNotificationConfig = configs.find((config) => config.id === configId);
151
+ if (!pushNotificationConfig) {
152
+ throw A2AError.internalError(`Push notification config not found for task: ${taskId} and config: ${configId}`);
153
+ }
154
+ return {
155
+ taskId,
156
+ pushNotificationConfig,
157
+ };
158
+ }
159
+ async listTaskPushNotificationConfigs(_params, _context) {
160
+ const params = await validateParams(A2A.ListTaskPushNotificationConfigParamsSchema, _params);
161
+ await this.pushNotificationsEnabled(params.id);
162
+ const { id: taskId } = params;
163
+ const configs = await this.pushNotifications.load(taskId);
164
+ if (!configs) {
165
+ return [];
166
+ }
167
+ return configs.map((pushNotificationConfig) => ({
168
+ taskId,
169
+ pushNotificationConfig,
170
+ }));
171
+ }
172
+ async deleteTaskPushNotificationConfig(_params, _context) {
173
+ const params = await validateParams(A2A.DeleteTaskPushNotificationConfigParamsSchema, _params);
174
+ await this.pushNotificationsEnabled(params.id);
175
+ const { id: taskId } = params;
176
+ await this.pushNotifications.delete(taskId);
177
+ }
178
+ registerConfig = async (taskId, config) => {
179
+ await this.pushNotificationsEnabled(taskId);
180
+ await this.pushNotifications?.save(taskId, config);
181
+ };
182
+ notify = async (task, _update, _context) => {
183
+ const enabled = await this.pushNotificationsEnabled(task.id)
184
+ .then(() => true)
185
+ .catch(() => {
186
+ logger.warn("Push notifications not enabled for task: ", {
187
+ taskId: task.id,
188
+ });
189
+ return false;
190
+ });
191
+ if (!enabled) {
192
+ return;
193
+ }
194
+ return await this.pushNotifications.send(task);
195
+ };
196
+ async getAuthenticatedExtendedAgentCard(context) {
197
+ if (!(await this.getAgentCard()).supportsAuthenticatedExtendedCard) {
198
+ throw A2AError.unsupportedOperation("Agent does not support authenticated extended card.");
199
+ }
200
+ if (!this._extendAgentCard) {
201
+ throw A2AError.authenticatedExtendedCardNotConfigured();
202
+ }
203
+ if (typeof this._extendAgentCard === "function") {
204
+ return await this._extendAgentCard(context);
205
+ }
206
+ if (context?.user?.isAuthenticated) {
207
+ return this._extendAgentCard;
208
+ }
209
+ return await this.getAgentCard();
210
+ }
211
+ static create(service, _pushNotifications, extendAgentCard) {
212
+ if (!_pushNotifications) {
213
+ const pushNotifications = new PushNotifications();
214
+ pushNotifications.sender = new DefaultPushNotificationSender(pushNotifications);
215
+ return new Native(service, pushNotifications, extendAgentCard);
216
+ }
217
+ if (_pushNotifications instanceof PushNotifications) {
218
+ return new Native(service, _pushNotifications, extendAgentCard);
219
+ }
220
+ const pushNotifications = new PushNotifications(_pushNotifications?.store);
221
+ pushNotifications.sender =
222
+ _pushNotifications?.sender ??
223
+ new DefaultPushNotificationSender(pushNotifications);
224
+ return new Native(service, pushNotifications, extendAgentCard);
225
+ }
226
+ }
227
+ /**
228
+ * native adapter for `@a2a-js/sdk`
229
+ * @param service - The service to wrap
230
+ * @param pushNotifications - (optional) arguments for creating {@link PushNotifications}
231
+ * @param extendAgentCard - (optional) The extend agent card/provider to use
232
+ * @returns A {@link A2ARequestHandler} instance
233
+ * @example
234
+ * ```typescript
235
+ * const agent = cr8("Custom Agent")
236
+ * .text("Hello!")
237
+ * .agent;
238
+ * const nativeAdapter = native(agent, pushNotifications, extendAgentCard);
239
+ * ```
240
+ */
241
+ export const native = Native.create;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Copyright 2025 The Artinet Project
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { A2A } from "../../types/index.js";
6
+ import { TaskStore } from "@a2a-js/sdk/server";
7
+ export declare const tasks: (taskStore: TaskStore) => A2A.Tasks;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Copyright 2025 The Artinet Project
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { A2A } from "../../types/index.js";
6
+ import { logger } from "../../config/index.js";
7
+ import { handleUpdate } from "../../services/a2a/handlers/update.js";
8
+ import { v4 } from "uuid";
9
+ import { getCurrentTimestamp } from "../../utils/utils.js";
10
+ class LoadManager {
11
+ _loadable;
12
+ constructor(_loadable) {
13
+ this._loadable = _loadable;
14
+ }
15
+ async get(id, _context) {
16
+ return await this._loadable.load(id, _context);
17
+ }
18
+ async set(id, data, context) {
19
+ return await this._loadable.save(data, context, id);
20
+ }
21
+ async delete(id) {
22
+ logger.warn("Delete not supported for loadable", { id });
23
+ return;
24
+ }
25
+ async has(id) {
26
+ return (await this._loadable.load(id)) !== undefined;
27
+ }
28
+ }
29
+ class TaskManager extends LoadManager {
30
+ constructor(_loadable) {
31
+ super(_loadable);
32
+ }
33
+ async update(context, update) {
34
+ logger.info(`TaskManager[update]: updating task`, {
35
+ taskId: context.taskId,
36
+ });
37
+ logger.debug(`TaskManager[update]: update`, { update });
38
+ logger.debug(`TaskManager[update]: context`, { context });
39
+ const task = await handleUpdate({
40
+ context,
41
+ task: await context.getTask(),
42
+ update,
43
+ });
44
+ logger.debug(`TaskManager[update]: task`, task);
45
+ await this.set(task.id, task);
46
+ return task;
47
+ }
48
+ async create(params) {
49
+ if (params.id) {
50
+ const task = await this.get(params.id);
51
+ if (task) {
52
+ return task;
53
+ }
54
+ }
55
+ logger.info(`TaskManager[create]: creating task`, { id: params.id });
56
+ const task = {
57
+ ...params,
58
+ id: params.id ?? v4(),
59
+ contextId: params.contextId ?? v4(),
60
+ kind: "task",
61
+ status: {
62
+ state: A2A.TaskState.submitted,
63
+ timestamp: getCurrentTimestamp(),
64
+ },
65
+ };
66
+ logger.debug(`TaskManager[create]:`, { taskId: task.id });
67
+ await this.set(task.id, task);
68
+ return task;
69
+ }
70
+ }
71
+ export const tasks = (taskStore) => {
72
+ return new TaskManager(taskStore);
73
+ };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Copyright 2025 The Artinet Project
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { PushNotificationStore, PushNotificationSender } from "@a2a-js/sdk/server";
6
+ import { A2A, core } from "../../types/index.js";
7
+ import { Manager } from "../../services/core/manager.js";
8
+ export interface Notifications extends core.Manager<A2A.PushNotificationConfig[]> {
9
+ save: (taskId: string, pushNotificationConfig: A2A.PushNotificationConfig) => Promise<void>;
10
+ load: (taskId: string) => Promise<A2A.PushNotificationConfig[]>;
11
+ delete: (taskId: string, configId?: string) => Promise<void>;
12
+ send: (task: A2A.Task) => Promise<void>;
13
+ }
14
+ /** Cached Push Notifications Manager */
15
+ export declare class PushNotifications extends Manager<A2A.PushNotificationConfig[]> implements Notifications {
16
+ private readonly _store;
17
+ private _sender;
18
+ constructor(store?: PushNotificationStore, sender?: PushNotificationSender);
19
+ get store(): PushNotificationStore | undefined;
20
+ get sender(): PushNotificationSender | undefined;
21
+ set sender(sender: PushNotificationSender | undefined);
22
+ save(taskId: string, pushNotificationConfig: A2A.PushNotificationConfig): Promise<void>;
23
+ load(taskId: string): Promise<A2A.PushNotificationConfig[]>;
24
+ delete(taskId: string, configId?: string): Promise<void>;
25
+ send(task: A2A.Task): Promise<void>;
26
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Copyright 2025 The Artinet Project
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { InMemoryPushNotificationStore, } from "@a2a-js/sdk/server";
6
+ import { Manager } from "../../services/core/manager.js";
7
+ /** Cached Push Notifications Manager */
8
+ export class PushNotifications
9
+ //May be more efficient to use a Record/Map instead of an array
10
+ extends Manager {
11
+ _store;
12
+ _sender;
13
+ constructor(store, sender) {
14
+ if (store && store instanceof InMemoryPushNotificationStore) {
15
+ /** We snatch its internal store to avoid creating a new Map and doubling memory usage */
16
+ super(store?.store);
17
+ }
18
+ else {
19
+ super();
20
+ }
21
+ this._store = store;
22
+ this._sender = sender;
23
+ }
24
+ get store() {
25
+ return this._store;
26
+ }
27
+ get sender() {
28
+ return this._sender;
29
+ }
30
+ set sender(sender) {
31
+ this._sender = sender;
32
+ }
33
+ async save(taskId, pushNotificationConfig) {
34
+ pushNotificationConfig.id = pushNotificationConfig.id ?? taskId;
35
+ /** Cache the configs in memory for faster access */
36
+ const configs = await this.get(taskId);
37
+ await this.set(taskId, [
38
+ ...(configs?.filter(
39
+ /**
40
+ * Since this is pure memory we can stomach the heavy filter operation for now,
41
+ * and its unlikely that an individual task will have excessive configs.
42
+ * @note Consider adding a warning when the filter operation is called with a large number of configs.
43
+ */
44
+ (config) => config.id !== pushNotificationConfig.id) ?? []),
45
+ pushNotificationConfig,
46
+ ]);
47
+ return await this.store?.save(taskId, pushNotificationConfig);
48
+ }
49
+ async load(taskId) {
50
+ let configs = await this.get(taskId);
51
+ /**
52
+ * Cache the configs in memory for faster access regardless of the storage layer.
53
+ * @note this may be removed once we have a persistant storage layer plugin.
54
+ */
55
+ if (!configs || configs.length === 0) {
56
+ configs = await this.store?.load(taskId);
57
+ if (configs && configs.length > 0) {
58
+ await this.set(taskId, configs);
59
+ }
60
+ }
61
+ return configs ?? [];
62
+ }
63
+ async delete(taskId, configId) {
64
+ if (configId) {
65
+ await this.set(taskId, (await this.get(taskId))?.filter((config) => config.id !== configId) ??
66
+ []);
67
+ }
68
+ else {
69
+ /**We dont need to maintain backward compatibility, so we can just delete all configs for the task*/
70
+ await super.delete(taskId);
71
+ }
72
+ await this.store?.delete(taskId, configId);
73
+ }
74
+ async send(task) {
75
+ return await this.sender?.send(task);
76
+ }
77
+ }
@@ -3,31 +3,19 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import express from "express";
6
- import { A2A } from "../../types/index.js";
7
- import { Agent } from "../../services/a2a/index.js";
8
- import { ServiceParams as CreateAgentParams } from "../../services/index.js";
9
6
  import { CorsOptions } from "cors";
10
- export interface ServerParams {
7
+ import { ServerParams as BaseServerParams } from "../params.js";
8
+ export type ServerParams = BaseServerParams & {
11
9
  app?: express.Express;
12
10
  corsOptions?: CorsOptions;
13
- basePath?: string;
14
- port?: number;
15
- /**
16
- * Your agentCard must have supportsAuthenticatedExtendedCard set to true
17
- */
18
- extendedAgentCard?: A2A.AgentCard;
19
- agent: Agent | CreateAgentParams;
20
- agentCardPath?: string;
21
- register?: boolean;
22
- }
23
- export declare function rpcParser(req: express.Request, res: express.Response, next: express.NextFunction): void;
11
+ };
24
12
  /**
25
13
  * @note Best used with the `cr8` builder.
26
14
  * @param {ServerParams} params - The server parameters
27
15
  * @returns {ExpressAgentServer} - The express agent server
28
16
  * @example
29
17
  * ```typescript
30
- * const { app, agent, start } = createAgentServer({
18
+ * const { app, agent, start } = serve({
31
19
  * agent: cr8("MyAgent")
32
20
  * .text("Hello, world!")
33
21
  * .agent,
@@ -35,9 +23,13 @@ export declare function rpcParser(req: express.Request, res: express.Response, n
35
23
  * });
36
24
  * ```
37
25
  */
38
- export declare function createAgentServer({ app, basePath, agentCardPath, agent, corsOptions, extendedAgentCard, register, port, }: ServerParams): {
26
+ export declare function serve({ app, basePath, agentCardPath, agent, corsOptions, extendedAgentCard, register, port, userBuilder, }: ServerParams): {
39
27
  app: express.Express;
40
- agent: Agent;
28
+ agent: import("../../index.js").Agent;
41
29
  start: (_port?: number) => import("node:http").Server<typeof import("node:http").IncomingMessage, typeof import("node:http").ServerResponse>;
42
30
  };
43
- export type ExpressAgentServer = ReturnType<typeof createAgentServer>;
31
+ /**
32
+ * @deprecated Use `cr8.serve` instead.
33
+ */
34
+ export declare const createAgentServer: typeof serve;
35
+ export type ExpressAgentServer = ReturnType<typeof serve>;
@@ -3,58 +3,18 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import express from "express";
6
- import { createAgent, Service, } from "../../services/index.js";
7
6
  import cors from "cors";
8
- import { jsonRPCMiddleware } from "./middeware.js";
9
- import { errorHandler } from "./errors.js";
10
7
  import { logger } from "../../config/index.js";
11
- import { A2AError } from "@a2a-js/sdk/server";
12
- import { formatJson } from "../../utils/common/utils.js";
13
- export function rpcParser(req, res, next) {
14
- express.json()(req, res, (err) => {
15
- if (!req.body || typeof req.body !== "object") {
16
- return next(A2AError.parseError(`Invalid request body: ${formatJson(req.body)}`));
17
- }
18
- if (err) {
19
- if (err instanceof SyntaxError &&
20
- "status" in err &&
21
- err.status === 400 &&
22
- "body" in err) {
23
- return next(A2AError.parseError(`Invalid request body: ${formatJson(req.body)}`));
24
- }
25
- return next(err);
26
- }
27
- next();
28
- });
29
- }
30
- const isParams = (agentOrParams) => {
31
- return (agentOrParams &&
32
- typeof agentOrParams === "object" &&
33
- "engine" in agentOrParams &&
34
- typeof agentOrParams.engine === "function" &&
35
- "agentCard" in agentOrParams &&
36
- typeof agentOrParams.agentCard === "object");
37
- };
38
- const ensureAgent = (agentOrParams) => {
39
- if (agentOrParams instanceof Service) {
40
- return agentOrParams;
41
- }
42
- else if (isParams(agentOrParams)) {
43
- return createAgent(agentOrParams);
44
- }
45
- throw new Error("invalid agent or params");
46
- };
47
- const registerAgent = async (agentCard) => {
48
- logger.debug("registerAgent: not implemented", { agentCard });
49
- return Promise.resolve(agentCard);
50
- };
8
+ import { native } from "../adapters/a2a_request_handler.js";
9
+ import { jsonRpcHandler, UserBuilder } from "@a2a-js/sdk/server/express";
10
+ import { ensureAgent, registerAgent, } from "../params.js";
51
11
  /**
52
12
  * @note Best used with the `cr8` builder.
53
13
  * @param {ServerParams} params - The server parameters
54
14
  * @returns {ExpressAgentServer} - The express agent server
55
15
  * @example
56
16
  * ```typescript
57
- * const { app, agent, start } = createAgentServer({
17
+ * const { app, agent, start } = serve({
58
18
  * agent: cr8("MyAgent")
59
19
  * .text("Hello, world!")
60
20
  * .agent,
@@ -62,38 +22,39 @@ const registerAgent = async (agentCard) => {
62
22
  * });
63
23
  * ```
64
24
  */
65
- export function createAgentServer({ app = express(), basePath = "/", agentCardPath = "/.well-known/agent-card.json", agent, corsOptions, extendedAgentCard, register = false, port, }) {
25
+ export function serve({ app = express(), basePath = "/", agentCardPath = "/.well-known/agent-card.json", agent, corsOptions, extendedAgentCard, register = false, port, userBuilder = UserBuilder.noAuthentication, }) {
66
26
  const agentInstance = ensureAgent(agent);
67
- app.use(cors(corsOptions));
27
+ /**
28
+ * Now that agents are services we can wrap them in any kind of transport layer
29
+ * or in express we can use json-rpc, but we could also use websockets, etc
30
+ */
31
+ agentInstance.getAgentCard().then((card) => {
32
+ const url = new URL(card.url);
33
+ if (!url.pathname.startsWith(basePath)) {
34
+ logger.warn(`AgentCard may be misconfigured: URL pathname ${url.pathname} does not start with base path ${basePath}, this may cause issues with the client.`);
35
+ }
36
+ });
37
+ const router = express.Router();
38
+ router.use(cors(corsOptions));
68
39
  if (agentCardPath !== "/.well-known/agent-card.json") {
69
- // mount at the root for compliance with RFC8615 standard
70
40
  // todo: align with emerging multi-agent standards
71
- app.use("/.well-known/agent-card.json", (_, res) => {
41
+ router.use(`/.well-known/agent-card.json`, (_, res) => {
72
42
  res.json(agentInstance.agentCard);
73
43
  });
74
44
  }
75
- app.use(agentCardPath, (_, res) => {
45
+ router.use(`${agentCardPath}`, (_, res) => {
76
46
  // mount at the custom path
77
47
  res.json(agentInstance.agentCard);
78
48
  });
79
49
  // mount at the old agent card path for backwards compatibility
80
- app.use("/.well-known/agent.json", (_, res) => {
50
+ router.use(`/.well-known/agent.json`, (_, res) => {
81
51
  res.json(agentInstance.agentCard);
82
52
  });
83
- /**
84
- * Now that agents are services we can wrap them in any kind of transport layer
85
- * for express we can use json-rpc, but we could also use websockets, or any other
86
- * transport layer.
87
- */
88
- //a standard express middleware to handle json-rpc requests
89
- app.post(basePath, rpcParser, async (req, res, next) => {
90
- const { jsonrpc } = req.body;
91
- if (jsonrpc !== "2.0") {
92
- return next(A2AError.invalidRequest("Invalid JSON-RPC request"));
93
- }
94
- return await jsonRPCMiddleware(agentInstance, req, res, next, extendedAgentCard);
95
- });
96
- app.use(errorHandler);
53
+ router.use(jsonRpcHandler({
54
+ requestHandler: native(agentInstance, undefined, extendedAgentCard),
55
+ userBuilder: userBuilder,
56
+ }));
57
+ app.use(basePath, router);
97
58
  /** this is an example of using trpc as express middleware
98
59
  app.use(
99
60
  `${basePath}`,
@@ -128,3 +89,7 @@ export function createAgentServer({ app = express(), basePath = "/", agentCardPa
128
89
  };
129
90
  return { app, agent: agentInstance, start };
130
91
  }
92
+ /**
93
+ * @deprecated Use `cr8.serve` instead.
94
+ */
95
+ export const createAgentServer = serve;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Copyright 2025 The Artinet Project
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ *
5
+ * @archive Helper utilities for express servers.
6
+ * @note We recommend using the @a2a-js/sdk/express middleware instead as these utilities will no longer be robustly maintained.
7
+ */
8
+ import { type ErrorRequestHandler } from "express";
9
+ import express from "express";
10
+ export declare function rpcParser(req: express.Request, res: express.Response, next: express.NextFunction): void;
11
+ /**
12
+ * Express error handler middleware.
13
+ */
14
+ export declare const errorHandler: ErrorRequestHandler;
@@ -1,11 +1,33 @@
1
1
  /**
2
2
  * Copyright 2025 The Artinet Project
3
3
  * SPDX-License-Identifier: Apache-2.0
4
+ *
5
+ * @archive Helper utilities for express servers.
6
+ * @note We recommend using the @a2a-js/sdk/express middleware instead as these utilities will no longer be robustly maintained.
4
7
  */
5
8
  import { SystemError } from "../../utils/index.js";
6
9
  import { logger } from "../../config/index.js";
7
10
  import escapeHtml from "escape-html";
8
11
  import { A2AError } from "@a2a-js/sdk/server";
12
+ import { formatJson } from "../../utils/index.js";
13
+ import express from "express";
14
+ export function rpcParser(req, res, next) {
15
+ express.json()(req, res, (err) => {
16
+ if (!req.body || typeof req.body !== "object") {
17
+ return next(A2AError.parseError(`Invalid request body: ${formatJson(req.body)}`));
18
+ }
19
+ if (err) {
20
+ if (err instanceof SyntaxError &&
21
+ "status" in err &&
22
+ err.status === 400 &&
23
+ "body" in err) {
24
+ return next(A2AError.parseError(`Invalid request body: ${formatJson(req.body)}`));
25
+ }
26
+ return next(err);
27
+ }
28
+ next();
29
+ });
30
+ }
9
31
  /**
10
32
  * Express error handler middleware.
11
33
  */
@@ -1 +1,4 @@
1
- export * from "./express/index.js";
1
+ export { native } from "./adapters/a2a_request_handler.js";
2
+ export { tasks } from "./adapters/loadable.js";
3
+ export { serve, type ServerParams, type ExpressAgentServer, createAgentServer, } from "./express/server.js";
4
+ export { rpcParser, errorHandler } from "./express/utils.js";
@@ -1 +1,4 @@
1
- export * from "./express/index.js";
1
+ export { native } from "./adapters/a2a_request_handler.js";
2
+ export { tasks } from "./adapters/loadable.js";
3
+ export { serve, createAgentServer, } from "./express/server.js";
4
+ export { rpcParser, errorHandler } from "./express/utils.js";