@a2a-js/sdk 0.2.2 → 0.2.4
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 +106 -89
- package/dist/client/index.cjs +396 -0
- package/dist/client/index.d.cts +120 -0
- package/{build/src/client/client.d.ts → dist/client/index.d.ts} +5 -3
- package/dist/client/index.js +370 -0
- package/dist/index.cjs +17 -0
- package/dist/index.d.cts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +0 -0
- package/dist/server/index.cjs +885 -0
- package/dist/server/index.d.cts +207 -0
- package/dist/server/index.d.ts +207 -0
- package/dist/server/index.js +841 -0
- package/{build/src/types.d.ts → dist/types-CcBgkR2G.d.cts} +105 -103
- package/dist/types-CcBgkR2G.d.ts +2048 -0
- package/package.json +25 -7
- package/build/src/a2a_response.d.ts +0 -5
- package/build/src/a2a_response.js +0 -2
- package/build/src/client/client.js +0 -409
- package/build/src/index.d.ts +0 -21
- package/build/src/index.js +0 -18
- package/build/src/samples/agents/movie-agent/genkit.d.ts +0 -2
- package/build/src/samples/agents/movie-agent/genkit.js +0 -11
- package/build/src/samples/agents/movie-agent/index.d.ts +0 -1
- package/build/src/samples/agents/movie-agent/index.js +0 -252
- package/build/src/samples/agents/movie-agent/tmdb.d.ts +0 -7
- package/build/src/samples/agents/movie-agent/tmdb.js +0 -32
- package/build/src/samples/agents/movie-agent/tools.d.ts +0 -15
- package/build/src/samples/agents/movie-agent/tools.js +0 -74
- package/build/src/samples/cli.d.ts +0 -2
- package/build/src/samples/cli.js +0 -289
- package/build/src/server/a2a_express_app.d.ts +0 -14
- package/build/src/server/a2a_express_app.js +0 -98
- package/build/src/server/agent_execution/agent_executor.d.ts +0 -18
- package/build/src/server/agent_execution/agent_executor.js +0 -2
- package/build/src/server/agent_execution/request_context.d.ts +0 -9
- package/build/src/server/agent_execution/request_context.js +0 -15
- package/build/src/server/error.d.ts +0 -23
- package/build/src/server/error.js +0 -57
- package/build/src/server/events/execution_event_bus.d.ts +0 -16
- package/build/src/server/events/execution_event_bus.js +0 -13
- package/build/src/server/events/execution_event_bus_manager.d.ts +0 -27
- package/build/src/server/events/execution_event_bus_manager.js +0 -36
- package/build/src/server/events/execution_event_queue.d.ts +0 -24
- package/build/src/server/events/execution_event_queue.js +0 -63
- package/build/src/server/request_handler/a2a_request_handler.d.ts +0 -11
- package/build/src/server/request_handler/a2a_request_handler.js +0 -2
- package/build/src/server/request_handler/default_request_handler.d.ts +0 -23
- package/build/src/server/request_handler/default_request_handler.js +0 -340
- package/build/src/server/result_manager.d.ts +0 -29
- package/build/src/server/result_manager.js +0 -149
- package/build/src/server/store.d.ts +0 -25
- package/build/src/server/store.js +0 -17
- package/build/src/server/transports/jsonrpc_transport_handler.d.ts +0 -15
- package/build/src/server/transports/jsonrpc_transport_handler.js +0 -114
- package/build/src/server/utils.d.ts +0 -22
- package/build/src/server/utils.js +0 -34
- package/build/src/types-old.d.ts +0 -832
- package/build/src/types-old.js +0 -20
- package/build/src/types.js +0 -8
package/README.md
CHANGED
|
@@ -28,19 +28,21 @@ You can also find JavaScript samples [here](https://github.com/google-a2a/a2a-sa
|
|
|
28
28
|
This directory contains a TypeScript server implementation for the Agent-to-Agent (A2A) communication protocol, built using Express.js.
|
|
29
29
|
|
|
30
30
|
### 1. Define Agent Card
|
|
31
|
+
|
|
31
32
|
```typescript
|
|
32
|
-
import { AgentCard } from "@a2a-js/sdk";
|
|
33
|
+
import type { AgentCard } from "@a2a-js/sdk";
|
|
33
34
|
|
|
34
35
|
const movieAgentCard: AgentCard = {
|
|
35
|
-
name:
|
|
36
|
-
description:
|
|
36
|
+
name: "Movie Agent",
|
|
37
|
+
description:
|
|
38
|
+
"An agent that can answer questions about movies and actors using TMDB.",
|
|
37
39
|
// Adjust the base URL and port as needed.
|
|
38
|
-
url:
|
|
40
|
+
url: "http://localhost:41241/",
|
|
39
41
|
provider: {
|
|
40
|
-
organization:
|
|
41
|
-
url:
|
|
42
|
+
organization: "A2A Agents",
|
|
43
|
+
url: "https://example.com/a2a-agents", // Added provider URL
|
|
42
44
|
},
|
|
43
|
-
version:
|
|
45
|
+
version: "0.0.2", // Incremented version
|
|
44
46
|
capabilities: {
|
|
45
47
|
streaming: true, // Supports streaming
|
|
46
48
|
pushNotifications: false, // Assuming not implemented for this agent yet
|
|
@@ -48,24 +50,25 @@ const movieAgentCard: AgentCard = {
|
|
|
48
50
|
},
|
|
49
51
|
securitySchemes: undefined, // Or define actual security schemes if any
|
|
50
52
|
security: undefined,
|
|
51
|
-
defaultInputModes: [
|
|
52
|
-
defaultOutputModes: [
|
|
53
|
+
defaultInputModes: ["text/plain"],
|
|
54
|
+
defaultOutputModes: ["text/plain"],
|
|
53
55
|
skills: [
|
|
54
56
|
{
|
|
55
|
-
id:
|
|
56
|
-
name:
|
|
57
|
-
description:
|
|
58
|
-
|
|
57
|
+
id: "general_movie_chat",
|
|
58
|
+
name: "General Movie Chat",
|
|
59
|
+
description:
|
|
60
|
+
"Answer general questions or chat about movies, actors, directors.",
|
|
61
|
+
tags: ["movies", "actors", "directors"],
|
|
59
62
|
examples: [
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
"Tell me about the plot of Inception.",
|
|
64
|
+
"Recommend a good sci-fi movie.",
|
|
65
|
+
"Who directed The Matrix?",
|
|
66
|
+
"What other movies has Scarlett Johansson been in?",
|
|
67
|
+
"Find action movies starring Keanu Reeves",
|
|
68
|
+
"Which came out first, Jurassic Park or Terminator 2?",
|
|
66
69
|
],
|
|
67
|
-
inputModes: [
|
|
68
|
-
outputModes: [
|
|
70
|
+
inputModes: ["text/plain"], // Explicitly defining for skill
|
|
71
|
+
outputModes: ["text/plain"], // Explicitly defining for skill
|
|
69
72
|
},
|
|
70
73
|
],
|
|
71
74
|
supportsAuthenticatedExtendedCard: false,
|
|
@@ -73,6 +76,7 @@ const movieAgentCard: AgentCard = {
|
|
|
73
76
|
```
|
|
74
77
|
|
|
75
78
|
### 2. Define Agent Executor
|
|
79
|
+
|
|
76
80
|
```typescript
|
|
77
81
|
import {
|
|
78
82
|
InMemoryTaskStore,
|
|
@@ -82,19 +86,19 @@ import {
|
|
|
82
86
|
RequestContext,
|
|
83
87
|
ExecutionEventBus,
|
|
84
88
|
DefaultRequestHandler,
|
|
85
|
-
} from "@a2a-js/sdk";
|
|
89
|
+
} from "@a2a-js/sdk/server";
|
|
86
90
|
|
|
87
91
|
// 1. Define your agent's logic as a AgentExecutor
|
|
88
92
|
class MyAgentExecutor implements AgentExecutor {
|
|
89
93
|
private cancelledTasks = new Set<string>();
|
|
90
94
|
|
|
91
95
|
public cancelTask = async (
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
taskId: string,
|
|
97
|
+
eventBus: ExecutionEventBus
|
|
98
|
+
): Promise<void> => {
|
|
99
|
+
this.cancelledTasks.add(taskId);
|
|
100
|
+
// The execute loop is responsible for publishing the final state
|
|
101
|
+
};
|
|
98
102
|
|
|
99
103
|
async execute(
|
|
100
104
|
requestContext: RequestContext,
|
|
@@ -114,11 +118,11 @@ class MyAgentExecutor implements AgentExecutor {
|
|
|
114
118
|
// 1. Publish initial Task event if it's a new task
|
|
115
119
|
if (!existingTask) {
|
|
116
120
|
const initialTask: Task = {
|
|
117
|
-
kind:
|
|
121
|
+
kind: "task",
|
|
118
122
|
id: taskId,
|
|
119
123
|
contextId: contextId,
|
|
120
124
|
status: {
|
|
121
|
-
state:
|
|
125
|
+
state: "submitted",
|
|
122
126
|
timestamp: new Date().toISOString(),
|
|
123
127
|
},
|
|
124
128
|
history: [userMessage],
|
|
@@ -130,16 +134,16 @@ class MyAgentExecutor implements AgentExecutor {
|
|
|
130
134
|
|
|
131
135
|
// 2. Publish "working" status update
|
|
132
136
|
const workingStatusUpdate: TaskStatusUpdateEvent = {
|
|
133
|
-
kind:
|
|
137
|
+
kind: "status-update",
|
|
134
138
|
taskId: taskId,
|
|
135
139
|
contextId: contextId,
|
|
136
140
|
status: {
|
|
137
|
-
state:
|
|
141
|
+
state: "working",
|
|
138
142
|
message: {
|
|
139
|
-
kind:
|
|
140
|
-
role:
|
|
143
|
+
kind: "message",
|
|
144
|
+
role: "agent",
|
|
141
145
|
messageId: uuidv4(),
|
|
142
|
-
parts: [{ kind:
|
|
146
|
+
parts: [{ kind: "text", text: "Generating code..." }],
|
|
143
147
|
taskId: taskId,
|
|
144
148
|
contextId: contextId,
|
|
145
149
|
},
|
|
@@ -156,11 +160,11 @@ class MyAgentExecutor implements AgentExecutor {
|
|
|
156
160
|
if (this.cancelledTasks.has(taskId)) {
|
|
157
161
|
console.log(`[MyAgentExecutor] Request cancelled for task: ${taskId}`);
|
|
158
162
|
const cancelledUpdate: TaskStatusUpdateEvent = {
|
|
159
|
-
kind:
|
|
163
|
+
kind: "status-update",
|
|
160
164
|
taskId: taskId,
|
|
161
165
|
contextId: contextId,
|
|
162
166
|
status: {
|
|
163
|
-
state:
|
|
167
|
+
state: "canceled",
|
|
164
168
|
timestamp: new Date().toISOString(),
|
|
165
169
|
},
|
|
166
170
|
final: true,
|
|
@@ -172,7 +176,7 @@ class MyAgentExecutor implements AgentExecutor {
|
|
|
172
176
|
|
|
173
177
|
// 3. Publish artifact update
|
|
174
178
|
const artifactUpdate: TaskArtifactUpdateEvent = {
|
|
175
|
-
kind:
|
|
179
|
+
kind: "artifact-update",
|
|
176
180
|
taskId: taskId,
|
|
177
181
|
contextId: contextId,
|
|
178
182
|
artifact: {
|
|
@@ -187,14 +191,14 @@ class MyAgentExecutor implements AgentExecutor {
|
|
|
187
191
|
|
|
188
192
|
// 4. Publish final status update
|
|
189
193
|
const finalUpdate: TaskStatusUpdateEvent = {
|
|
190
|
-
kind:
|
|
194
|
+
kind: "status-update",
|
|
191
195
|
taskId: taskId,
|
|
192
196
|
contextId: contextId,
|
|
193
197
|
status: {
|
|
194
|
-
state:
|
|
198
|
+
state: "completed",
|
|
195
199
|
message: {
|
|
196
|
-
kind:
|
|
197
|
-
role:
|
|
200
|
+
kind: "message",
|
|
201
|
+
role: "agent",
|
|
198
202
|
messageId: uuidv4(),
|
|
199
203
|
taskId: taskId,
|
|
200
204
|
contextId: contextId,
|
|
@@ -210,6 +214,7 @@ class MyAgentExecutor implements AgentExecutor {
|
|
|
210
214
|
```
|
|
211
215
|
|
|
212
216
|
### 3. Start the server
|
|
217
|
+
|
|
213
218
|
```typescript
|
|
214
219
|
const taskStore: TaskStore = new InMemoryTaskStore();
|
|
215
220
|
const agentExecutor: AgentExecutor = new MyAgentExecutor();
|
|
@@ -221,19 +226,26 @@ const requestHandler = new DefaultRequestHandler(
|
|
|
221
226
|
);
|
|
222
227
|
|
|
223
228
|
const appBuilder = new A2AExpressApp(requestHandler);
|
|
224
|
-
const expressApp = appBuilder.setupRoutes(express(),
|
|
229
|
+
const expressApp = appBuilder.setupRoutes(express(), "");
|
|
225
230
|
|
|
226
231
|
const PORT = process.env.CODER_AGENT_PORT || 41242; // Different port for coder agent
|
|
227
232
|
expressApp.listen(PORT, () => {
|
|
228
|
-
console.log(
|
|
229
|
-
|
|
230
|
-
|
|
233
|
+
console.log(
|
|
234
|
+
`[MyAgent] Server using new framework started on http://localhost:${PORT}`
|
|
235
|
+
);
|
|
236
|
+
console.log(
|
|
237
|
+
`[MyAgent] Agent Card: http://localhost:${PORT}/.well-known/agent.json`
|
|
238
|
+
);
|
|
239
|
+
console.log("[MyAgent] Press Ctrl+C to stop the server");
|
|
231
240
|
});
|
|
232
241
|
```
|
|
242
|
+
|
|
233
243
|
### Agent Executor
|
|
244
|
+
|
|
234
245
|
Developers are expected to implement this interface and provide two methods: `execute` and `cancelTask`.
|
|
235
246
|
|
|
236
247
|
#### `execute`
|
|
248
|
+
|
|
237
249
|
- This method is provided with a `RequestContext` and an `EventBus` to publish execution events.
|
|
238
250
|
- Executor can either respond by publishing a Message or Task.
|
|
239
251
|
- For a task, check if there's an existing task in `RequestContext`. If not, publish an initial Task event using `taskId` & `contextId` from `RequestContext`.
|
|
@@ -242,9 +254,10 @@ Developers are expected to implement this interface and provide two methods: `ex
|
|
|
242
254
|
- Executor should also check if an ongoing task has been cancelled. If yes, cancel the execution and emit an `TaskStatusUpdateEvent` with cancelled state.
|
|
243
255
|
|
|
244
256
|
#### `cancelTask`
|
|
257
|
+
|
|
245
258
|
Executors should implement cancellation mechanism for an ongoing task.
|
|
246
259
|
|
|
247
|
-
## A2A Client
|
|
260
|
+
## A2A Client
|
|
248
261
|
|
|
249
262
|
There's a `A2AClient` class, which provides methods for interacting with an A2A server over HTTP using JSON-RPC.
|
|
250
263
|
|
|
@@ -259,8 +272,8 @@ There's a `A2AClient` class, which provides methods for interacting with an A2A
|
|
|
259
272
|
### Basic Usage
|
|
260
273
|
|
|
261
274
|
```typescript
|
|
262
|
-
import {
|
|
263
|
-
|
|
275
|
+
import { A2AClient } from "@a2a-js/sdk/client";
|
|
276
|
+
import type {
|
|
264
277
|
Message,
|
|
265
278
|
MessageSendParams,
|
|
266
279
|
Task,
|
|
@@ -268,7 +281,7 @@ import {
|
|
|
268
281
|
SendMessageResponse,
|
|
269
282
|
GetTaskResponse,
|
|
270
283
|
SendMessageSuccessResponse,
|
|
271
|
-
GetTaskSuccessResponse
|
|
284
|
+
GetTaskSuccessResponse,
|
|
272
285
|
} from "@a2a-js/sdk";
|
|
273
286
|
import { v4 as uuidv4 } from "uuid";
|
|
274
287
|
|
|
@@ -285,50 +298,50 @@ async function run() {
|
|
|
285
298
|
messageId: messageId,
|
|
286
299
|
role: "user",
|
|
287
300
|
parts: [{ kind: "text", text: "Hello, agent!" }],
|
|
288
|
-
kind: "message"
|
|
301
|
+
kind: "message",
|
|
289
302
|
},
|
|
290
303
|
configuration: {
|
|
291
304
|
blocking: true,
|
|
292
|
-
acceptedOutputModes: [
|
|
293
|
-
}
|
|
305
|
+
acceptedOutputModes: ["text/plain"],
|
|
306
|
+
},
|
|
294
307
|
};
|
|
295
|
-
|
|
296
|
-
const sendResponse: SendMessageResponse =
|
|
308
|
+
|
|
309
|
+
const sendResponse: SendMessageResponse =
|
|
310
|
+
await client.sendMessage(sendParams);
|
|
297
311
|
|
|
298
312
|
if (sendResponse.error) {
|
|
299
|
-
|
|
300
|
-
|
|
313
|
+
console.error("Error sending message:", sendResponse.error);
|
|
314
|
+
return;
|
|
301
315
|
}
|
|
302
316
|
|
|
303
317
|
// On success, the result can be a Task or a Message. Check which one it is.
|
|
304
318
|
const result = (sendResponse as SendMessageSuccessResponse).result;
|
|
305
319
|
|
|
306
|
-
if (result.kind ===
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
} else if (result.kind ===
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
320
|
+
if (result.kind === "task") {
|
|
321
|
+
// The agent created a task.
|
|
322
|
+
const taskResult = result as Task;
|
|
323
|
+
console.log("Send Message Result (Task):", taskResult);
|
|
324
|
+
taskId = taskResult.id; // Save the task ID for the next call
|
|
325
|
+
} else if (result.kind === "message") {
|
|
326
|
+
// The agent responded with a direct message.
|
|
327
|
+
const messageResult = result as Message;
|
|
328
|
+
console.log("Send Message Result (Direct Message):", messageResult);
|
|
329
|
+
// No task was created, so we can't get task status.
|
|
316
330
|
}
|
|
317
331
|
|
|
318
332
|
// 2. If a task was created, get its status.
|
|
319
333
|
if (taskId) {
|
|
320
|
-
|
|
321
|
-
|
|
334
|
+
const getParams: TaskQueryParams = { id: taskId };
|
|
335
|
+
const getResponse: GetTaskResponse = await client.getTask(getParams);
|
|
322
336
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
const getTaskResult = (getResponse as GetTaskSuccessResponse).result;
|
|
329
|
-
console.log("Get Task Result:", getTaskResult);
|
|
330
|
-
}
|
|
337
|
+
if (getResponse.error) {
|
|
338
|
+
console.error(`Error getting task ${taskId}:`, getResponse.error);
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
331
341
|
|
|
342
|
+
const getTaskResult = (getResponse as GetTaskSuccessResponse).result;
|
|
343
|
+
console.log("Get Task Result:", getTaskResult);
|
|
344
|
+
}
|
|
332
345
|
} catch (error) {
|
|
333
346
|
console.error("A2A Client Communication Error:", error);
|
|
334
347
|
}
|
|
@@ -340,8 +353,8 @@ run();
|
|
|
340
353
|
### Streaming Usage
|
|
341
354
|
|
|
342
355
|
```typescript
|
|
343
|
-
import {
|
|
344
|
-
|
|
356
|
+
import { A2AClient } from "@a2a-js/sdk/client";
|
|
357
|
+
import type {
|
|
345
358
|
TaskStatusUpdateEvent,
|
|
346
359
|
TaskArtifactUpdateEvent,
|
|
347
360
|
MessageSendParams,
|
|
@@ -356,31 +369,33 @@ async function streamTask() {
|
|
|
356
369
|
const messageId = uuidv4();
|
|
357
370
|
try {
|
|
358
371
|
console.log(`\n--- Starting streaming task for message ${messageId} ---`);
|
|
359
|
-
|
|
372
|
+
|
|
360
373
|
// Construct the `MessageSendParams` object.
|
|
361
374
|
const streamParams: MessageSendParams = {
|
|
362
375
|
message: {
|
|
363
376
|
messageId: messageId,
|
|
364
377
|
role: "user",
|
|
365
378
|
parts: [{ kind: "text", text: "Stream me some updates!" }],
|
|
366
|
-
kind: "message"
|
|
379
|
+
kind: "message",
|
|
367
380
|
},
|
|
368
381
|
};
|
|
369
|
-
|
|
382
|
+
|
|
370
383
|
// Use the `sendMessageStream` method.
|
|
371
384
|
const stream = client.sendMessageStream(streamParams);
|
|
372
385
|
let currentTaskId: string | undefined;
|
|
373
386
|
|
|
374
387
|
for await (const event of stream) {
|
|
375
388
|
// The first event is often the Task object itself, establishing the ID.
|
|
376
|
-
if ((event as Task).kind ===
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
389
|
+
if ((event as Task).kind === "task") {
|
|
390
|
+
currentTaskId = (event as Task).id;
|
|
391
|
+
console.log(
|
|
392
|
+
`[${currentTaskId}] Task created. Status: ${(event as Task).status.state}`
|
|
393
|
+
);
|
|
394
|
+
continue;
|
|
380
395
|
}
|
|
381
|
-
|
|
396
|
+
|
|
382
397
|
// Differentiate subsequent stream events.
|
|
383
|
-
if ((event as TaskStatusUpdateEvent).kind ===
|
|
398
|
+
if ((event as TaskStatusUpdateEvent).kind === "status-update") {
|
|
384
399
|
const statusEvent = event as TaskStatusUpdateEvent;
|
|
385
400
|
console.log(
|
|
386
401
|
`[${statusEvent.taskId}] Status Update: ${statusEvent.status.state} - ${
|
|
@@ -391,7 +406,9 @@ async function streamTask() {
|
|
|
391
406
|
console.log(`[${statusEvent.taskId}] Stream marked as final.`);
|
|
392
407
|
break; // Exit loop when server signals completion
|
|
393
408
|
}
|
|
394
|
-
} else if (
|
|
409
|
+
} else if (
|
|
410
|
+
(event as TaskArtifactUpdateEvent).kind === "artifact-update"
|
|
411
|
+
) {
|
|
395
412
|
const artifactEvent = event as TaskArtifactUpdateEvent;
|
|
396
413
|
// Use artifact.name or artifact.artifactId for identification
|
|
397
414
|
console.log(
|