@assistant-ui/react-a2a 0.2.15 → 0.2.17
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/dist/A2AClient.d.ts +45 -42
- package/dist/A2AClient.d.ts.map +1 -1
- package/dist/A2AClient.js +273 -349
- package/dist/A2AClient.js.map +1 -1
- package/dist/A2AThreadRuntimeCore.d.ts +76 -72
- package/dist/A2AThreadRuntimeCore.d.ts.map +1 -1
- package/dist/A2AThreadRuntimeCore.js +400 -479
- package/dist/A2AThreadRuntimeCore.js.map +1 -1
- package/dist/conversions.d.ts +16 -12
- package/dist/conversions.d.ts.map +1 -1
- package/dist/conversions.js +88 -79
- package/dist/conversions.js.map +1 -1
- package/dist/index.d.ts +5 -8
- package/dist/index.js +5 -8
- package/dist/types.d.ts +229 -228
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +5 -4
- package/dist/types.js.map +1 -1
- package/dist/useA2ARuntime.d.ts +39 -45
- package/dist/useA2ARuntime.d.ts.map +1 -1
- package/dist/useA2ARuntime.js +119 -134
- package/dist/useA2ARuntime.js.map +1 -1
- package/package.json +7 -7
- package/src/A2AClient.test.ts +115 -6
- package/src/A2AClient.ts +37 -7
- package/src/A2AThreadRuntimeCore.test.ts +5 -5
- package/src/conversions.test.ts +12 -14
- package/src/useA2ARuntime.ts +15 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
package/src/A2AClient.ts
CHANGED
|
@@ -26,6 +26,10 @@ export type A2AClientOptions = {
|
|
|
26
26
|
| undefined;
|
|
27
27
|
/** A2A extension URIs to negotiate. Sent as A2A-Extensions header. */
|
|
28
28
|
extensions?: string[] | undefined;
|
|
29
|
+
/** Extra fetch options applied to every request. */
|
|
30
|
+
fetchOptions?:
|
|
31
|
+
| Omit<RequestInit, "headers" | "body" | "method" | "signal">
|
|
32
|
+
| undefined;
|
|
29
33
|
};
|
|
30
34
|
|
|
31
35
|
export class A2AError extends Error {
|
|
@@ -87,10 +91,10 @@ function normalizeKeys(obj: unknown, opaque = false): unknown {
|
|
|
87
91
|
) {
|
|
88
92
|
result[camelKey] = value.slice(5).toLowerCase();
|
|
89
93
|
} else if (camelKey === "content" && Array.isArray(value)) {
|
|
90
|
-
//
|
|
94
|
+
// v0.3 servers used "content" for message/artifact parts; normalize to "parts" for backward compat
|
|
91
95
|
result.parts = normalizeKeys(value, false);
|
|
92
96
|
} else if (camelKey !== "parts" || !("parts" in result)) {
|
|
93
|
-
//
|
|
97
|
+
// dedup: "content" was already mapped to parts above; don't overwrite
|
|
94
98
|
result[camelKey] = isOpaqueChild ? value : normalizeKeys(value, false);
|
|
95
99
|
}
|
|
96
100
|
}
|
|
@@ -111,8 +115,7 @@ function toWireTaskState(state: A2ATaskState): string {
|
|
|
111
115
|
}
|
|
112
116
|
|
|
113
117
|
function toWireMessage(msg: A2AMessage): unknown {
|
|
114
|
-
|
|
115
|
-
return { ...rest, role: toWireRole(msg.role), content: parts };
|
|
118
|
+
return { ...msg, role: toWireRole(msg.role) };
|
|
116
119
|
}
|
|
117
120
|
|
|
118
121
|
function discriminateStreamResponse(
|
|
@@ -158,6 +161,10 @@ export class A2AClient {
|
|
|
158
161
|
private basePath: string;
|
|
159
162
|
private tenant: string | undefined;
|
|
160
163
|
private extensionUris: string[] | undefined;
|
|
164
|
+
private fetchOptions: Omit<
|
|
165
|
+
RequestInit,
|
|
166
|
+
"headers" | "body" | "method" | "signal"
|
|
167
|
+
>;
|
|
161
168
|
private headersFn:
|
|
162
169
|
| Record<string, string>
|
|
163
170
|
| (() => Record<string, string> | Promise<Record<string, string>>);
|
|
@@ -169,6 +176,14 @@ export class A2AClient {
|
|
|
169
176
|
: "";
|
|
170
177
|
this.tenant = options.tenant;
|
|
171
178
|
this.extensionUris = options.extensions;
|
|
179
|
+
const {
|
|
180
|
+
headers: _h,
|
|
181
|
+
body: _b,
|
|
182
|
+
method: _m,
|
|
183
|
+
signal: _s,
|
|
184
|
+
...safeFetchOptions
|
|
185
|
+
} = (options.fetchOptions ?? {}) as RequestInit;
|
|
186
|
+
this.fetchOptions = safeFetchOptions;
|
|
172
187
|
this.headersFn = options.headers ?? {};
|
|
173
188
|
}
|
|
174
189
|
|
|
@@ -229,6 +244,7 @@ export class A2AClient {
|
|
|
229
244
|
const isGet = !options.method || options.method.toUpperCase() === "GET";
|
|
230
245
|
const headers = await this.getHeaders(!isGet);
|
|
231
246
|
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
247
|
+
...this.fetchOptions,
|
|
232
248
|
...options,
|
|
233
249
|
headers: {
|
|
234
250
|
...headers,
|
|
@@ -247,7 +263,11 @@ export class A2AClient {
|
|
|
247
263
|
async getAgentCard(signal?: AbortSignal): Promise<A2AAgentCard> {
|
|
248
264
|
const headers = await this.getHeaders(false); // GET: no Content-Type
|
|
249
265
|
const url = `${this.baseUrl}/.well-known/agent-card.json`;
|
|
250
|
-
const response = await fetch(url, {
|
|
266
|
+
const response = await fetch(url, {
|
|
267
|
+
...this.fetchOptions,
|
|
268
|
+
headers,
|
|
269
|
+
...signalInit(signal),
|
|
270
|
+
});
|
|
251
271
|
if (!response.ok) {
|
|
252
272
|
await this.throwResponseError(response);
|
|
253
273
|
}
|
|
@@ -310,6 +330,7 @@ export class A2AClient {
|
|
|
310
330
|
const response = await fetch(
|
|
311
331
|
`${this.baseUrl}${this.getBasePath()}/message:stream`,
|
|
312
332
|
{
|
|
333
|
+
...this.fetchOptions,
|
|
313
334
|
method: "POST",
|
|
314
335
|
headers,
|
|
315
336
|
body: JSON.stringify(body),
|
|
@@ -390,7 +411,11 @@ export class A2AClient {
|
|
|
390
411
|
|
|
391
412
|
const response = await fetch(
|
|
392
413
|
`${this.baseUrl}${this.getBasePath()}/tasks/${encodeURIComponent(taskId)}:subscribe`,
|
|
393
|
-
{
|
|
414
|
+
{
|
|
415
|
+
...this.fetchOptions,
|
|
416
|
+
headers,
|
|
417
|
+
...signalInit(signal),
|
|
418
|
+
},
|
|
394
419
|
);
|
|
395
420
|
if (!response.ok) {
|
|
396
421
|
await this.throwResponseError(response);
|
|
@@ -453,7 +478,12 @@ export class A2AClient {
|
|
|
453
478
|
const headers = await this.getHeaders(!isGet);
|
|
454
479
|
const response = await fetch(
|
|
455
480
|
`${this.baseUrl}${this.getBasePath()}/tasks/${encodeURIComponent(taskId)}/pushNotificationConfigs/${encodeURIComponent(configId)}`,
|
|
456
|
-
{
|
|
481
|
+
{
|
|
482
|
+
...this.fetchOptions,
|
|
483
|
+
method: "DELETE",
|
|
484
|
+
headers,
|
|
485
|
+
...signalInit(signal),
|
|
486
|
+
},
|
|
457
487
|
);
|
|
458
488
|
if (!response.ok) {
|
|
459
489
|
await this.throwResponseError(response);
|
|
@@ -37,7 +37,7 @@ function createUserAppendMessage(text: string): AppendMessage {
|
|
|
37
37
|
parentId: null,
|
|
38
38
|
role: "user",
|
|
39
39
|
content: [{ type: "text", text }],
|
|
40
|
-
};
|
|
40
|
+
} as unknown as AppendMessage;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
function statusUpdateEvent(state: string, text?: string): A2AStreamEvent {
|
|
@@ -90,7 +90,7 @@ describe("A2AThreadRuntimeCore", () => {
|
|
|
90
90
|
) {
|
|
91
91
|
return new A2AThreadRuntimeCore({
|
|
92
92
|
client: createMockClient(clientOverrides),
|
|
93
|
-
notifyUpdate,
|
|
93
|
+
notifyUpdate: notifyUpdate as unknown as () => void,
|
|
94
94
|
...coreOverrides,
|
|
95
95
|
});
|
|
96
96
|
}
|
|
@@ -369,7 +369,7 @@ describe("A2AThreadRuntimeCore", () => {
|
|
|
369
369
|
}),
|
|
370
370
|
}),
|
|
371
371
|
onArtifactComplete,
|
|
372
|
-
notifyUpdate,
|
|
372
|
+
notifyUpdate: notifyUpdate as unknown as () => void,
|
|
373
373
|
});
|
|
374
374
|
|
|
375
375
|
await core.append(createUserAppendMessage("Go"));
|
|
@@ -588,7 +588,7 @@ describe("A2AThreadRuntimeCore", () => {
|
|
|
588
588
|
})),
|
|
589
589
|
}),
|
|
590
590
|
onError,
|
|
591
|
-
notifyUpdate,
|
|
591
|
+
notifyUpdate: notifyUpdate as unknown as () => void,
|
|
592
592
|
});
|
|
593
593
|
|
|
594
594
|
await expect(core.append(createUserAppendMessage("Go"))).rejects.toThrow(
|
|
@@ -680,7 +680,7 @@ describe("A2AThreadRuntimeCore", () => {
|
|
|
680
680
|
createdAt: new Date(),
|
|
681
681
|
content: [{ type: "text", text: "External" }],
|
|
682
682
|
status: { type: "complete", reason: "stop" },
|
|
683
|
-
} as ThreadMessage,
|
|
683
|
+
} as unknown as ThreadMessage,
|
|
684
684
|
];
|
|
685
685
|
|
|
686
686
|
core.applyExternalMessages(msgs);
|
package/src/conversions.test.ts
CHANGED
|
@@ -200,14 +200,12 @@ describe("taskStateToMessageStatus", () => {
|
|
|
200
200
|
});
|
|
201
201
|
|
|
202
202
|
describe("isTerminalTaskState", () => {
|
|
203
|
-
it.each([
|
|
204
|
-
"
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
expect(isTerminalTaskState(state)).toBe(true);
|
|
210
|
-
});
|
|
203
|
+
it.each(["completed", "failed", "canceled", "rejected"] as A2ATaskState[])(
|
|
204
|
+
"returns true for %s",
|
|
205
|
+
(state) => {
|
|
206
|
+
expect(isTerminalTaskState(state)).toBe(true);
|
|
207
|
+
},
|
|
208
|
+
);
|
|
211
209
|
|
|
212
210
|
it.each([
|
|
213
211
|
"submitted",
|
|
@@ -221,12 +219,12 @@ describe("isTerminalTaskState", () => {
|
|
|
221
219
|
});
|
|
222
220
|
|
|
223
221
|
describe("isInterruptedTaskState", () => {
|
|
224
|
-
it.each([
|
|
225
|
-
"
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
222
|
+
it.each(["input_required", "auth_required"] as A2ATaskState[])(
|
|
223
|
+
"returns true for %s",
|
|
224
|
+
(state) => {
|
|
225
|
+
expect(isInterruptedTaskState(state)).toBe(true);
|
|
226
|
+
},
|
|
227
|
+
);
|
|
230
228
|
|
|
231
229
|
it.each([
|
|
232
230
|
"submitted",
|
package/src/useA2ARuntime.ts
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
|
-
/// <reference types="@assistant-ui/core/store" />
|
|
2
1
|
"use client";
|
|
3
2
|
|
|
4
3
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
5
4
|
import {
|
|
6
5
|
useExternalStoreRuntime,
|
|
6
|
+
useExternalStoreSharedOptions,
|
|
7
7
|
useRuntimeAdapters,
|
|
8
8
|
} from "@assistant-ui/core/react";
|
|
9
9
|
import type {
|
|
10
10
|
AssistantRuntime,
|
|
11
11
|
AppendMessage,
|
|
12
12
|
AttachmentAdapter,
|
|
13
|
+
DictationAdapter,
|
|
13
14
|
ExternalStoreAdapter,
|
|
15
|
+
ExternalStoreSharedOptions,
|
|
14
16
|
FeedbackAdapter,
|
|
17
|
+
RealtimeVoiceAdapter,
|
|
15
18
|
SpeechSynthesisAdapter,
|
|
16
19
|
ThreadHistoryAdapter,
|
|
17
20
|
ThreadMessage,
|
|
@@ -76,7 +79,7 @@ export type UseA2AThreadListAdapter = {
|
|
|
76
79
|
|
|
77
80
|
// --- Options ---
|
|
78
81
|
|
|
79
|
-
export type UseA2ARuntimeOptions = {
|
|
82
|
+
export type UseA2ARuntimeOptions = ExternalStoreSharedOptions & {
|
|
80
83
|
/** Pre-built A2A client instance. Provide this OR baseUrl. */
|
|
81
84
|
client?: A2AClient;
|
|
82
85
|
/** Base URL of the A2A server. Used to create a client if `client` is not provided. */
|
|
@@ -89,6 +92,8 @@ export type UseA2ARuntimeOptions = {
|
|
|
89
92
|
headers?: A2AClientOptions["headers"];
|
|
90
93
|
/** A2A extension URIs to negotiate. Only used with baseUrl. */
|
|
91
94
|
extensions?: string[];
|
|
95
|
+
/** Extra fetch options (e.g. `{ credentials: 'include' }`). Only used with `baseUrl`. */
|
|
96
|
+
fetchOptions?: A2AClientOptions["fetchOptions"];
|
|
92
97
|
|
|
93
98
|
/** Initial context ID for the conversation. */
|
|
94
99
|
contextId?: string;
|
|
@@ -105,6 +110,8 @@ export type UseA2ARuntimeOptions = {
|
|
|
105
110
|
adapters?: {
|
|
106
111
|
attachments?: AttachmentAdapter;
|
|
107
112
|
speech?: SpeechSynthesisAdapter;
|
|
113
|
+
dictation?: DictationAdapter;
|
|
114
|
+
voice?: RealtimeVoiceAdapter;
|
|
108
115
|
feedback?: FeedbackAdapter;
|
|
109
116
|
history?: ThreadHistoryAdapter;
|
|
110
117
|
threadList?: UseA2AThreadListAdapter;
|
|
@@ -132,6 +139,7 @@ export function useA2ARuntime(options: UseA2ARuntimeOptions): AssistantRuntime {
|
|
|
132
139
|
tenant: options.tenant,
|
|
133
140
|
headers: options.headers,
|
|
134
141
|
extensions: options.extensions,
|
|
142
|
+
fetchOptions: options.fetchOptions,
|
|
135
143
|
});
|
|
136
144
|
} else {
|
|
137
145
|
throw new Error("useA2ARuntime requires either `client` or `baseUrl`");
|
|
@@ -198,6 +206,8 @@ export function useA2ARuntime(options: UseA2ARuntimeOptions): AssistantRuntime {
|
|
|
198
206
|
() => ({
|
|
199
207
|
attachments: adapters?.attachments ?? runtimeAdapters?.attachments,
|
|
200
208
|
speech: adapters?.speech,
|
|
209
|
+
dictation: adapters?.dictation,
|
|
210
|
+
voice: adapters?.voice,
|
|
201
211
|
feedback: adapters?.feedback,
|
|
202
212
|
threadList,
|
|
203
213
|
}),
|
|
@@ -205,10 +215,12 @@ export function useA2ARuntime(options: UseA2ARuntimeOptions): AssistantRuntime {
|
|
|
205
215
|
);
|
|
206
216
|
|
|
207
217
|
// Build store adapter
|
|
218
|
+
const shared = useExternalStoreSharedOptions(options);
|
|
208
219
|
const store = useMemo(() => {
|
|
209
220
|
void _version;
|
|
210
221
|
|
|
211
222
|
return {
|
|
223
|
+
...shared,
|
|
212
224
|
isLoading: core.isLoading,
|
|
213
225
|
messages: core.getMessages(),
|
|
214
226
|
isRunning: core.isRunning(),
|
|
@@ -228,7 +240,7 @@ export function useA2ARuntime(options: UseA2ARuntimeOptions): AssistantRuntime {
|
|
|
228
240
|
core.applyExternalMessages(messages),
|
|
229
241
|
adapters: adapterAdapters,
|
|
230
242
|
} satisfies ExternalStoreAdapter<ThreadMessage>;
|
|
231
|
-
}, [adapterAdapters, core, _version]);
|
|
243
|
+
}, [adapterAdapters, core, _version, shared]);
|
|
232
244
|
|
|
233
245
|
const runtime = useExternalStoreRuntime(store);
|
|
234
246
|
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,aAAa,EACb,UAAU,EACV,eAAe,EACf,eAAe,GAChB,2BAAwB;AACzB,YAAY,EACV,oBAAoB,EACpB,uBAAuB,GACxB,2BAAwB;AAGzB,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,uBAAoB;AAClD,YAAY,EAAE,gBAAgB,EAAE,uBAAoB;AAGpD,YAAY,EACV,OAAO,EACP,OAAO,EACP,UAAU,EACV,YAAY,EACZ,aAAa,EACb,WAAW,EACX,OAAO,EACP,cAAc,EACd,wBAAwB,EACxB,0BAA0B,EAC1B,qBAAqB,EACrB,6BAA6B,EAC7B,0CAA0C,EAC1C,2BAA2B,EAC3B,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,uBAAuB,EACvB,yBAAyB,EACzB,6BAA6B,EAC7B,6BAA6B,EAC7B,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,uBAAuB,EACvB,8BAA8B,EAC9B,0BAA0B,EAC1B,iBAAiB,EACjB,sBAAsB,EACtB,qBAAqB,EACrB,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,GACb,mBAAgB;AACjB,OAAO,EAAE,oBAAoB,EAAE,mBAAgB;AAG/C,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,wBAAwB,EACxB,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,GACvB,yBAAsB"}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY;AACZ,OAAO,EACL,aAAa,EACb,UAAU,EACV,eAAe,EACf,eAAe,GAChB,2BAAwB;AAMzB,SAAS;AACT,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,uBAAoB;AAyClD,OAAO,EAAE,oBAAoB,EAAE,mBAAgB;AAE/C,4CAA4C;AAC5C,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,wBAAwB,EACxB,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,GACvB,yBAAsB"}
|