@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/dist/useA2ARuntime.d.ts
CHANGED
|
@@ -1,48 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
import { A2AAgentCard, A2AArtifact, A2ASendMessageConfiguration, A2ATask } from "./types.js";
|
|
2
|
+
import { A2AClient, A2AClientOptions } from "./A2AClient.js";
|
|
3
|
+
import { AssistantRuntime, AttachmentAdapter, DictationAdapter, ExternalStoreSharedOptions, FeedbackAdapter, RealtimeVoiceAdapter, SpeechSynthesisAdapter, ThreadHistoryAdapter, ThreadMessage } from "@assistant-ui/core";
|
|
4
|
+
|
|
5
|
+
//#region src/useA2ARuntime.d.ts
|
|
6
|
+
declare const useA2ATask: () => A2ATask | undefined;
|
|
7
|
+
declare const useA2AArtifacts: () => readonly A2AArtifact[];
|
|
8
|
+
declare const useA2AAgentCard: () => A2AAgentCard | undefined;
|
|
9
|
+
type UseA2AThreadListAdapter = {
|
|
10
|
+
threadId?: string;
|
|
11
|
+
onSwitchToNewThread?: () => Promise<void> | void;
|
|
12
|
+
onSwitchToThread?: (threadId: string) => Promise<{
|
|
13
|
+
messages: readonly ThreadMessage[];
|
|
14
|
+
}>;
|
|
15
15
|
};
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
onArtifactComplete?: (artifact: import("./types").A2AArtifact) => void;
|
|
39
|
-
adapters?: {
|
|
40
|
-
attachments?: AttachmentAdapter;
|
|
41
|
-
speech?: SpeechSynthesisAdapter;
|
|
42
|
-
feedback?: FeedbackAdapter;
|
|
43
|
-
history?: ThreadHistoryAdapter;
|
|
44
|
-
threadList?: UseA2AThreadListAdapter;
|
|
45
|
-
};
|
|
16
|
+
type UseA2ARuntimeOptions = ExternalStoreSharedOptions & {
|
|
17
|
+
/** Pre-built A2A client instance. Provide this OR baseUrl. */client?: A2AClient; /** Base URL of the A2A server. Used to create a client if `client` is not provided. */
|
|
18
|
+
baseUrl?: string; /** Optional path prefix for all API endpoints (e.g. "/v1"). Does not affect agent card discovery. Only used with baseUrl. */
|
|
19
|
+
basePath?: string; /** Optional tenant ID for multi-tenant servers. Only used with baseUrl. */
|
|
20
|
+
tenant?: string; /** Headers for the A2A client (only used with baseUrl). */
|
|
21
|
+
headers?: A2AClientOptions["headers"]; /** A2A extension URIs to negotiate. Only used with baseUrl. */
|
|
22
|
+
extensions?: string[]; /** Extra fetch options (e.g. `{ credentials: 'include' }`). Only used with `baseUrl`. */
|
|
23
|
+
fetchOptions?: A2AClientOptions["fetchOptions"]; /** Initial context ID for the conversation. */
|
|
24
|
+
contextId?: string; /** Default send message configuration. */
|
|
25
|
+
configuration?: A2ASendMessageConfiguration; /** Called when an error occurs. */
|
|
26
|
+
onError?: (error: Error) => void; /** Called when a run is cancelled. */
|
|
27
|
+
onCancel?: () => void; /** Called when an artifact is fully received (lastChunk). */
|
|
28
|
+
onArtifactComplete?: (artifact: A2AArtifact) => void;
|
|
29
|
+
adapters?: {
|
|
30
|
+
attachments?: AttachmentAdapter;
|
|
31
|
+
speech?: SpeechSynthesisAdapter;
|
|
32
|
+
dictation?: DictationAdapter;
|
|
33
|
+
voice?: RealtimeVoiceAdapter;
|
|
34
|
+
feedback?: FeedbackAdapter;
|
|
35
|
+
history?: ThreadHistoryAdapter;
|
|
36
|
+
threadList?: UseA2AThreadListAdapter;
|
|
37
|
+
};
|
|
46
38
|
};
|
|
47
|
-
|
|
39
|
+
declare function useA2ARuntime(options: UseA2ARuntimeOptions): AssistantRuntime;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { UseA2ARuntimeOptions, UseA2AThreadListAdapter, useA2AAgentCard, useA2AArtifacts, useA2ARuntime, useA2ATask };
|
|
48
42
|
//# sourceMappingURL=useA2ARuntime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useA2ARuntime.d.ts","
|
|
1
|
+
{"version":3,"file":"useA2ARuntime.d.ts","names":[],"sources":["../src/useA2ARuntime.ts"],"mappings":";;;;;cAyDa,UAAA,QAAU,OAAA;AAAA,cAIV,eAAA,iBAAe,WAAA;AAAA,cAIf,eAAA,QAAe,YAAA;AAAA,KAMhB,uBAAA;EACV,QAAA;EACA,mBAAA,SAA4B,OAAA;EAC5B,gBAAA,IAAoB,QAAA,aAAqB,OAAA;IACvC,QAAA,WAAmB,aAAA;EAAA;AAAA;AAAA,KAMX,oBAAA,GAAuB,0BAAA;EAhBtB,8DAkBX,MAAA,GAAS,SAAA;EAET,OAAA,WApB0B;EAsB1B,QAAA,WAhBiC;EAkBjC,MAAA,WAhB4B;EAkB5B,OAAA,GAAU,gBAAA,aAjB+B;EAmBzC,UAAA,aAnBgD;EAqBhD,YAAA,GAAe,gBAAA,kBAtBf;EAyBA,SAAA,WAxBA;EA0BA,aAAA,GAAgB,2BAAA,EA1ByB;EA6BzC,OAAA,IAAW,KAAA,EAAO,KAAA,WA5BG;EA8BrB,QAAA,eA9BkC;EAgClC,kBAAA,IAAsB,QAAA,EAJC,WAAA;EAMvB,QAAA;IACE,WAAA,GAAc,iBAAA;IACd,MAAA,GAAS,sBAAA;IACT,SAAA,GAAY,gBAAA;IACZ,KAAA,GAAQ,oBAAA;IACR,QAAA,GAAW,eAAA;IACX,OAAA,GAAU,oBAAA;IACV,UAAA,GAAa,uBAAA;EAAA;AAAA;AAAA,iBAMD,aAAA,CAAc,OAAA,EAAS,oBAAA,GAAuB,gBAAgB"}
|
package/dist/useA2ARuntime.js
CHANGED
|
@@ -1,145 +1,130 @@
|
|
|
1
|
-
/// <reference types="@assistant-ui/core/store" />
|
|
2
1
|
"use client";
|
|
3
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
|
-
import { useExternalStoreRuntime, useRuntimeAdapters, } from "@assistant-ui/core/react";
|
|
5
|
-
import { useAuiState } from "@assistant-ui/store";
|
|
6
2
|
import { A2AClient } from "./A2AClient.js";
|
|
7
3
|
import { A2AThreadRuntimeCore } from "./A2AThreadRuntimeCore.js";
|
|
8
|
-
|
|
4
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { useExternalStoreRuntime, useExternalStoreSharedOptions, useRuntimeAdapters } from "@assistant-ui/core/react";
|
|
6
|
+
import { useAuiState } from "@assistant-ui/store";
|
|
7
|
+
//#region src/useA2ARuntime.ts
|
|
9
8
|
const symbolA2AExtras = Symbol("a2a-extras");
|
|
10
9
|
const asA2AExtras = (extras) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
!(symbolA2AExtras in extras))
|
|
14
|
-
throw new Error("This hook can only be used inside a useA2ARuntime provider");
|
|
15
|
-
return extras;
|
|
10
|
+
if (typeof extras !== "object" || extras == null || !(symbolA2AExtras in extras)) throw new Error("This hook can only be used inside a useA2ARuntime provider");
|
|
11
|
+
return extras;
|
|
16
12
|
};
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return useAuiState((s) => asA2AExtras(s.thread.extras).task);
|
|
13
|
+
const useA2ATask = () => {
|
|
14
|
+
return useAuiState((s) => asA2AExtras(s.thread.extras).task);
|
|
20
15
|
};
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
const useA2AArtifacts = () => {
|
|
17
|
+
return useAuiState((s) => asA2AExtras(s.thread.extras).artifacts);
|
|
23
18
|
};
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
const useA2AAgentCard = () => {
|
|
20
|
+
return useAuiState((s) => asA2AExtras(s.thread.extras).agentCard);
|
|
26
21
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
};
|
|
132
|
-
}, [adapterAdapters, core, _version]);
|
|
133
|
-
const runtime = useExternalStoreRuntime(store);
|
|
134
|
-
useEffect(() => {
|
|
135
|
-
core.attachRuntime(runtime);
|
|
136
|
-
return () => {
|
|
137
|
-
core.detachRuntime();
|
|
138
|
-
};
|
|
139
|
-
}, [core, runtime]);
|
|
140
|
-
useEffect(() => {
|
|
141
|
-
core.__internal_load();
|
|
142
|
-
}, [core]);
|
|
143
|
-
return runtime;
|
|
22
|
+
function useA2ARuntime(options) {
|
|
23
|
+
const [_version, setVersion] = useState(0);
|
|
24
|
+
const notifyUpdate = useCallback(() => setVersion((v) => v + 1), []);
|
|
25
|
+
const runtimeAdapters = useRuntimeAdapters();
|
|
26
|
+
const historyAdapter = options.adapters?.history ?? runtimeAdapters?.history;
|
|
27
|
+
const threadListAdapter = options.adapters?.threadList;
|
|
28
|
+
const clientRef = useRef(null);
|
|
29
|
+
if (!clientRef.current) if (options.client) clientRef.current = options.client;
|
|
30
|
+
else if (options.baseUrl) clientRef.current = new A2AClient({
|
|
31
|
+
baseUrl: options.baseUrl,
|
|
32
|
+
basePath: options.basePath,
|
|
33
|
+
tenant: options.tenant,
|
|
34
|
+
headers: options.headers,
|
|
35
|
+
extensions: options.extensions,
|
|
36
|
+
fetchOptions: options.fetchOptions
|
|
37
|
+
});
|
|
38
|
+
else throw new Error("useA2ARuntime requires either `client` or `baseUrl`");
|
|
39
|
+
const client = clientRef.current;
|
|
40
|
+
const coreRef = useRef(null);
|
|
41
|
+
if (!coreRef.current) coreRef.current = new A2AThreadRuntimeCore({
|
|
42
|
+
client,
|
|
43
|
+
contextId: options.contextId,
|
|
44
|
+
configuration: options.configuration,
|
|
45
|
+
...options.onError && { onError: options.onError },
|
|
46
|
+
...options.onCancel && { onCancel: options.onCancel },
|
|
47
|
+
...options.onArtifactComplete && { onArtifactComplete: options.onArtifactComplete },
|
|
48
|
+
...historyAdapter && { history: historyAdapter },
|
|
49
|
+
notifyUpdate
|
|
50
|
+
});
|
|
51
|
+
const core = coreRef.current;
|
|
52
|
+
core.updateOptions({
|
|
53
|
+
client,
|
|
54
|
+
contextId: options.contextId,
|
|
55
|
+
configuration: options.configuration,
|
|
56
|
+
...options.onError && { onError: options.onError },
|
|
57
|
+
...options.onCancel && { onCancel: options.onCancel },
|
|
58
|
+
...options.onArtifactComplete && { onArtifactComplete: options.onArtifactComplete },
|
|
59
|
+
...historyAdapter && { history: historyAdapter }
|
|
60
|
+
});
|
|
61
|
+
const threadList = useMemo(() => {
|
|
62
|
+
if (!threadListAdapter) return void 0;
|
|
63
|
+
const { onSwitchToNewThread, onSwitchToThread } = threadListAdapter;
|
|
64
|
+
return {
|
|
65
|
+
threadId: threadListAdapter.threadId,
|
|
66
|
+
onSwitchToNewThread: onSwitchToNewThread ? async () => {
|
|
67
|
+
await onSwitchToNewThread();
|
|
68
|
+
core.applyExternalMessages([]);
|
|
69
|
+
} : void 0,
|
|
70
|
+
onSwitchToThread: onSwitchToThread ? async (threadId) => {
|
|
71
|
+
const result = await onSwitchToThread(threadId);
|
|
72
|
+
core.applyExternalMessages(result.messages);
|
|
73
|
+
} : void 0
|
|
74
|
+
};
|
|
75
|
+
}, [threadListAdapter, core]);
|
|
76
|
+
const adapters = options.adapters;
|
|
77
|
+
const adapterAdapters = useMemo(() => ({
|
|
78
|
+
attachments: adapters?.attachments ?? runtimeAdapters?.attachments,
|
|
79
|
+
speech: adapters?.speech,
|
|
80
|
+
dictation: adapters?.dictation,
|
|
81
|
+
voice: adapters?.voice,
|
|
82
|
+
feedback: adapters?.feedback,
|
|
83
|
+
threadList
|
|
84
|
+
}), [
|
|
85
|
+
adapters,
|
|
86
|
+
runtimeAdapters,
|
|
87
|
+
threadList
|
|
88
|
+
]);
|
|
89
|
+
const shared = useExternalStoreSharedOptions(options);
|
|
90
|
+
const runtime = useExternalStoreRuntime(useMemo(() => {
|
|
91
|
+
return {
|
|
92
|
+
...shared,
|
|
93
|
+
isLoading: core.isLoading,
|
|
94
|
+
messages: core.getMessages(),
|
|
95
|
+
isRunning: core.isRunning(),
|
|
96
|
+
extras: {
|
|
97
|
+
[symbolA2AExtras]: true,
|
|
98
|
+
task: core.getTask(),
|
|
99
|
+
artifacts: core.getArtifacts(),
|
|
100
|
+
agentCard: core.getAgentCard()
|
|
101
|
+
},
|
|
102
|
+
onNew: (message) => core.append(message),
|
|
103
|
+
onEdit: (message) => core.edit(message),
|
|
104
|
+
onReload: (parentId) => core.reload(parentId),
|
|
105
|
+
onCancel: () => core.cancel(),
|
|
106
|
+
setMessages: (messages) => core.applyExternalMessages(messages),
|
|
107
|
+
onImport: (messages) => core.applyExternalMessages(messages),
|
|
108
|
+
adapters: adapterAdapters
|
|
109
|
+
};
|
|
110
|
+
}, [
|
|
111
|
+
adapterAdapters,
|
|
112
|
+
core,
|
|
113
|
+
_version,
|
|
114
|
+
shared
|
|
115
|
+
]));
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
core.attachRuntime(runtime);
|
|
118
|
+
return () => {
|
|
119
|
+
core.detachRuntime();
|
|
120
|
+
};
|
|
121
|
+
}, [core, runtime]);
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
core.__internal_load();
|
|
124
|
+
}, [core]);
|
|
125
|
+
return runtime;
|
|
144
126
|
}
|
|
127
|
+
//#endregion
|
|
128
|
+
export { useA2AAgentCard, useA2AArtifacts, useA2ARuntime, useA2ATask };
|
|
129
|
+
|
|
145
130
|
//# sourceMappingURL=useA2ARuntime.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useA2ARuntime.js","sourceRoot":"","sources":["../src/useA2ARuntime.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useA2ARuntime.js","names":[],"sources":["../src/useA2ARuntime.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n useExternalStoreRuntime,\n useExternalStoreSharedOptions,\n useRuntimeAdapters,\n} from \"@assistant-ui/core/react\";\nimport type {\n AssistantRuntime,\n AppendMessage,\n AttachmentAdapter,\n DictationAdapter,\n ExternalStoreAdapter,\n ExternalStoreSharedOptions,\n FeedbackAdapter,\n RealtimeVoiceAdapter,\n SpeechSynthesisAdapter,\n ThreadHistoryAdapter,\n ThreadMessage,\n} from \"@assistant-ui/core\";\nimport { useAuiState } from \"@assistant-ui/store\";\nimport { A2AClient } from \"./A2AClient\";\nimport type { A2AClientOptions } from \"./A2AClient\";\nimport { A2AThreadRuntimeCore } from \"./A2AThreadRuntimeCore\";\nimport type {\n A2AArtifact,\n A2AAgentCard,\n A2ASendMessageConfiguration,\n A2ATask,\n} from \"./types\";\n\n// --- Extras symbol for A2A-specific state ---\n\nconst symbolA2AExtras = Symbol(\"a2a-extras\");\n\ntype A2AExtras = {\n [symbolA2AExtras]: true;\n task: A2ATask | undefined;\n artifacts: readonly A2AArtifact[];\n agentCard: A2AAgentCard | undefined;\n};\n\nconst asA2AExtras = (extras: unknown): A2AExtras => {\n if (\n typeof extras !== \"object\" ||\n extras == null ||\n !(symbolA2AExtras in extras)\n )\n throw new Error(\n \"This hook can only be used inside a useA2ARuntime provider\",\n );\n return extras as A2AExtras;\n};\n\n// --- Public hooks for A2A state ---\n\nexport const useA2ATask = () => {\n return useAuiState((s) => asA2AExtras(s.thread.extras).task);\n};\n\nexport const useA2AArtifacts = () => {\n return useAuiState((s) => asA2AExtras(s.thread.extras).artifacts);\n};\n\nexport const useA2AAgentCard = () => {\n return useAuiState((s) => asA2AExtras(s.thread.extras).agentCard);\n};\n\n// --- Thread list adapter type ---\n\nexport type UseA2AThreadListAdapter = {\n threadId?: string;\n onSwitchToNewThread?: () => Promise<void> | void;\n onSwitchToThread?: (threadId: string) => Promise<{\n messages: readonly ThreadMessage[];\n }>;\n};\n\n// --- Options ---\n\nexport type UseA2ARuntimeOptions = ExternalStoreSharedOptions & {\n /** Pre-built A2A client instance. Provide this OR baseUrl. */\n client?: A2AClient;\n /** Base URL of the A2A server. Used to create a client if `client` is not provided. */\n baseUrl?: string;\n /** Optional path prefix for all API endpoints (e.g. \"/v1\"). Does not affect agent card discovery. Only used with baseUrl. */\n basePath?: string;\n /** Optional tenant ID for multi-tenant servers. Only used with baseUrl. */\n tenant?: string;\n /** Headers for the A2A client (only used with baseUrl). */\n headers?: A2AClientOptions[\"headers\"];\n /** A2A extension URIs to negotiate. Only used with baseUrl. */\n extensions?: string[];\n /** Extra fetch options (e.g. `{ credentials: 'include' }`). Only used with `baseUrl`. */\n fetchOptions?: A2AClientOptions[\"fetchOptions\"];\n\n /** Initial context ID for the conversation. */\n contextId?: string;\n /** Default send message configuration. */\n configuration?: A2ASendMessageConfiguration;\n\n /** Called when an error occurs. */\n onError?: (error: Error) => void;\n /** Called when a run is cancelled. */\n onCancel?: () => void;\n /** Called when an artifact is fully received (lastChunk). */\n onArtifactComplete?: (artifact: import(\"./types\").A2AArtifact) => void;\n\n adapters?: {\n attachments?: AttachmentAdapter;\n speech?: SpeechSynthesisAdapter;\n dictation?: DictationAdapter;\n voice?: RealtimeVoiceAdapter;\n feedback?: FeedbackAdapter;\n history?: ThreadHistoryAdapter;\n threadList?: UseA2AThreadListAdapter;\n };\n};\n\n// --- Main hook ---\n\nexport function useA2ARuntime(options: UseA2ARuntimeOptions): AssistantRuntime {\n const [_version, setVersion] = useState(0);\n const notifyUpdate = useCallback(() => setVersion((v) => v + 1), []);\n const runtimeAdapters = useRuntimeAdapters();\n const historyAdapter = options.adapters?.history ?? runtimeAdapters?.history;\n const threadListAdapter = options.adapters?.threadList;\n\n // Create or reuse client\n const clientRef = useRef<A2AClient | null>(null);\n if (!clientRef.current) {\n if (options.client) {\n clientRef.current = options.client;\n } else if (options.baseUrl) {\n clientRef.current = new A2AClient({\n baseUrl: options.baseUrl,\n basePath: options.basePath,\n tenant: options.tenant,\n headers: options.headers,\n extensions: options.extensions,\n fetchOptions: options.fetchOptions,\n });\n } else {\n throw new Error(\"useA2ARuntime requires either `client` or `baseUrl`\");\n }\n }\n const client = clientRef.current;\n\n // Create or reuse core\n const coreRef = useRef<A2AThreadRuntimeCore | null>(null);\n if (!coreRef.current) {\n coreRef.current = new A2AThreadRuntimeCore({\n client,\n contextId: options.contextId,\n configuration: options.configuration,\n ...(options.onError && { onError: options.onError }),\n ...(options.onCancel && { onCancel: options.onCancel }),\n ...(options.onArtifactComplete && {\n onArtifactComplete: options.onArtifactComplete,\n }),\n ...(historyAdapter && { history: historyAdapter }),\n notifyUpdate,\n });\n }\n\n const core = coreRef.current;\n core.updateOptions({\n client,\n contextId: options.contextId,\n configuration: options.configuration,\n ...(options.onError && { onError: options.onError }),\n ...(options.onCancel && { onCancel: options.onCancel }),\n ...(options.onArtifactComplete && {\n onArtifactComplete: options.onArtifactComplete,\n }),\n ...(historyAdapter && { history: historyAdapter }),\n });\n\n // Thread list\n const threadList = useMemo(() => {\n if (!threadListAdapter) return undefined;\n\n const { onSwitchToNewThread, onSwitchToThread } = threadListAdapter;\n\n return {\n threadId: threadListAdapter.threadId,\n onSwitchToNewThread: onSwitchToNewThread\n ? async () => {\n await onSwitchToNewThread();\n core.applyExternalMessages([]);\n }\n : undefined,\n onSwitchToThread: onSwitchToThread\n ? async (threadId: string) => {\n const result = await onSwitchToThread(threadId);\n core.applyExternalMessages(result.messages);\n }\n : undefined,\n };\n }, [threadListAdapter, core]);\n\n // Adapters\n const adapters = options.adapters;\n const adapterAdapters = useMemo(\n () => ({\n attachments: adapters?.attachments ?? runtimeAdapters?.attachments,\n speech: adapters?.speech,\n dictation: adapters?.dictation,\n voice: adapters?.voice,\n feedback: adapters?.feedback,\n threadList,\n }),\n [adapters, runtimeAdapters, threadList],\n );\n\n // Build store adapter\n const shared = useExternalStoreSharedOptions(options);\n const store = useMemo(() => {\n void _version;\n\n return {\n ...shared,\n isLoading: core.isLoading,\n messages: core.getMessages(),\n isRunning: core.isRunning(),\n extras: {\n [symbolA2AExtras]: true,\n task: core.getTask(),\n artifacts: core.getArtifacts(),\n agentCard: core.getAgentCard(),\n } satisfies A2AExtras,\n onNew: (message: AppendMessage) => core.append(message),\n onEdit: (message: AppendMessage) => core.edit(message),\n onReload: (parentId: string | null) => core.reload(parentId),\n onCancel: () => core.cancel(),\n setMessages: (messages: readonly ThreadMessage[]) =>\n core.applyExternalMessages(messages),\n onImport: (messages: readonly ThreadMessage[]) =>\n core.applyExternalMessages(messages),\n adapters: adapterAdapters,\n } satisfies ExternalStoreAdapter<ThreadMessage>;\n }, [adapterAdapters, core, _version, shared]);\n\n const runtime = useExternalStoreRuntime(store);\n\n useEffect(() => {\n core.attachRuntime(runtime);\n return () => {\n core.detachRuntime();\n };\n }, [core, runtime]);\n\n useEffect(() => {\n core.__internal_load();\n }, [core]);\n\n return runtime;\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/react-a2a",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.17",
|
|
4
4
|
"description": "A2A (Agent-to-Agent) v1.0 protocol adapter for assistant-ui",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"a2a",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
],
|
|
30
30
|
"sideEffects": false,
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@assistant-ui/core": "^0.2.
|
|
33
|
-
"@assistant-ui/store": "^0.2.
|
|
32
|
+
"@assistant-ui/core": "^0.2.8",
|
|
33
|
+
"@assistant-ui/store": "^0.2.13"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@types/react": "*",
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@types/react": "^19.2.
|
|
46
|
-
"react": "^19.2.
|
|
47
|
-
"vitest": "^4.1.
|
|
48
|
-
"@assistant-ui/x-buildutils": "0.0.
|
|
45
|
+
"@types/react": "^19.2.15",
|
|
46
|
+
"react": "^19.2.6",
|
|
47
|
+
"vitest": "^4.1.7",
|
|
48
|
+
"@assistant-ui/x-buildutils": "0.0.10"
|
|
49
49
|
},
|
|
50
50
|
"publishConfig": {
|
|
51
51
|
"access": "public",
|
package/src/A2AClient.test.ts
CHANGED
|
@@ -148,6 +148,115 @@ describe("A2AClient", () => {
|
|
|
148
148
|
});
|
|
149
149
|
});
|
|
150
150
|
|
|
151
|
+
describe("fetchOptions", () => {
|
|
152
|
+
it("applies fetchOptions to all request types", async () => {
|
|
153
|
+
const fetchOptionsClient = new A2AClient({
|
|
154
|
+
baseUrl: "https://agent.test",
|
|
155
|
+
fetchOptions: { credentials: "include" },
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
fetchMock
|
|
159
|
+
.mockResolvedValueOnce(
|
|
160
|
+
mockFetchResponse({
|
|
161
|
+
task: { id: "t1", status: { state: "completed" } },
|
|
162
|
+
}),
|
|
163
|
+
)
|
|
164
|
+
.mockResolvedValueOnce(
|
|
165
|
+
mockFetchResponse({
|
|
166
|
+
name: "Test Agent",
|
|
167
|
+
description: "A test",
|
|
168
|
+
version: "1.0",
|
|
169
|
+
supportedInterfaces: [],
|
|
170
|
+
capabilities: {},
|
|
171
|
+
defaultInputModes: [],
|
|
172
|
+
defaultOutputModes: [],
|
|
173
|
+
skills: [],
|
|
174
|
+
}),
|
|
175
|
+
)
|
|
176
|
+
.mockResolvedValueOnce(
|
|
177
|
+
mockSSEResponse([
|
|
178
|
+
`data: ${JSON.stringify({ status_update: { task_id: "t1", context_id: "ctx-1", status: { state: "TASK_STATE_WORKING" } } })}`,
|
|
179
|
+
"",
|
|
180
|
+
"",
|
|
181
|
+
]),
|
|
182
|
+
)
|
|
183
|
+
.mockResolvedValueOnce(
|
|
184
|
+
mockSSEResponse([
|
|
185
|
+
`data: ${JSON.stringify({ status_update: { task_id: "t1", context_id: "ctx-1", status: { state: "TASK_STATE_WORKING" } } })}`,
|
|
186
|
+
"",
|
|
187
|
+
"",
|
|
188
|
+
]),
|
|
189
|
+
)
|
|
190
|
+
.mockResolvedValueOnce({
|
|
191
|
+
ok: true,
|
|
192
|
+
status: 204,
|
|
193
|
+
statusText: "No Content",
|
|
194
|
+
headers: new Headers(),
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
await fetchOptionsClient.sendMessage(userMessage);
|
|
198
|
+
await fetchOptionsClient.getAgentCard();
|
|
199
|
+
for await (const _ of fetchOptionsClient.streamMessage(userMessage)) {
|
|
200
|
+
void _;
|
|
201
|
+
}
|
|
202
|
+
for await (const _ of fetchOptionsClient.subscribeToTask("t1")) {
|
|
203
|
+
void _;
|
|
204
|
+
}
|
|
205
|
+
await fetchOptionsClient.deleteTaskPushNotificationConfig("t1", "pnc-1");
|
|
206
|
+
|
|
207
|
+
for (const [, init] of fetchMock.mock.calls) {
|
|
208
|
+
expect(init.credentials).toBe("include");
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it("strips internally-managed fields even when smuggled via cast", async () => {
|
|
213
|
+
const smuggledSignal = new AbortController().signal;
|
|
214
|
+
const fetchOptionsClient = new A2AClient({
|
|
215
|
+
baseUrl: "https://agent.test",
|
|
216
|
+
fetchOptions: {
|
|
217
|
+
method: "GET",
|
|
218
|
+
headers: { "X-Injected": "1" },
|
|
219
|
+
body: "smuggled",
|
|
220
|
+
signal: smuggledSignal,
|
|
221
|
+
} as RequestInit,
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
fetchMock
|
|
225
|
+
.mockResolvedValueOnce(
|
|
226
|
+
mockFetchResponse({
|
|
227
|
+
task: { id: "t1", status: { state: "completed" } },
|
|
228
|
+
}),
|
|
229
|
+
)
|
|
230
|
+
.mockResolvedValueOnce(
|
|
231
|
+
mockFetchResponse({
|
|
232
|
+
name: "Test",
|
|
233
|
+
description: "desc",
|
|
234
|
+
version: "1.0",
|
|
235
|
+
supportedInterfaces: [],
|
|
236
|
+
capabilities: {},
|
|
237
|
+
defaultInputModes: [],
|
|
238
|
+
defaultOutputModes: [],
|
|
239
|
+
skills: [],
|
|
240
|
+
}),
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
await fetchOptionsClient.sendMessage(userMessage);
|
|
244
|
+
await fetchOptionsClient.getAgentCard();
|
|
245
|
+
|
|
246
|
+
for (const [, init] of fetchMock.mock.calls) {
|
|
247
|
+
expect(init.headers["X-Injected"]).toBeUndefined();
|
|
248
|
+
expect(init.body).not.toBe("smuggled");
|
|
249
|
+
expect(init.signal).not.toBe(smuggledSignal);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
expect(fetchMock.mock.calls[0]![1].method).toBe("POST");
|
|
253
|
+
expect(fetchMock.mock.calls[0]![1].headers["Content-Type"]).toBe(
|
|
254
|
+
"application/a2a+json",
|
|
255
|
+
);
|
|
256
|
+
expect(fetchMock.mock.calls[1]![1].method).toBeUndefined();
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
|
|
151
260
|
// --- Tenant ---
|
|
152
261
|
|
|
153
262
|
describe("tenant", () => {
|
|
@@ -275,7 +384,7 @@ describe("A2AClient", () => {
|
|
|
275
384
|
expect(body.message.messageId).toBe("msg-1");
|
|
276
385
|
});
|
|
277
386
|
|
|
278
|
-
it("sends '
|
|
387
|
+
it("sends 'parts' per A2A v1.0 spec (gRPC + JSON-RPC unified in a2aproject/A2A#1100)", async () => {
|
|
279
388
|
fetchMock.mockResolvedValue(
|
|
280
389
|
mockFetchResponse({
|
|
281
390
|
task: { id: "t1", status: { state: "completed" } },
|
|
@@ -285,8 +394,8 @@ describe("A2AClient", () => {
|
|
|
285
394
|
await client.sendMessage(userMessage);
|
|
286
395
|
|
|
287
396
|
const body = JSON.parse(fetchMock.mock.calls[0]![1].body);
|
|
288
|
-
expect(body.message.
|
|
289
|
-
expect(body.message.
|
|
397
|
+
expect(body.message.parts).toEqual([{ text: "Hello" }]);
|
|
398
|
+
expect(body.message.content).toBeUndefined();
|
|
290
399
|
});
|
|
291
400
|
|
|
292
401
|
it("unwraps task from SendMessageResponse", async () => {
|
|
@@ -320,7 +429,7 @@ describe("A2AClient", () => {
|
|
|
320
429
|
expect((result as any).role).toBe("agent");
|
|
321
430
|
});
|
|
322
431
|
|
|
323
|
-
it("normalizes 'content' array from
|
|
432
|
+
it("normalizes 'content' array from v0.3 server response to internal 'parts'", async () => {
|
|
324
433
|
fetchMock.mockResolvedValue(
|
|
325
434
|
mockFetchResponse({
|
|
326
435
|
message: {
|
|
@@ -778,7 +887,7 @@ describe("A2AClient", () => {
|
|
|
778
887
|
expect(events).toHaveLength(2);
|
|
779
888
|
});
|
|
780
889
|
|
|
781
|
-
it("normalizes
|
|
890
|
+
it("normalizes 'content' array from v0.3 server response to 'parts' in SSE artifact update events", async () => {
|
|
782
891
|
const sseData = JSON.stringify({
|
|
783
892
|
artifact_update: {
|
|
784
893
|
task_id: "t1",
|
|
@@ -810,7 +919,7 @@ describe("A2AClient", () => {
|
|
|
810
919
|
expect((evt.event.artifact as any).content).toBeUndefined();
|
|
811
920
|
});
|
|
812
921
|
|
|
813
|
-
it("normalizes
|
|
922
|
+
it("normalizes 'content' array from v0.3 server response to 'parts' in SSE status update messages", async () => {
|
|
814
923
|
const sseData = JSON.stringify({
|
|
815
924
|
status_update: {
|
|
816
925
|
task_id: "t1",
|