agentstack-sdk 0.6.1 → 0.6.2-rc2

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 (199) hide show
  1. package/README.md +36 -29
  2. package/dist/api.cjs +1994 -2
  3. package/dist/api.d.cts +29 -0
  4. package/dist/api.d.ts +25 -1
  5. package/dist/api.js +1801 -2
  6. package/dist/core-DcGxYeok.d.ts +1238 -0
  7. package/dist/core-XN6gWSAb.d.cts +1238 -0
  8. package/dist/core.cjs +1773 -2
  9. package/dist/core.d.cts +7 -0
  10. package/dist/core.d.ts +7 -5
  11. package/dist/core.js +1725 -2
  12. package/dist/extensions.cjs +798 -2
  13. package/dist/extensions.d.cts +244 -0
  14. package/dist/extensions.d.ts +240 -1
  15. package/dist/extensions.js +652 -2
  16. package/dist/index.cjs +3142 -2
  17. package/dist/index.d.cts +10 -0
  18. package/dist/index.d.ts +10 -7
  19. package/dist/index.js +2781 -2
  20. package/dist/index.umd.js +16509 -2
  21. package/dist/schemas-Dy3P_eAt.d.cts +57 -0
  22. package/dist/schemas-Dy3P_eAt.d.ts +57 -0
  23. package/dist/server.cjs +2762 -0
  24. package/dist/server.d.cts +244 -0
  25. package/dist/server.d.ts +244 -0
  26. package/dist/server.js +2716 -0
  27. package/dist/types-B5B3b0V2.d.cts +396 -0
  28. package/dist/types-B5B3b0V2.d.ts +396 -0
  29. package/dist/types-CmEs5_Ag.d.cts +3522 -0
  30. package/dist/types-DJm5-rZZ.d.ts +3522 -0
  31. package/dist/types-DvLt-XuC.d.ts +866 -0
  32. package/dist/types-E26YDM19.d.cts +866 -0
  33. package/dist/types-MfIzGgpV.d.cts +43 -0
  34. package/dist/types-MfIzGgpV.d.ts +43 -0
  35. package/package.json +36 -21
  36. package/src/client/a2a/extensions/auth/oauth/index.ts +6 -6
  37. package/src/client/a2a/extensions/auth/secrets/index.ts +6 -6
  38. package/src/client/a2a/extensions/interactions/approval/index.ts +7 -7
  39. package/src/client/a2a/extensions/services/embedding/index.ts +7 -3
  40. package/src/client/a2a/extensions/services/form/index.ts +3 -3
  41. package/src/client/a2a/extensions/services/llm/index.ts +3 -3
  42. package/src/client/a2a/extensions/services/mcp/index.ts +3 -3
  43. package/src/client/a2a/extensions/services/platform-api/index.ts +2 -2
  44. package/src/client/a2a/extensions/ui/agent-detail/index.ts +4 -4
  45. package/src/client/a2a/extensions/ui/canvas/index.ts +4 -4
  46. package/src/client/a2a/extensions/ui/citation/index.ts +4 -4
  47. package/src/client/a2a/extensions/ui/error/index.ts +4 -4
  48. package/src/client/a2a/extensions/ui/form-request/index.ts +4 -4
  49. package/src/client/a2a/extensions/ui/settings/index.ts +7 -3
  50. package/src/client/a2a/extensions/ui/trajectory/index.ts +4 -4
  51. package/src/client/core/extensions/types.ts +8 -1
  52. package/src/client/core/handle-task-status-update.ts +10 -3
  53. package/src/client/core/index.ts +1 -0
  54. package/src/client/core/utils/extract-text-from-message.ts +15 -0
  55. package/src/examples/hello-world.ts +34 -0
  56. package/src/experimental/server/a2a/extensions/agent-detail/index.ts +35 -0
  57. package/src/experimental/server/a2a/extensions/agent-detail/types.ts +10 -0
  58. package/src/experimental/server/a2a/extensions/index.ts +11 -0
  59. package/src/experimental/server/a2a/extensions/llm/index.ts +70 -0
  60. package/src/experimental/server/a2a/extensions/llm/types.ts +16 -0
  61. package/src/experimental/server/a2a/extensions/platform-self-registration/index.ts +34 -0
  62. package/src/experimental/server/a2a/extensions/platform-self-registration/types.ts +10 -0
  63. package/src/experimental/server/a2a/helpers.ts +95 -0
  64. package/{dist/client/a2a/index.d.ts → src/experimental/server/a2a/index.ts} +1 -1
  65. package/src/experimental/server/a2a/utils.ts +43 -0
  66. package/src/experimental/server/core/config/index.ts +17 -0
  67. package/src/experimental/server/core/config/schemas.ts +15 -0
  68. package/src/experimental/server/core/config/types.ts +10 -0
  69. package/src/experimental/server/core/context/index.ts +18 -0
  70. package/src/experimental/server/core/extensions/types.ts +24 -0
  71. package/{dist/client/a2a/protocol/index.d.ts → src/experimental/server/core/index.ts} +4 -0
  72. package/{dist/client/a2a/protocol/tests.d.ts → src/experimental/server/core/schemas.ts} +2 -1
  73. package/src/experimental/server/core/server/autoregistration.ts +142 -0
  74. package/src/experimental/server/core/server/executor.ts +284 -0
  75. package/src/experimental/server/core/server/helpers.ts +12 -0
  76. package/src/experimental/server/core/server/index.ts +166 -0
  77. package/src/experimental/server/core/server/types.ts +58 -0
  78. package/src/experimental/server/core/types.ts +8 -0
  79. package/src/experimental/server/core/utils.ts +59 -0
  80. package/{dist/client/api/core/errors/index.d.ts → src/server.ts} +3 -2
  81. package/dist/api.cjs.map +0 -1
  82. package/dist/api.js.map +0 -1
  83. package/dist/api.umd.js +0 -2
  84. package/dist/api.umd.js.map +0 -1
  85. package/dist/client/a2a/extensions/auth/oauth/index.d.ts +0 -10
  86. package/dist/client/a2a/extensions/auth/oauth/schemas.d.ts +0 -32
  87. package/dist/client/a2a/extensions/auth/oauth/types.d.ts +0 -13
  88. package/dist/client/a2a/extensions/auth/secrets/index.d.ts +0 -10
  89. package/dist/client/a2a/extensions/auth/secrets/schemas.d.ts +0 -23
  90. package/dist/client/a2a/extensions/auth/secrets/types.d.ts +0 -10
  91. package/dist/client/a2a/extensions/common/form/schemas.d.ts +0 -290
  92. package/dist/client/a2a/extensions/common/form/types.d.ts +0 -24
  93. package/dist/client/a2a/extensions/index.d.ts +0 -21
  94. package/dist/client/a2a/extensions/interactions/approval/index.d.ts +0 -10
  95. package/dist/client/a2a/extensions/interactions/approval/schemas.d.ts +0 -43
  96. package/dist/client/a2a/extensions/interactions/approval/types.d.ts +0 -14
  97. package/dist/client/a2a/extensions/schemas.d.ts +0 -19
  98. package/dist/client/a2a/extensions/services/embedding/index.d.ts +0 -9
  99. package/dist/client/a2a/extensions/services/embedding/schemas.d.ts +0 -29
  100. package/dist/client/a2a/extensions/services/embedding/types.d.ts +0 -10
  101. package/dist/client/a2a/extensions/services/form/index.d.ts +0 -9
  102. package/dist/client/a2a/extensions/services/form/schemas.d.ts +0 -97
  103. package/dist/client/a2a/extensions/services/form/types.d.ts +0 -8
  104. package/dist/client/a2a/extensions/services/llm/index.d.ts +0 -9
  105. package/dist/client/a2a/extensions/services/llm/schemas.d.ts +0 -29
  106. package/dist/client/a2a/extensions/services/llm/types.d.ts +0 -10
  107. package/dist/client/a2a/extensions/services/mcp/index.d.ts +0 -9
  108. package/dist/client/a2a/extensions/services/mcp/schemas.d.ts +0 -35
  109. package/dist/client/a2a/extensions/services/mcp/types.d.ts +0 -14
  110. package/dist/client/a2a/extensions/services/platform-api/index.d.ts +0 -11
  111. package/dist/client/a2a/extensions/services/platform-api/schemas.d.ts +0 -10
  112. package/dist/client/a2a/extensions/services/platform-api/types.d.ts +0 -7
  113. package/dist/client/a2a/extensions/types.d.ts +0 -19
  114. package/dist/client/a2a/extensions/ui/agent-detail/index.d.ts +0 -9
  115. package/dist/client/a2a/extensions/ui/agent-detail/schemas.d.ts +0 -41
  116. package/dist/client/a2a/extensions/ui/agent-detail/types.d.ts +0 -13
  117. package/dist/client/a2a/extensions/ui/canvas/index.d.ts +0 -9
  118. package/dist/client/a2a/extensions/ui/canvas/schemas.d.ts +0 -11
  119. package/dist/client/a2a/extensions/ui/canvas/types.d.ts +0 -7
  120. package/dist/client/a2a/extensions/ui/citation/index.d.ts +0 -9
  121. package/dist/client/a2a/extensions/ui/citation/schemas.d.ts +0 -21
  122. package/dist/client/a2a/extensions/ui/citation/types.d.ts +0 -8
  123. package/dist/client/a2a/extensions/ui/error/index.d.ts +0 -9
  124. package/dist/client/a2a/extensions/ui/error/schemas.d.ts +0 -30
  125. package/dist/client/a2a/extensions/ui/error/types.d.ts +0 -9
  126. package/dist/client/a2a/extensions/ui/form-request/index.d.ts +0 -9
  127. package/dist/client/a2a/extensions/ui/settings/index.d.ts +0 -9
  128. package/dist/client/a2a/extensions/ui/settings/schemas.d.ts +0 -113
  129. package/dist/client/a2a/extensions/ui/settings/types.d.ts +0 -18
  130. package/dist/client/a2a/extensions/ui/trajectory/index.d.ts +0 -9
  131. package/dist/client/a2a/extensions/ui/trajectory/schemas.d.ts +0 -10
  132. package/dist/client/a2a/extensions/ui/trajectory/types.d.ts +0 -7
  133. package/dist/client/a2a/protocol/schemas.d.ts +0 -988
  134. package/dist/client/a2a/protocol/types.d.ts +0 -52
  135. package/dist/client/a2a/protocol/utils.d.ts +0 -6
  136. package/dist/client/api/common/schemas.d.ts +0 -30
  137. package/dist/client/api/common/types.d.ts +0 -18
  138. package/dist/client/api/configuration/api.d.ts +0 -22
  139. package/dist/client/api/configuration/schemas.d.ts +0 -31
  140. package/dist/client/api/configuration/types.d.ts +0 -11
  141. package/dist/client/api/connectors/api.d.ts +0 -78
  142. package/dist/client/api/connectors/schemas.d.ts +0 -114
  143. package/dist/client/api/connectors/types.d.ts +0 -28
  144. package/dist/client/api/contexts/api.d.ts +0 -133
  145. package/dist/client/api/contexts/schemas.d.ts +0 -359
  146. package/dist/client/api/contexts/types.d.ts +0 -34
  147. package/dist/client/api/core/client.d.ts +0 -1273
  148. package/dist/client/api/core/errors/types.d.ts +0 -36
  149. package/dist/client/api/core/errors/utils.d.ts +0 -23
  150. package/dist/client/api/core/index.d.ts +0 -7
  151. package/dist/client/api/core/schemas.d.ts +0 -17
  152. package/dist/client/api/core/types.d.ts +0 -45
  153. package/dist/client/api/core/utils.d.ts +0 -23
  154. package/dist/client/api/files/api.d.ts +0 -32
  155. package/dist/client/api/files/schemas.d.ts +0 -61
  156. package/dist/client/api/files/types.d.ts +0 -19
  157. package/dist/client/api/index.d.ts +0 -7
  158. package/dist/client/api/model-providers/api.d.ts +0 -50
  159. package/dist/client/api/model-providers/schemas.d.ts +0 -80
  160. package/dist/client/api/model-providers/types.d.ts +0 -44
  161. package/dist/client/api/provider-builds/api.d.ts +0 -143
  162. package/dist/client/api/provider-builds/schemas.d.ts +0 -250
  163. package/dist/client/api/provider-builds/types.d.ts +0 -31
  164. package/dist/client/api/providers/api.d.ts +0 -847
  165. package/dist/client/api/providers/schemas.d.ts +0 -1335
  166. package/dist/client/api/providers/types.d.ts +0 -45
  167. package/dist/client/api/schemas.d.ts +0 -15
  168. package/dist/client/api/types.d.ts +0 -15
  169. package/dist/client/api/user-feedback/api.d.ts +0 -9
  170. package/dist/client/api/user-feedback/schemas.d.ts +0 -15
  171. package/dist/client/api/user-feedback/types.d.ts +0 -8
  172. package/dist/client/api/users/api.d.ts +0 -13
  173. package/dist/client/api/users/schemas.d.ts +0 -20
  174. package/dist/client/api/users/types.d.ts +0 -14
  175. package/dist/client/api/variables/api.d.ts +0 -12
  176. package/dist/client/api/variables/schemas.d.ts +0 -13
  177. package/dist/client/api/variables/types.d.ts +0 -10
  178. package/dist/client/core/create-authenticated-fetch.d.ts +0 -5
  179. package/dist/client/core/extensions/extract.d.ts +0 -8
  180. package/dist/client/core/extensions/fulfill.d.ts +0 -8
  181. package/dist/client/core/extensions/resolve-user-metadata.d.ts +0 -6
  182. package/dist/client/core/extensions/types.d.ts +0 -68
  183. package/dist/client/core/fulfillment-resolvers/build-llm-extension-fulfillment-resolver.d.ts +0 -8
  184. package/dist/client/core/handle-agent-card.d.ts +0 -128
  185. package/dist/client/core/handle-task-status-update.d.ts +0 -7
  186. package/dist/client/core/index.d.ts +0 -14
  187. package/dist/client/core/utils/build-message-builder.d.ts +0 -9
  188. package/dist/client/core/utils/get-agent-card-path.d.ts +0 -5
  189. package/dist/core.cjs.map +0 -1
  190. package/dist/core.js.map +0 -1
  191. package/dist/core.umd.js +0 -2
  192. package/dist/core.umd.js.map +0 -1
  193. package/dist/extensions.cjs.map +0 -1
  194. package/dist/extensions.js.map +0 -1
  195. package/dist/extensions.umd.js +0 -2
  196. package/dist/extensions.umd.js.map +0 -1
  197. package/dist/index.cjs.map +0 -1
  198. package/dist/index.js.map +0 -1
  199. package/dist/index.umd.js.map +0 -1
