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.
- package/README.md +36 -29
- package/dist/api.cjs +1994 -2
- package/dist/api.d.cts +29 -0
- package/dist/api.d.ts +25 -1
- package/dist/api.js +1801 -2
- package/dist/core-DcGxYeok.d.ts +1238 -0
- package/dist/core-XN6gWSAb.d.cts +1238 -0
- package/dist/core.cjs +1773 -2
- package/dist/core.d.cts +7 -0
- package/dist/core.d.ts +7 -5
- package/dist/core.js +1725 -2
- package/dist/extensions.cjs +798 -2
- package/dist/extensions.d.cts +244 -0
- package/dist/extensions.d.ts +240 -1
- package/dist/extensions.js +652 -2
- package/dist/index.cjs +3142 -2
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -7
- package/dist/index.js +2781 -2
- package/dist/index.umd.js +16509 -2
- package/dist/schemas-Dy3P_eAt.d.cts +57 -0
- package/dist/schemas-Dy3P_eAt.d.ts +57 -0
- package/dist/server.cjs +2762 -0
- package/dist/server.d.cts +244 -0
- package/dist/server.d.ts +244 -0
- package/dist/server.js +2716 -0
- package/dist/types-B5B3b0V2.d.cts +396 -0
- package/dist/types-B5B3b0V2.d.ts +396 -0
- package/dist/types-CmEs5_Ag.d.cts +3522 -0
- package/dist/types-DJm5-rZZ.d.ts +3522 -0
- package/dist/types-DvLt-XuC.d.ts +866 -0
- package/dist/types-E26YDM19.d.cts +866 -0
- package/dist/types-MfIzGgpV.d.cts +43 -0
- package/dist/types-MfIzGgpV.d.ts +43 -0
- package/package.json +36 -21
- package/src/client/a2a/extensions/auth/oauth/index.ts +6 -6
- package/src/client/a2a/extensions/auth/secrets/index.ts +6 -6
- package/src/client/a2a/extensions/interactions/approval/index.ts +7 -7
- package/src/client/a2a/extensions/services/embedding/index.ts +7 -3
- package/src/client/a2a/extensions/services/form/index.ts +3 -3
- package/src/client/a2a/extensions/services/llm/index.ts +3 -3
- package/src/client/a2a/extensions/services/mcp/index.ts +3 -3
- package/src/client/a2a/extensions/services/platform-api/index.ts +2 -2
- package/src/client/a2a/extensions/ui/agent-detail/index.ts +4 -4
- package/src/client/a2a/extensions/ui/canvas/index.ts +4 -4
- package/src/client/a2a/extensions/ui/citation/index.ts +4 -4
- package/src/client/a2a/extensions/ui/error/index.ts +4 -4
- package/src/client/a2a/extensions/ui/form-request/index.ts +4 -4
- package/src/client/a2a/extensions/ui/settings/index.ts +7 -3
- package/src/client/a2a/extensions/ui/trajectory/index.ts +4 -4
- package/src/client/core/extensions/types.ts +8 -1
- package/src/client/core/handle-task-status-update.ts +10 -3
- package/src/client/core/index.ts +1 -0
- package/src/client/core/utils/extract-text-from-message.ts +15 -0
- package/src/examples/hello-world.ts +34 -0
- package/src/experimental/server/a2a/extensions/agent-detail/index.ts +35 -0
- package/src/experimental/server/a2a/extensions/agent-detail/types.ts +10 -0
- package/src/experimental/server/a2a/extensions/index.ts +11 -0
- package/src/experimental/server/a2a/extensions/llm/index.ts +70 -0
- package/src/experimental/server/a2a/extensions/llm/types.ts +16 -0
- package/src/experimental/server/a2a/extensions/platform-self-registration/index.ts +34 -0
- package/src/experimental/server/a2a/extensions/platform-self-registration/types.ts +10 -0
- package/src/experimental/server/a2a/helpers.ts +95 -0
- package/{dist/client/a2a/index.d.ts → src/experimental/server/a2a/index.ts} +1 -1
- package/src/experimental/server/a2a/utils.ts +43 -0
- package/src/experimental/server/core/config/index.ts +17 -0
- package/src/experimental/server/core/config/schemas.ts +15 -0
- package/src/experimental/server/core/config/types.ts +10 -0
- package/src/experimental/server/core/context/index.ts +18 -0
- package/src/experimental/server/core/extensions/types.ts +24 -0
- package/{dist/client/a2a/protocol/index.d.ts → src/experimental/server/core/index.ts} +4 -0
- package/{dist/client/a2a/protocol/tests.d.ts → src/experimental/server/core/schemas.ts} +2 -1
- package/src/experimental/server/core/server/autoregistration.ts +142 -0
- package/src/experimental/server/core/server/executor.ts +284 -0
- package/src/experimental/server/core/server/helpers.ts +12 -0
- package/src/experimental/server/core/server/index.ts +166 -0
- package/src/experimental/server/core/server/types.ts +58 -0
- package/src/experimental/server/core/types.ts +8 -0
- package/src/experimental/server/core/utils.ts +59 -0
- package/{dist/client/api/core/errors/index.d.ts → src/server.ts} +3 -2
- package/dist/api.cjs.map +0 -1
- package/dist/api.js.map +0 -1
- package/dist/api.umd.js +0 -2
- package/dist/api.umd.js.map +0 -1
- package/dist/client/a2a/extensions/auth/oauth/index.d.ts +0 -10
- package/dist/client/a2a/extensions/auth/oauth/schemas.d.ts +0 -32
- package/dist/client/a2a/extensions/auth/oauth/types.d.ts +0 -13
- package/dist/client/a2a/extensions/auth/secrets/index.d.ts +0 -10
- package/dist/client/a2a/extensions/auth/secrets/schemas.d.ts +0 -23
- package/dist/client/a2a/extensions/auth/secrets/types.d.ts +0 -10
- package/dist/client/a2a/extensions/common/form/schemas.d.ts +0 -290
- package/dist/client/a2a/extensions/common/form/types.d.ts +0 -24
- package/dist/client/a2a/extensions/index.d.ts +0 -21
- package/dist/client/a2a/extensions/interactions/approval/index.d.ts +0 -10
- package/dist/client/a2a/extensions/interactions/approval/schemas.d.ts +0 -43
- package/dist/client/a2a/extensions/interactions/approval/types.d.ts +0 -14
- package/dist/client/a2a/extensions/schemas.d.ts +0 -19
- package/dist/client/a2a/extensions/services/embedding/index.d.ts +0 -9
- package/dist/client/a2a/extensions/services/embedding/schemas.d.ts +0 -29
- package/dist/client/a2a/extensions/services/embedding/types.d.ts +0 -10
- package/dist/client/a2a/extensions/services/form/index.d.ts +0 -9
- package/dist/client/a2a/extensions/services/form/schemas.d.ts +0 -97
- package/dist/client/a2a/extensions/services/form/types.d.ts +0 -8
- package/dist/client/a2a/extensions/services/llm/index.d.ts +0 -9
- package/dist/client/a2a/extensions/services/llm/schemas.d.ts +0 -29
- package/dist/client/a2a/extensions/services/llm/types.d.ts +0 -10
- package/dist/client/a2a/extensions/services/mcp/index.d.ts +0 -9
- package/dist/client/a2a/extensions/services/mcp/schemas.d.ts +0 -35
- package/dist/client/a2a/extensions/services/mcp/types.d.ts +0 -14
- package/dist/client/a2a/extensions/services/platform-api/index.d.ts +0 -11
- package/dist/client/a2a/extensions/services/platform-api/schemas.d.ts +0 -10
- package/dist/client/a2a/extensions/services/platform-api/types.d.ts +0 -7
- package/dist/client/a2a/extensions/types.d.ts +0 -19
- package/dist/client/a2a/extensions/ui/agent-detail/index.d.ts +0 -9
- package/dist/client/a2a/extensions/ui/agent-detail/schemas.d.ts +0 -41
- package/dist/client/a2a/extensions/ui/agent-detail/types.d.ts +0 -13
- package/dist/client/a2a/extensions/ui/canvas/index.d.ts +0 -9
- package/dist/client/a2a/extensions/ui/canvas/schemas.d.ts +0 -11
- package/dist/client/a2a/extensions/ui/canvas/types.d.ts +0 -7
- package/dist/client/a2a/extensions/ui/citation/index.d.ts +0 -9
- package/dist/client/a2a/extensions/ui/citation/schemas.d.ts +0 -21
- package/dist/client/a2a/extensions/ui/citation/types.d.ts +0 -8
- package/dist/client/a2a/extensions/ui/error/index.d.ts +0 -9
- package/dist/client/a2a/extensions/ui/error/schemas.d.ts +0 -30
- package/dist/client/a2a/extensions/ui/error/types.d.ts +0 -9
- package/dist/client/a2a/extensions/ui/form-request/index.d.ts +0 -9
- package/dist/client/a2a/extensions/ui/settings/index.d.ts +0 -9
- package/dist/client/a2a/extensions/ui/settings/schemas.d.ts +0 -113
- package/dist/client/a2a/extensions/ui/settings/types.d.ts +0 -18
- package/dist/client/a2a/extensions/ui/trajectory/index.d.ts +0 -9
- package/dist/client/a2a/extensions/ui/trajectory/schemas.d.ts +0 -10
- package/dist/client/a2a/extensions/ui/trajectory/types.d.ts +0 -7
- package/dist/client/a2a/protocol/schemas.d.ts +0 -988
- package/dist/client/a2a/protocol/types.d.ts +0 -52
- package/dist/client/a2a/protocol/utils.d.ts +0 -6
- package/dist/client/api/common/schemas.d.ts +0 -30
- package/dist/client/api/common/types.d.ts +0 -18
- package/dist/client/api/configuration/api.d.ts +0 -22
- package/dist/client/api/configuration/schemas.d.ts +0 -31
- package/dist/client/api/configuration/types.d.ts +0 -11
- package/dist/client/api/connectors/api.d.ts +0 -78
- package/dist/client/api/connectors/schemas.d.ts +0 -114
- package/dist/client/api/connectors/types.d.ts +0 -28
- package/dist/client/api/contexts/api.d.ts +0 -133
- package/dist/client/api/contexts/schemas.d.ts +0 -359
- package/dist/client/api/contexts/types.d.ts +0 -34
- package/dist/client/api/core/client.d.ts +0 -1273
- package/dist/client/api/core/errors/types.d.ts +0 -36
- package/dist/client/api/core/errors/utils.d.ts +0 -23
- package/dist/client/api/core/index.d.ts +0 -7
- package/dist/client/api/core/schemas.d.ts +0 -17
- package/dist/client/api/core/types.d.ts +0 -45
- package/dist/client/api/core/utils.d.ts +0 -23
- package/dist/client/api/files/api.d.ts +0 -32
- package/dist/client/api/files/schemas.d.ts +0 -61
- package/dist/client/api/files/types.d.ts +0 -19
- package/dist/client/api/index.d.ts +0 -7
- package/dist/client/api/model-providers/api.d.ts +0 -50
- package/dist/client/api/model-providers/schemas.d.ts +0 -80
- package/dist/client/api/model-providers/types.d.ts +0 -44
- package/dist/client/api/provider-builds/api.d.ts +0 -143
- package/dist/client/api/provider-builds/schemas.d.ts +0 -250
- package/dist/client/api/provider-builds/types.d.ts +0 -31
- package/dist/client/api/providers/api.d.ts +0 -847
- package/dist/client/api/providers/schemas.d.ts +0 -1335
- package/dist/client/api/providers/types.d.ts +0 -45
- package/dist/client/api/schemas.d.ts +0 -15
- package/dist/client/api/types.d.ts +0 -15
- package/dist/client/api/user-feedback/api.d.ts +0 -9
- package/dist/client/api/user-feedback/schemas.d.ts +0 -15
- package/dist/client/api/user-feedback/types.d.ts +0 -8
- package/dist/client/api/users/api.d.ts +0 -13
- package/dist/client/api/users/schemas.d.ts +0 -20
- package/dist/client/api/users/types.d.ts +0 -14
- package/dist/client/api/variables/api.d.ts +0 -12
- package/dist/client/api/variables/schemas.d.ts +0 -13
- package/dist/client/api/variables/types.d.ts +0 -10
- package/dist/client/core/create-authenticated-fetch.d.ts +0 -5
- package/dist/client/core/extensions/extract.d.ts +0 -8
- package/dist/client/core/extensions/fulfill.d.ts +0 -8
- package/dist/client/core/extensions/resolve-user-metadata.d.ts +0 -6
- package/dist/client/core/extensions/types.d.ts +0 -68
- package/dist/client/core/fulfillment-resolvers/build-llm-extension-fulfillment-resolver.d.ts +0 -8
- package/dist/client/core/handle-agent-card.d.ts +0 -128
- package/dist/client/core/handle-task-status-update.d.ts +0 -7
- package/dist/client/core/index.d.ts +0 -14
- package/dist/client/core/utils/build-message-builder.d.ts +0 -9
- package/dist/client/core/utils/get-agent-card-path.d.ts +0 -5
- package/dist/core.cjs.map +0 -1
- package/dist/core.js.map +0 -1
- package/dist/core.umd.js +0 -2
- package/dist/core.umd.js.map +0 -1
- package/dist/extensions.cjs.map +0 -1
- package/dist/extensions.js.map +0 -1
- package/dist/extensions.umd.js +0 -2
- package/dist/extensions.umd.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- 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,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
|
+
}
|