@a2a-js/sdk 0.3.7 → 0.3.9
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 +70 -0
- package/dist/{chunk-SJNAG4AL.js → chunk-EGOOH5HP.js} +1 -55
- package/dist/chunk-F6ACNKFR.js +41 -0
- package/dist/chunk-QQCCX2KH.js +3338 -0
- package/dist/{chunk-LTPINR5K.js → chunk-S53FFHPM.js} +3 -98
- package/dist/chunk-TS5RMC7F.js +56 -0
- package/dist/chunk-U3QAVT4H.js +1986 -0
- package/dist/chunk-UHZEIZLS.js +62 -0
- package/dist/client/index.cjs +2118 -26
- package/dist/client/index.d.cts +4 -415
- package/dist/client/index.d.ts +4 -415
- package/dist/client/index.js +111 -35
- package/dist/client/transports/grpc/index.cjs +4601 -0
- package/dist/client/transports/grpc/index.d.cts +42 -0
- package/dist/client/transports/grpc/index.d.ts +42 -0
- package/dist/client/transports/grpc/index.js +262 -0
- package/dist/core-BAzQJfA2.d.ts +416 -0
- package/dist/core-Ci-lR0jz.d.cts +416 -0
- package/dist/server/express/index.cjs +2134 -120
- package/dist/server/express/index.js +80 -20
- package/dist/server/grpc/index.cjs +4560 -0
- package/dist/server/grpc/index.d.cts +1053 -0
- package/dist/server/grpc/index.d.ts +1053 -0
- package/dist/server/grpc/index.js +186 -0
- package/dist/server/index.cjs +1 -1
- package/dist/server/index.js +8 -4
- package/package.json +41 -3
package/README.md
CHANGED
|
@@ -29,10 +29,28 @@ If you plan to use the Express integration (imports from `@a2a-js/sdk/server/exp
|
|
|
29
29
|
npm install express
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
### For gRPC Usage
|
|
33
|
+
|
|
34
|
+
If you plan to use the GRPC transport (imports from `@a2a-js/sdk/server/grpc` or `@a2a-js/sdk/client/grpc`), you must install the required peer dependencies:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install @grpc/grpc-js @bufbuild/protobuf
|
|
38
|
+
```
|
|
39
|
+
|
|
32
40
|
You can also find some samples [here](https://github.com/a2aproject/a2a-js/tree/main/src/samples).
|
|
33
41
|
|
|
34
42
|
---
|
|
35
43
|
|
|
44
|
+
## Compatibility
|
|
45
|
+
|
|
46
|
+
This SDK implements the A2A Protocol Specification [`v0.3.0`](https://a2a-protocol.org/v0.3.0/specification).
|
|
47
|
+
|
|
48
|
+
| Transport | Client | Server |
|
|
49
|
+
| :--- | :---: | :---: |
|
|
50
|
+
| **JSON-RPC** | ✅ | ✅ |
|
|
51
|
+
| **HTTP+JSON/REST** | ✅ | ✅ |
|
|
52
|
+
| **GRPC** (Node.js only) | ✅ | ✅ |
|
|
53
|
+
|
|
36
54
|
## Quickstart
|
|
37
55
|
|
|
38
56
|
This example shows how to create a simple "Hello World" agent server and a client to interact with it.
|
|
@@ -44,6 +62,7 @@ The core of an A2A server is the `AgentExecutor`, which contains your agent's lo
|
|
|
44
62
|
```typescript
|
|
45
63
|
// server.ts
|
|
46
64
|
import express from 'express';
|
|
65
|
+
import { Server, ServerCredentials } from '@grpc/grpc-js';
|
|
47
66
|
import { v4 as uuidv4 } from 'uuid';
|
|
48
67
|
import { AgentCard, Message, AGENT_CARD_PATH } from '@a2a-js/sdk';
|
|
49
68
|
import {
|
|
@@ -54,6 +73,7 @@ import {
|
|
|
54
73
|
InMemoryTaskStore,
|
|
55
74
|
} from '@a2a-js/sdk/server';
|
|
56
75
|
import { agentCardHandler, jsonRpcHandler, restHandler, UserBuilder } from '@a2a-js/sdk/server/express';
|
|
76
|
+
import { grpcService, A2AService } from '@a2a-js/sdk/server/grpc';
|
|
57
77
|
|
|
58
78
|
// 1. Define your agent's identity card.
|
|
59
79
|
const helloAgentCard: AgentCard = {
|
|
@@ -71,6 +91,7 @@ const helloAgentCard: AgentCard = {
|
|
|
71
91
|
additionalInterfaces: [
|
|
72
92
|
{ url: 'http://localhost:4000/a2a/jsonrpc', transport: 'JSONRPC' }, // Default JSON-RPC transport
|
|
73
93
|
{ url: 'http://localhost:4000/a2a/rest', transport: 'HTTP+JSON' }, // HTTP+JSON/REST transport
|
|
94
|
+
{ url: 'localhost:4001', transport: 'GRPC' }, // GRPC transport
|
|
74
95
|
],
|
|
75
96
|
};
|
|
76
97
|
|
|
@@ -113,6 +134,15 @@ app.use('/a2a/rest', restHandler({ requestHandler, userBuilder: UserBuilder.noAu
|
|
|
113
134
|
app.listen(4000, () => {
|
|
114
135
|
console.log(`🚀 Server started on http://localhost:4000`);
|
|
115
136
|
});
|
|
137
|
+
|
|
138
|
+
const server = new Server();
|
|
139
|
+
server.addService(A2AService, grpcService({
|
|
140
|
+
requestHandler,
|
|
141
|
+
userBuilder: UserBuilder.noAuthentication,
|
|
142
|
+
}));
|
|
143
|
+
server.bindAsync(`localhost:4001`, ServerCredentials.createInsecure(), () => {
|
|
144
|
+
console.log(`🚀 Server started on localhost:4001`);
|
|
145
|
+
});
|
|
116
146
|
```
|
|
117
147
|
|
|
118
148
|
### Client: Sending a Message
|
|
@@ -153,6 +183,46 @@ async function run() {
|
|
|
153
183
|
await run();
|
|
154
184
|
```
|
|
155
185
|
|
|
186
|
+
### gRPC Client: Sending a Message
|
|
187
|
+
|
|
188
|
+
The [`ClientFactory`](src/client/factory.ts) has to be created explicitly passing the [`GrpcTransportFactory`](src/client/transports/grpc/grpc_transport.ts).
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
// client.ts
|
|
192
|
+
import { ClientFactory, ClientFactoryOptions } from '@a2a-js/sdk/client';
|
|
193
|
+
import { GrpcTransportFactory } from '@a2a-js/sdk/client/grpc';
|
|
194
|
+
import { Message, MessageSendParams, SendMessageSuccessResponse } from '@a2a-js/sdk';
|
|
195
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
196
|
+
|
|
197
|
+
async function run() {
|
|
198
|
+
const factory = new ClientFactory({
|
|
199
|
+
transports: [new GrpcTransportFactory()]
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// createFromUrl accepts baseUrl and optional path,
|
|
203
|
+
// (the default path is /.well-known/agent-card.json)
|
|
204
|
+
const client = await factory.createFromUrl('http://localhost:4000');
|
|
205
|
+
|
|
206
|
+
const sendParams: MessageSendParams = {
|
|
207
|
+
message: {
|
|
208
|
+
messageId: uuidv4(),
|
|
209
|
+
role: 'user',
|
|
210
|
+
parts: [{ kind: 'text', text: 'Hi there!' }],
|
|
211
|
+
kind: 'message',
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
try {
|
|
216
|
+
const response = await client.sendMessage(sendParams);
|
|
217
|
+
const result = response as Message;
|
|
218
|
+
console.log('Agent response:', result.parts[0].text); // "Hello, world!"
|
|
219
|
+
} catch(e) {
|
|
220
|
+
console.error('Error:', e);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
await run();
|
|
225
|
+
```
|
|
156
226
|
---
|
|
157
227
|
|
|
158
228
|
## A2A `Task` Support
|
|
@@ -56,56 +56,6 @@ var AuthenticatedExtendedCardNotConfiguredError = class extends Error {
|
|
|
56
56
|
}
|
|
57
57
|
};
|
|
58
58
|
|
|
59
|
-
// src/sse_utils.ts
|
|
60
|
-
var SSE_HEADERS = {
|
|
61
|
-
"Content-Type": "text/event-stream",
|
|
62
|
-
"Cache-Control": "no-cache",
|
|
63
|
-
Connection: "keep-alive",
|
|
64
|
-
"X-Accel-Buffering": "no"
|
|
65
|
-
// Disable buffering in nginx
|
|
66
|
-
};
|
|
67
|
-
function formatSSEEvent(event) {
|
|
68
|
-
return `data: ${JSON.stringify(event)}
|
|
69
|
-
|
|
70
|
-
`;
|
|
71
|
-
}
|
|
72
|
-
function formatSSEErrorEvent(error) {
|
|
73
|
-
return `event: error
|
|
74
|
-
data: ${JSON.stringify(error)}
|
|
75
|
-
|
|
76
|
-
`;
|
|
77
|
-
}
|
|
78
|
-
async function* parseSseStream(response) {
|
|
79
|
-
if (!response.body) {
|
|
80
|
-
throw new Error("SSE response body is undefined. Cannot read stream.");
|
|
81
|
-
}
|
|
82
|
-
let buffer = "";
|
|
83
|
-
let eventType = "message";
|
|
84
|
-
let eventData = "";
|
|
85
|
-
for await (const value of response.body.pipeThrough(new TextDecoderStream())) {
|
|
86
|
-
buffer += value;
|
|
87
|
-
let lineEndIndex;
|
|
88
|
-
while ((lineEndIndex = buffer.indexOf("\n")) >= 0) {
|
|
89
|
-
const line = buffer.substring(0, lineEndIndex).trim();
|
|
90
|
-
buffer = buffer.substring(lineEndIndex + 1);
|
|
91
|
-
if (line === "") {
|
|
92
|
-
if (eventData) {
|
|
93
|
-
yield { type: eventType, data: eventData };
|
|
94
|
-
eventData = "";
|
|
95
|
-
eventType = "message";
|
|
96
|
-
}
|
|
97
|
-
} else if (line.startsWith("event:")) {
|
|
98
|
-
eventType = line.substring("event:".length).trim();
|
|
99
|
-
} else if (line.startsWith("data:")) {
|
|
100
|
-
eventData = line.substring("data:".length).trim();
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
if (eventData) {
|
|
105
|
-
yield { type: eventType, data: eventData };
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
59
|
export {
|
|
110
60
|
A2A_ERROR_CODE,
|
|
111
61
|
TaskNotFoundError,
|
|
@@ -114,9 +64,5 @@ export {
|
|
|
114
64
|
UnsupportedOperationError,
|
|
115
65
|
ContentTypeNotSupportedError,
|
|
116
66
|
InvalidAgentResponseError,
|
|
117
|
-
AuthenticatedExtendedCardNotConfiguredError
|
|
118
|
-
SSE_HEADERS,
|
|
119
|
-
formatSSEEvent,
|
|
120
|
-
formatSSEErrorEvent,
|
|
121
|
-
parseSseStream
|
|
67
|
+
AuthenticatedExtendedCardNotConfiguredError
|
|
122
68
|
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Extensions
|
|
3
|
+
} from "./chunk-ZX6KNMCP.js";
|
|
4
|
+
|
|
5
|
+
// src/server/context.ts
|
|
6
|
+
var ServerCallContext = class {
|
|
7
|
+
_requestedExtensions;
|
|
8
|
+
_user;
|
|
9
|
+
_activatedExtensions;
|
|
10
|
+
constructor(requestedExtensions, user) {
|
|
11
|
+
this._requestedExtensions = requestedExtensions;
|
|
12
|
+
this._user = user;
|
|
13
|
+
}
|
|
14
|
+
get user() {
|
|
15
|
+
return this._user;
|
|
16
|
+
}
|
|
17
|
+
get activatedExtensions() {
|
|
18
|
+
return this._activatedExtensions;
|
|
19
|
+
}
|
|
20
|
+
get requestedExtensions() {
|
|
21
|
+
return this._requestedExtensions;
|
|
22
|
+
}
|
|
23
|
+
addActivatedExtension(uri) {
|
|
24
|
+
this._activatedExtensions = Extensions.createFrom(this._activatedExtensions, uri);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// src/server/authentication/user.ts
|
|
29
|
+
var UnauthenticatedUser = class {
|
|
30
|
+
get isAuthenticated() {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
get userName() {
|
|
34
|
+
return "";
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export {
|
|
39
|
+
ServerCallContext,
|
|
40
|
+
UnauthenticatedUser
|
|
41
|
+
};
|