@@ -0,0 +1,284 @@
1
+ /**
2
+ * Copyright 2025 © BeeAI a Series of LF Projects, LLC
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ import type { Message, Task } from '@a2a-js/sdk';
7
+ import type { AgentExecutor, ExecutionEventBus, RequestContext } from '@a2a-js/sdk/server';
8
+
9
+ import {
10
+ createArtifactUpdateEvent,
11
+ createDataPart,
12
+ createMessage,
13
+ createStatusUpdateEvent,
14
+ createTextPart,
15
+ } from '../../a2a/helpers';
16
+ import { isArtifact, isAsyncIterable, isMessage, isPart, isTaskStatus, isTaskStatusUpdateEvent } from '../../a2a/utils';
17
+ import { RunContext } from '../context';
18
+ import type { ExtensionConfig, ExtensionServer } from '../extensions/types';
19
+ import type { AgentFunction, RunYield } from './types';
20
+
21
+ export class AgentExecutorImpl<TDeps> implements AgentExecutor {
22
+ private readonly handler: AgentFunction<TDeps>;
23
+ private readonly extensions?: ExtensionConfig<TDeps>;
24
+ private readonly runningTasks: Map<string, { cancelled: boolean }> = new Map();
25
+
26
+ constructor(handler: AgentFunction<TDeps>, extensions?: ExtensionConfig<TDeps>) {
27
+ this.handler = handler;
28
+ this.extensions = extensions;
29
+ }
30
+
31
+ private getOrCreateTask(requestContext: RequestContext, eventBus: ExecutionEventBus): Task {
32
+ const { taskId, contextId, task } = requestContext;
33
+
34
+ if (task) {
35
+ return task;
36
+ }
37
+
38
+ const initialTask: Task = {
39
+ kind: 'task',
40
+ id: taskId,
41
+ contextId,
42
+ status: {
43
+ state: 'submitted',
44
+ timestamp: new Date().toISOString(),
45
+ },
46
+ history: [],
47
+ };
48
+
49
+ eventBus.publish(initialTask);
50
+
51
+ eventBus.publish(
52
+ createStatusUpdateEvent({
53
+ taskId: initialTask.id,
54
+ contextId,
55
+ status: {
56
+ state: 'working',
57
+ },
58
+ final: false,
59
+ }),
60
+ );
61
+
62
+ return initialTask;
63
+ }
64
+
65
+ async execute(requestContext: RequestContext, eventBus: ExecutionEventBus): Promise<void> {
66
+ const { userMessage, contextId } = requestContext;
67
+
68
+ const task = this.getOrCreateTask(requestContext, eventBus);
69
+ const runContext = new RunContext(task.id, contextId, task);
70
+ const taskState = { cancelled: false };
71
+
72
+ this.runningTasks.set(task.id, taskState);
73
+
74
+ try {
75
+ const deps = this.resolveExtensions(userMessage);
76
+ const result = this.handler(userMessage, runContext, deps);
77
+
78
+ if (isAsyncIterable(result)) {
79
+ for await (const yielded of result) {
80
+ if (taskState.cancelled) {
81
+ this.publishCancelled(eventBus, task.id, contextId);
82
+
83
+ return;
84
+ }
85
+
86
+ this.processYield(eventBus, task.id, contextId, yielded);
87
+ }
88
+ } else {
89
+ const awaited = await result;
90
+
91
+ if (awaited !== undefined) {
92
+ this.processYield(eventBus, task.id, contextId, awaited);
93
+ }
94
+ }
95
+
96
+ if (!taskState.cancelled) {
97
+ eventBus.publish(
98
+ createStatusUpdateEvent({
99
+ taskId: task.id,
100
+ contextId,
101
+ status: {
102
+ state: 'completed',
103
+ },
104
+ final: true,
105
+ }),
106
+ );
107
+ }
108
+ } catch (error) {
109
+ const message = createMessage({
110
+ taskId: task.id,
111
+ contextId,
112
+ parts: [createTextPart(error instanceof Error ? error.message : 'Unknown error')],
113
+ });
114
+
115
+ eventBus.publish(
116
+ createStatusUpdateEvent({
117
+ taskId: task.id,
118
+ contextId,
119
+ status: {
120
+ state: 'failed',
121
+ message,
122
+ },
123
+ final: true,
124
+ }),
125
+ );
126
+
127
+ this.runningTasks.delete(task.id);
128
+ } finally {
129
+ eventBus.finished();
130
+ }
131
+ }
132
+
133
+ async cancelTask(taskId: string): Promise<void> {
134
+ const taskState = this.runningTasks.get(taskId);
135
+
136
+ if (taskState) {
137
+ taskState.cancelled = true;
138
+ }
139
+ }
140
+
141
+ private resolveExtensions(message: Message): TDeps {
142
+ if (!this.extensions) {
143
+ return {} as TDeps;
144
+ }
145
+
146
+ const deps: Record<string, unknown> = {};
147
+
148
+ for (const [key, ext] of Object.entries(this.extensions) as [string, ExtensionServer][]) {
149
+ const fulfillments = ext.spec.parseFulfillments(message);
150
+
151
+ deps[key] = ext.resolveDeps(fulfillments);
152
+ }
153
+
154
+ return deps as TDeps;
155
+ }
156
+
157
+ private publishCancelled(eventBus: ExecutionEventBus, taskId: string, contextId: string): void {
158
+ eventBus.publish(
159
+ createStatusUpdateEvent({
160
+ taskId,
161
+ contextId,
162
+ status: {
163
+ state: 'canceled',
164
+ },
165
+ final: true,
166
+ }),
167
+ );
168
+ }
169
+
170
+ private processYield(eventBus: ExecutionEventBus, taskId: string, contextId: string, yielded: RunYield): void {
171
+ if (typeof yielded === 'string') {
172
+ const message = createMessage({
173
+ taskId,
174
+ contextId,
175
+ parts: [createTextPart(yielded)],
176
+ });
177
+
178
+ eventBus.publish(
179
+ createStatusUpdateEvent({
180
+ taskId,
181
+ contextId,
182
+ status: {
183
+ state: 'working',
184
+ message,
185
+ },
186
+ final: false,
187
+ }),
188
+ );
189
+ } else if (yielded instanceof Error) {
190
+ const message = createMessage({
191
+ taskId,
192
+ contextId,
193
+ parts: [createTextPart(yielded.message)],
194
+ });
195
+
196
+ eventBus.publish(
197
+ createStatusUpdateEvent({
198
+ taskId,
199
+ contextId,
200
+ status: {
201
+ state: 'failed',
202
+ message,
203
+ },
204
+ final: true,
205
+ }),
206
+ );
207
+ } else if (isMessage(yielded)) {
208
+ const message: Message = {
209
+ ...yielded,
210
+ taskId,
211
+ contextId,
212
+ };
213
+
214
+ eventBus.publish(
215
+ createStatusUpdateEvent({
216
+ taskId,
217
+ contextId,
218
+ status: {
219
+ state: 'working',
220
+ message,
221
+ },
222
+ final: false,
223
+ }),
224
+ );
225
+ } else if (isPart(yielded)) {
226
+ const message = createMessage({
227
+ taskId,
228
+ contextId,
229
+ parts: [yielded],
230
+ });
231
+
232
+ eventBus.publish(
233
+ createStatusUpdateEvent({
234
+ taskId,
235
+ contextId,
236
+ status: {
237
+ state: 'working',
238
+ message,
239
+ },
240
+ final: false,
241
+ }),
242
+ );
243
+ } else if (isTaskStatusUpdateEvent(yielded)) {
244
+ eventBus.publish(yielded);
245
+ } else if (isTaskStatus(yielded)) {
246
+ eventBus.publish(
247
+ createStatusUpdateEvent({
248
+ taskId,
249
+ contextId,
250
+ status: yielded,
251
+ final: false,
252
+ }),
253
+ );
254
+ } else if (isArtifact(yielded)) {
255
+ eventBus.publish(
256
+ createArtifactUpdateEvent({
257
+ taskId,
258
+ contextId,
259
+ artifact: yielded,
260
+ lastChunk: true,
261
+ append: false,
262
+ }),
263
+ );
264
+ } else if (typeof yielded === 'object' && yielded != null) {
265
+ const message = createMessage({
266
+ taskId,
267
+ contextId,
268
+ parts: [createDataPart(yielded)],
269
+ });
270
+
271
+ eventBus.publish(
272
+ createStatusUpdateEvent({
273
+ taskId,
274
+ contextId,
275
+ status: {
276
+ state: 'working',
277
+ message,
278
+ },
279
+ final: false,
280
+ }),
281
+ );
282
+ }
283
+ }
284
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Copyright 2025 © BeeAI a Series of LF Projects, LLC
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ export function createAgentCardUrl(host: string, port: number, selfRegistrationId?: string) {
7
+ return `http://${host === '0.0.0.0' ? 'localhost' : host}:${port}${selfRegistrationId ? `#${selfRegistrationId}` : ''}`;
8
+ }
9
+
10
+ export function normalizeDockerHost(host: string) {
11
+ return host.replace(/0\.0\.0\.0|localhost|127\.0\.0\.1/g, 'host.docker.internal');
12
+ }
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Copyright 2025 © BeeAI a Series of LF Projects, LLC
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ import type { AgentCard, AgentExtension } from '@a2a-js/sdk';
7
+ import { DefaultRequestHandler, InMemoryTaskStore } from '@a2a-js/sdk/server';
8
+ import { agentCardHandler, jsonRpcHandler, UserBuilder } from '@a2a-js/sdk/server/express';
9
+ import express from 'express';
10
+
11
+ import { buildApiClient } from '../../../../api';
12
+ import { AgentDetailExtensionSpec } from '../../a2a/extensions/agent-detail';
13
+ import { PlatformSelfRegistrationExtensionSpec } from '../../a2a/extensions/platform-self-registration';
14
+ import { loadConfig } from '../config';
15
+ import type { ExtensionConfig, ExtensionServer } from '../extensions/types';
16
+ import { createAutoregisterToAgentstack } from './autoregistration';
17
+ import { AgentExecutorImpl } from './executor';
18
+ import { createAgentCardUrl } from './helpers';
19
+ import type { AgentOptions, ServerHandle, ServerOptions } from './types';
20
+
21
+ export class Server {
22
+ private agentCard?: AgentCard;
23
+ private agentOptions?: AgentOptions<unknown>;
24
+ private agentConfigured = false;
25
+
26
+ agent<TDeps>(options: AgentOptions<TDeps>): this {
27
+ if (this.agentConfigured) {
28
+ throw new Error('Agent already configured. Only one agent per server is supported.');
29
+ }
30
+
31
+ let extensions = this.buildExtensions(options.extensions);
32
+
33
+ if (options.detail) {
34
+ const detailExt = new AgentDetailExtensionSpec(options.detail);
35
+
36
+ extensions = [...(extensions ?? []), detailExt.toAgentCardExtension()];
37
+ }
38
+
39
+ this.agentCard = {
40
+ name: options.name,
41
+ description: options.description ?? '',
42
+ url: 'http://localhost:8000',
43
+ version: options.version ?? '1.0.0',
44
+ protocolVersion: options.protocolVersion ?? '0.3.0',
45
+ capabilities: {
46
+ streaming: true,
47
+ extensions,
48
+ },
49
+ defaultInputModes: ['text'],
50
+ defaultOutputModes: ['text'],
51
+ skills: [],
52
+ };
53
+
54
+ this.agentOptions = options as AgentOptions<unknown>;
55
+ this.agentConfigured = true;
56
+
57
+ return this;
58
+ }
59
+
60
+ async run(options: ServerOptions = {}): Promise<ServerHandle> {
61
+ if (!this.agentConfigured || !this.agentCard || !this.agentOptions) {
62
+ throw new Error('No agent configured. Call agent() before run().');
63
+ }
64
+
65
+ const config = loadConfig();
66
+ const host = options.host ?? '0.0.0.0';
67
+ const port = options.port ?? 8000;
68
+ const selfRegistrationId = options.selfRegistrationId;
69
+ const platformUrl = options.platformUrl ?? config.platformUrl;
70
+ const productionMode = config.productionMode;
71
+
72
+ this.agentCard.url = createAgentCardUrl(host, port);
73
+
74
+ if (selfRegistrationId && !productionMode) {
75
+ const selfRegExtension = new PlatformSelfRegistrationExtensionSpec({ self_registration_id: selfRegistrationId });
76
+
77
+ this.agentCard.capabilities.extensions = [
78
+ ...(this.agentCard.capabilities.extensions ?? []),
79
+ selfRegExtension.toAgentCardExtension(),
80
+ ];
81
+ }
82
+
83
+ const taskStore = new InMemoryTaskStore();
84
+ const executor = new AgentExecutorImpl(this.agentOptions.handler, this.agentOptions.extensions);
85
+ const requestHandler = new DefaultRequestHandler(this.agentCard, taskStore, executor);
86
+
87
+ const app = express();
88
+
89
+ const agentCardPath = `/.well-known/agent-card.json`;
90
+
91
+ app.use(jsonRpcHandler({ requestHandler, userBuilder: UserBuilder.noAuthentication }));
92
+ app.use(agentCardPath, agentCardHandler({ agentCardProvider: requestHandler }));
93
+
94
+ const api = buildApiClient({ baseUrl: platformUrl });
95
+
96
+ let stopAutoregistration: (() => void) | undefined;
97
+
98
+ if (selfRegistrationId && !productionMode) {
99
+ stopAutoregistration = createAutoregisterToAgentstack({
100
+ selfRegistrationId,
101
+ agentCard: this.agentCard,
102
+ host,
103
+ port,
104
+ api,
105
+ });
106
+ }
107
+
108
+ return new Promise((resolve, reject) => {
109
+ const server = app.listen(port, host, async () => {
110
+ console.log(`Agent "${this.agentCard!.name}" running at http://${host}:${port}`);
111
+ console.log(`Agent card available at http://${host}:${port}${agentCardPath}`);
112
+
113
+ const url = createAgentCardUrl(host, port);
114
+ const handle: ServerHandle = {
115
+ port,
116
+ url,
117
+ close: () =>
118
+ new Promise((resolveClose, rejectClose) => {
119
+ stopAutoregistration?.();
120
+
121
+ server.close((error) => {
122
+ if (error) {
123
+ rejectClose(error);
124
+ } else {
125
+ resolveClose();
126
+ }
127
+ });
128
+ }),
129
+ };
130
+
131
+ resolve(handle);
132
+ });
133
+
134
+ server.on('error', (error) => {
135
+ stopAutoregistration?.();
136
+ reject(error);
137
+ });
138
+
139
+ const cleanup = () => {
140
+ stopAutoregistration?.();
141
+ server.close();
142
+ };
143
+
144
+ process.on('SIGTERM', cleanup);
145
+ process.on('SIGINT', cleanup);
146
+ });
147
+ }
148
+
149
+ private buildExtensions(extensionConfig: ExtensionConfig | undefined): AgentExtension[] | undefined {
150
+ if (!extensionConfig) {
151
+ return undefined;
152
+ }
153
+
154
+ const extensions: AgentExtension[] = [];
155
+
156
+ for (const ext of Object.values(extensionConfig) as ExtensionServer[]) {
157
+ extensions.push(ext.spec.toAgentCardExtension());
158
+ }
159
+
160
+ if (extensions.length === 0) {
161
+ return undefined;
162
+ }
163
+
164
+ return extensions;
165
+ }
166
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Copyright 2025 © BeeAI a Series of LF Projects, LLC
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ import type { AgentCard, Artifact, Message, Part, TaskStatus, TaskStatusUpdateEvent } from '@a2a-js/sdk';
7
+
8
+ import type { buildApiClient } from '../../../../api';
9
+ import type { AgentDetail } from '../../../../client/a2a/extensions/ui/agent-detail/types';
10
+ import type { RunContext } from '../context';
11
+ import type { ExtensionConfig } from '../extensions/types';
12
+
13
+ export type RunYield =
14
+ | string
15
+ | Message
16
+ | Part
17
+ | TaskStatus
18
+ | TaskStatusUpdateEvent
19
+ | Artifact
20
+ | Error
21
+ | Record<string, unknown>;
22
+
23
+ export type AgentFunction<TDeps = Record<string, never>> = (
24
+ input: Message,
25
+ ctx: RunContext,
26
+ deps: TDeps,
27
+ ) => AsyncIterable<RunYield> | Promise<RunYield | void>;
28
+
29
+ export interface AgentOptions<TDeps = Record<string, never>> {
30
+ name: string;
31
+ description?: string;
32
+ detail?: AgentDetail;
33
+ extensions?: ExtensionConfig<TDeps>;
34
+ version?: string;
35
+ protocolVersion?: string;
36
+ handler: AgentFunction<TDeps>;
37
+ }
38
+
39
+ export interface ServerOptions {
40
+ host?: string;
41
+ port?: number;
42
+ selfRegistrationId?: string;
43
+ platformUrl?: string;
44
+ }
45
+
46
+ export interface ServerHandle {
47
+ port: number;
48
+ url: string;
49
+ close: () => Promise<void>;
50
+ }
51
+
52
+ export interface AutoregistrationOptions {
53
+ selfRegistrationId: string;
54
+ agentCard: AgentCard;
55
+ host: string;
56
+ port: number;
57
+ api: ReturnType<typeof buildApiClient>;
58
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Copyright 2025 © BeeAI a Series of LF Projects, LLC
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ export * from './config/types';
7
+ export * from './extensions/types';
8
+ export * from './server/types';
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Copyright 2025 © BeeAI a Series of LF Projects, LLC
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ function sleep(ms: number): Promise<void> {
7
+ return new Promise((resolve) => setTimeout(resolve, ms));
8
+ }
9
+
10
+ interface RetryOptions {
11
+ maxAttempts?: number;
12
+ maxDelayMs?: number;
13
+ shouldAbort?: () => boolean;
14
+ onRetry?: (attempt: number, error: Error, delayMs: number) => void;
15
+ }
16
+
17
+ export async function withRetry<T>(fn: () => Promise<T>, options: RetryOptions = {}): Promise<T> {
18
+ const { maxAttempts = 10, maxDelayMs = 10000, shouldAbort, onRetry } = options;
19
+
20
+ let lastError: Error | undefined;
21
+
22
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
23
+ if (shouldAbort?.()) {
24
+ throw new Error('Operation aborted');
25
+ }
26
+
27
+ try {
28
+ return await fn();
29
+ } catch (error) {
30
+ lastError = error instanceof Error ? error : new Error(String(error));
31
+
32
+ const delay = Math.min(1000 * Math.pow(2, attempt), maxDelayMs);
33
+
34
+ onRetry?.(attempt + 1, lastError, delay);
35
+
36
+ await sleep(delay);
37
+ }
38
+ }
39
+
40
+ throw lastError ?? new Error('Max retry attempts exceeded');
41
+ }
42
+
43
+ export function setsEqual(a: Set<string>, b: Set<string>): boolean {
44
+ if (a.size !== b.size) {
45
+ return false;
46
+ }
47
+
48
+ for (const item of a) {
49
+ if (!b.has(item)) {
50
+ return false;
51
+ }
52
+ }
53
+
54
+ return true;
55
+ }
56
+
57
+ export function getErrorMessage(error: unknown) {
58
+ return error instanceof Error ? error.message : String(error);
59
+ }
@@ -2,5 +2,6 @@
2
2
  * Copyright 2025 © BeeAI a Series of LF Projects, LLC
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
- export * from './types';
6
- export * from './utils';
5
+
6
+ export * from './experimental/server/a2a';
7
+ export * from './experimental/server/core';