@assistant-ui/react-google-adk 0.0.6 → 0.0.8
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/AdkClient.d.ts.map +1 -1
- package/dist/AdkClient.js +1 -26
- package/dist/AdkClient.js.map +1 -1
- package/dist/AdkEventAccumulator.d.ts.map +1 -1
- package/dist/AdkEventAccumulator.js +10 -20
- package/dist/AdkEventAccumulator.js.map +1 -1
- package/dist/AdkSessionAdapter.js +2 -2
- package/dist/AdkSessionAdapter.js.map +1 -1
- package/dist/contentToParts.d.ts +3 -0
- package/dist/contentToParts.d.ts.map +1 -0
- package/dist/contentToParts.js +36 -0
- package/dist/contentToParts.js.map +1 -0
- package/dist/convertAdkMessages.d.ts +1 -1
- package/dist/convertAdkMessages.d.ts.map +1 -1
- package/dist/convertAdkMessages.js +16 -0
- package/dist/convertAdkMessages.js.map +1 -1
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/useAdkMessages.d.ts.map +1 -1
- package/dist/useAdkMessages.js +3 -27
- package/dist/useAdkMessages.js.map +1 -1
- package/dist/useAdkRuntime.d.ts +2 -1
- package/dist/useAdkRuntime.d.ts.map +1 -1
- package/dist/useAdkRuntime.js +25 -7
- package/dist/useAdkRuntime.js.map +1 -1
- package/package.json +7 -7
- package/src/AdkClient.test.ts +99 -0
- package/src/AdkClient.ts +4 -31
- package/src/AdkEventAccumulator.test.ts +125 -2
- package/src/AdkEventAccumulator.ts +30 -20
- package/src/AdkSessionAdapter.test.ts +1 -1
- package/src/AdkSessionAdapter.ts +3 -3
- package/src/contentToParts.ts +38 -0
- package/src/convertAdkMessages.test.ts +53 -0
- package/src/convertAdkMessages.ts +18 -1
- package/src/types.ts +11 -0
- package/src/useAdkMessages.test.ts +75 -0
- package/src/useAdkMessages.ts +3 -31
- package/src/useAdkRuntime.test.ts +74 -1
- package/src/useAdkRuntime.ts +25 -6
package/dist/useAdkRuntime.js
CHANGED
|
@@ -7,7 +7,8 @@ import { useAdkMessages } from "./useAdkMessages.js";
|
|
|
7
7
|
import { convertAdkMessage } from "./convertAdkMessages.js";
|
|
8
8
|
import { symbolAdkRuntimeExtras } from "./hooks.js";
|
|
9
9
|
import { v4 as uuidv4 } from "uuid";
|
|
10
|
-
|
|
10
|
+
/** @internal — exported for unit tests. */
|
|
11
|
+
export const getMessageContent = (msg) => {
|
|
11
12
|
const allContent = [
|
|
12
13
|
...msg.content,
|
|
13
14
|
...(msg.attachments?.flatMap((a) => a.content) ?? []),
|
|
@@ -21,14 +22,17 @@ const getMessageContent = (msg) => {
|
|
|
21
22
|
return { type: "image_url", url: part.image };
|
|
22
23
|
case "file":
|
|
23
24
|
return {
|
|
24
|
-
type: "
|
|
25
|
-
|
|
25
|
+
type: "file",
|
|
26
|
+
mimeType: part.mimeType,
|
|
27
|
+
data: part.data,
|
|
28
|
+
...(part.filename != null && { filename: part.filename }),
|
|
26
29
|
};
|
|
27
30
|
case "tool-call":
|
|
28
31
|
throw new Error("Tool call appends are not supported.");
|
|
29
|
-
default:
|
|
32
|
+
default: {
|
|
30
33
|
const _exhaustiveCheck = type;
|
|
31
34
|
throw new Error(`Unsupported append message part type: ${_exhaustiveCheck}`);
|
|
35
|
+
}
|
|
32
36
|
}
|
|
33
37
|
});
|
|
34
38
|
if (content.length === 1 && content[0]?.type === "text") {
|
|
@@ -85,13 +89,18 @@ const truncateAdkMessages = (threadMessages, parentId) => {
|
|
|
85
89
|
}
|
|
86
90
|
return truncated;
|
|
87
91
|
};
|
|
88
|
-
const useAdkRuntimeImpl = ({ autoCancelPendingToolCalls, adapters: { attachments, feedback, speech } = {}, unstable_allowCancellation, stream, load, getCheckpointId, eventHandlers, }) => {
|
|
92
|
+
const useAdkRuntimeImpl = ({ autoCancelPendingToolCalls, adapters: { attachments, dictation, feedback, speech } = {}, unstable_allowCancellation, stream, load, getCheckpointId, eventHandlers, }) => {
|
|
93
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
89
94
|
const aui = useAui();
|
|
90
|
-
const { messages, stateDelta, agentInfo, longRunningToolIds, artifactDelta, toolConfirmations, authRequests, escalated, messageMetadata, sendMessage, cancel, replaceMessages,
|
|
95
|
+
const { messages, stateDelta, agentInfo, longRunningToolIds, artifactDelta, toolConfirmations, authRequests, escalated, messageMetadata, sendMessage, cancel, replaceMessages,
|
|
96
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
97
|
+
} = useAdkMessages({
|
|
91
98
|
stream,
|
|
92
99
|
...(eventHandlers && { eventHandlers }),
|
|
93
100
|
});
|
|
101
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
94
102
|
const [isRunning, setIsRunning] = useState(false);
|
|
103
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
95
104
|
const [toolStatuses, setToolStatuses] = useState({});
|
|
96
105
|
const hasExecutingTools = Object.values(toolStatuses).some((s) => s?.type === "executing");
|
|
97
106
|
const effectiveIsRunning = isRunning || hasExecutingTools;
|
|
@@ -104,18 +113,22 @@ const useAdkRuntimeImpl = ({ autoCancelPendingToolCalls, adapters: { attachments
|
|
|
104
113
|
setIsRunning(false);
|
|
105
114
|
}
|
|
106
115
|
};
|
|
116
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
107
117
|
const threadMessages = useExternalMessageConverter({
|
|
108
118
|
callback: convertAdkMessage,
|
|
109
119
|
messages,
|
|
110
120
|
isRunning: effectiveIsRunning,
|
|
111
121
|
});
|
|
122
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
112
123
|
const threadMessagesRef = useRef(threadMessages);
|
|
113
124
|
threadMessagesRef.current = threadMessages;
|
|
125
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
114
126
|
const [runtimeRef] = useState(() => ({
|
|
115
127
|
get current() {
|
|
116
128
|
return runtime;
|
|
117
129
|
},
|
|
118
130
|
}));
|
|
131
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
119
132
|
const toolInvocations = useToolInvocations({
|
|
120
133
|
state: { messages: threadMessages, isRunning: effectiveIsRunning },
|
|
121
134
|
getTools: () => runtimeRef.current.thread.getModelContext().tools,
|
|
@@ -135,10 +148,11 @@ const useAdkRuntimeImpl = ({ autoCancelPendingToolCalls, adapters: { attachments
|
|
|
135
148
|
},
|
|
136
149
|
setToolStatuses,
|
|
137
150
|
});
|
|
151
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
138
152
|
const runtime = useExternalStoreRuntime({
|
|
139
153
|
isRunning: effectiveIsRunning,
|
|
140
154
|
messages: threadMessages,
|
|
141
|
-
adapters: { attachments, feedback, speech },
|
|
155
|
+
adapters: { attachments, dictation, feedback, speech },
|
|
142
156
|
extras: {
|
|
143
157
|
[symbolAdkRuntimeExtras]: true,
|
|
144
158
|
agentInfo,
|
|
@@ -223,10 +237,13 @@ const useAdkRuntimeImpl = ({ autoCancelPendingToolCalls, adapters: { attachments
|
|
|
223
237
|
: undefined,
|
|
224
238
|
});
|
|
225
239
|
{
|
|
240
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
226
241
|
const loadRef = useRef(load);
|
|
242
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
227
243
|
useEffect(() => {
|
|
228
244
|
loadRef.current = load;
|
|
229
245
|
});
|
|
246
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
230
247
|
useEffect(() => {
|
|
231
248
|
const loadFn = loadRef.current;
|
|
232
249
|
if (!loadFn)
|
|
@@ -259,6 +276,7 @@ export const useAdkRuntime = ({ cloud, sessionAdapter, create, delete: deleteFn,
|
|
|
259
276
|
const adapter = sessionAdapter ?? cloudAdapter;
|
|
260
277
|
return useRemoteThreadListRuntime({
|
|
261
278
|
runtimeHook: function RuntimeHook() {
|
|
279
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
262
280
|
return useAdkRuntimeImpl(options);
|
|
263
281
|
},
|
|
264
282
|
adapter,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAdkRuntime.js","sourceRoot":"","sources":["../src/useAdkRuntime.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EACL,wBAAwB,
|
|
1
|
+
{"version":3,"file":"useAdkRuntime.js","sourceRoot":"","sources":["../src/useAdkRuntime.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/react-google-adk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "Google ADK adapter for assistant-ui",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"google-adk",
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
],
|
|
35
35
|
"sideEffects": false,
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@assistant-ui/core": "^0.1.
|
|
38
|
-
"@assistant-ui/store": "^0.2.
|
|
37
|
+
"@assistant-ui/core": "^0.1.16",
|
|
38
|
+
"@assistant-ui/store": "^0.2.9",
|
|
39
39
|
"assistant-cloud": "*",
|
|
40
|
-
"assistant-stream": "^0.3.
|
|
41
|
-
"uuid": "^
|
|
40
|
+
"assistant-stream": "^0.3.12",
|
|
41
|
+
"uuid": "^14.0.0"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"@google/adk": ">=0.5.0",
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
"@types/react": "^19.2.14",
|
|
58
58
|
"@types/uuid": "^11.0.0",
|
|
59
59
|
"react": "^19.2.5",
|
|
60
|
-
"vitest": "^4.1.
|
|
61
|
-
"@assistant-ui/x-buildutils": "0.0.
|
|
60
|
+
"vitest": "^4.1.5",
|
|
61
|
+
"@assistant-ui/x-buildutils": "0.0.6"
|
|
62
62
|
},
|
|
63
63
|
"publishConfig": {
|
|
64
64
|
"access": "public",
|
package/src/AdkClient.test.ts
CHANGED
|
@@ -137,6 +137,37 @@ describe("createAdkStream - proxy mode", () => {
|
|
|
137
137
|
});
|
|
138
138
|
});
|
|
139
139
|
|
|
140
|
+
it("sends file parts as inlineData in proxy mode", async () => {
|
|
141
|
+
mockFetch.mockResolvedValueOnce(new Response(sseBody(""), { status: 200 }));
|
|
142
|
+
|
|
143
|
+
const stream = createAdkStream({ api: "/api/adk" });
|
|
144
|
+
const messages: AdkMessage[] = [
|
|
145
|
+
{
|
|
146
|
+
id: "m1",
|
|
147
|
+
type: "human",
|
|
148
|
+
content: [
|
|
149
|
+
{ type: "text", text: "see attached" },
|
|
150
|
+
{
|
|
151
|
+
type: "file",
|
|
152
|
+
mimeType: "application/pdf",
|
|
153
|
+
data: "JVBERi0xLjQK",
|
|
154
|
+
filename: "report.pdf",
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
},
|
|
158
|
+
];
|
|
159
|
+
const gen = await stream(messages, makeConfig());
|
|
160
|
+
for await (const _ of gen) {
|
|
161
|
+
/* noop */
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const body = JSON.parse(mockFetch.mock.calls[0]![1]?.body as string);
|
|
165
|
+
expect(body.parts).toHaveLength(2);
|
|
166
|
+
expect(body.parts[1]).toEqual({
|
|
167
|
+
inlineData: { mimeType: "application/pdf", data: "JVBERi0xLjQK" },
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
140
171
|
it("sends parts array when multiple messages are provided", async () => {
|
|
141
172
|
mockFetch.mockResolvedValueOnce(new Response(sseBody(""), { status: 200 }));
|
|
142
173
|
|
|
@@ -608,6 +639,74 @@ describe("createAdkStream - content conversion", () => {
|
|
|
608
639
|
});
|
|
609
640
|
});
|
|
610
641
|
|
|
642
|
+
it("converts file content parts to inlineData in direct mode", async () => {
|
|
643
|
+
mockFetch.mockResolvedValueOnce(new Response(sseBody(""), { status: 200 }));
|
|
644
|
+
|
|
645
|
+
const stream = createAdkStream({
|
|
646
|
+
api: "http://localhost:8000",
|
|
647
|
+
appName: "app",
|
|
648
|
+
userId: "u",
|
|
649
|
+
});
|
|
650
|
+
const messages: AdkMessage[] = [
|
|
651
|
+
{
|
|
652
|
+
id: "m1",
|
|
653
|
+
type: "human",
|
|
654
|
+
content: [
|
|
655
|
+
{
|
|
656
|
+
type: "file",
|
|
657
|
+
mimeType: "application/pdf",
|
|
658
|
+
data: "JVBERi0xLjQK",
|
|
659
|
+
filename: "report.pdf",
|
|
660
|
+
},
|
|
661
|
+
],
|
|
662
|
+
},
|
|
663
|
+
];
|
|
664
|
+
const gen = await stream(messages, makeConfig());
|
|
665
|
+
for await (const _ of gen) {
|
|
666
|
+
/* noop */
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
const body = JSON.parse(mockFetch.mock.calls[0]![1]?.body as string);
|
|
670
|
+
expect(body.newMessage.parts[0]).toEqual({
|
|
671
|
+
inlineData: { mimeType: "application/pdf", data: "JVBERi0xLjQK" },
|
|
672
|
+
});
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
it("converts file_url content parts to fileData with mimeType in direct mode", async () => {
|
|
676
|
+
mockFetch.mockResolvedValueOnce(new Response(sseBody(""), { status: 200 }));
|
|
677
|
+
|
|
678
|
+
const stream = createAdkStream({
|
|
679
|
+
api: "http://localhost:8000",
|
|
680
|
+
appName: "app",
|
|
681
|
+
userId: "u",
|
|
682
|
+
});
|
|
683
|
+
const messages: AdkMessage[] = [
|
|
684
|
+
{
|
|
685
|
+
id: "m1",
|
|
686
|
+
type: "human",
|
|
687
|
+
content: [
|
|
688
|
+
{
|
|
689
|
+
type: "file_url",
|
|
690
|
+
url: "gs://bucket/report.pdf",
|
|
691
|
+
mimeType: "application/pdf",
|
|
692
|
+
},
|
|
693
|
+
],
|
|
694
|
+
},
|
|
695
|
+
];
|
|
696
|
+
const gen = await stream(messages, makeConfig());
|
|
697
|
+
for await (const _ of gen) {
|
|
698
|
+
/* noop */
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
const body = JSON.parse(mockFetch.mock.calls[0]![1]?.body as string);
|
|
702
|
+
expect(body.newMessage.parts[0]).toEqual({
|
|
703
|
+
fileData: {
|
|
704
|
+
fileUri: "gs://bucket/report.pdf",
|
|
705
|
+
mimeType: "application/pdf",
|
|
706
|
+
},
|
|
707
|
+
});
|
|
708
|
+
});
|
|
709
|
+
|
|
611
710
|
it("converts code content parts to executableCode", async () => {
|
|
612
711
|
mockFetch.mockResolvedValueOnce(new Response(sseBody(""), { status: 200 }));
|
|
613
712
|
|
package/src/AdkClient.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { contentToParts } from "./contentToParts";
|
|
1
2
|
import type {
|
|
2
3
|
AdkEvent,
|
|
4
|
+
AdkEventPart,
|
|
3
5
|
AdkMessage,
|
|
4
|
-
AdkMessageContentPart,
|
|
5
6
|
AdkStreamCallback,
|
|
6
7
|
} from "./types";
|
|
7
8
|
|
|
@@ -119,9 +120,9 @@ async function resolveHeaders(
|
|
|
119
120
|
*/
|
|
120
121
|
function messagesToContent(messages: AdkMessage[]): {
|
|
121
122
|
role: string;
|
|
122
|
-
parts:
|
|
123
|
+
parts: AdkEventPart[];
|
|
123
124
|
} {
|
|
124
|
-
const parts:
|
|
125
|
+
const parts: AdkEventPart[] = [];
|
|
125
126
|
|
|
126
127
|
for (const msg of messages) {
|
|
127
128
|
if (msg.type === "human") {
|
|
@@ -209,34 +210,6 @@ function messagesToProxyBody(
|
|
|
209
210
|
return body;
|
|
210
211
|
}
|
|
211
212
|
|
|
212
|
-
function contentToParts(
|
|
213
|
-
content: string | AdkMessageContentPart[],
|
|
214
|
-
): Array<Record<string, unknown>> {
|
|
215
|
-
if (typeof content === "string") return [{ text: content }];
|
|
216
|
-
return content.map((part) => {
|
|
217
|
-
switch (part.type) {
|
|
218
|
-
case "text":
|
|
219
|
-
return { text: part.text };
|
|
220
|
-
case "reasoning":
|
|
221
|
-
return { text: part.text, thought: true };
|
|
222
|
-
case "image":
|
|
223
|
-
return { inlineData: { mimeType: part.mimeType, data: part.data } };
|
|
224
|
-
case "image_url":
|
|
225
|
-
return { fileData: { fileUri: part.url } };
|
|
226
|
-
case "code":
|
|
227
|
-
return {
|
|
228
|
-
executableCode: { code: part.code, language: part.language },
|
|
229
|
-
};
|
|
230
|
-
case "code_result":
|
|
231
|
-
return {
|
|
232
|
-
codeExecutionResult: { output: part.output, outcome: part.outcome },
|
|
233
|
-
};
|
|
234
|
-
default:
|
|
235
|
-
return { text: "" };
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
|
|
240
213
|
async function* parseSSEResponse(response: Response): AsyncGenerator<AdkEvent> {
|
|
241
214
|
const reader = response.body!.getReader();
|
|
242
215
|
const decoder = new TextDecoder();
|
|
@@ -1085,14 +1085,21 @@ describe("AdkEventAccumulator - user message handling", () => {
|
|
|
1085
1085
|
});
|
|
1086
1086
|
});
|
|
1087
1087
|
|
|
1088
|
-
it("creates human message with fileData content", () => {
|
|
1088
|
+
it("creates human message with image fileData content", () => {
|
|
1089
1089
|
const acc = new AdkEventAccumulator();
|
|
1090
1090
|
const msgs = acc.processEvent(
|
|
1091
1091
|
makeEvent({
|
|
1092
1092
|
author: "user",
|
|
1093
1093
|
content: {
|
|
1094
1094
|
role: "user",
|
|
1095
|
-
parts: [
|
|
1095
|
+
parts: [
|
|
1096
|
+
{
|
|
1097
|
+
fileData: {
|
|
1098
|
+
fileUri: "gs://bucket/image.png",
|
|
1099
|
+
mimeType: "image/png",
|
|
1100
|
+
},
|
|
1101
|
+
},
|
|
1102
|
+
],
|
|
1096
1103
|
},
|
|
1097
1104
|
}),
|
|
1098
1105
|
);
|
|
@@ -1103,6 +1110,122 @@ describe("AdkEventAccumulator - user message handling", () => {
|
|
|
1103
1110
|
});
|
|
1104
1111
|
});
|
|
1105
1112
|
|
|
1113
|
+
it("routes non-image inlineData to a file part", () => {
|
|
1114
|
+
const acc = new AdkEventAccumulator();
|
|
1115
|
+
const msgs = acc.processEvent(
|
|
1116
|
+
makeEvent({
|
|
1117
|
+
author: "user",
|
|
1118
|
+
content: {
|
|
1119
|
+
role: "user",
|
|
1120
|
+
parts: [
|
|
1121
|
+
{
|
|
1122
|
+
inlineData: { mimeType: "application/pdf", data: "JVBERi0xLjQK" },
|
|
1123
|
+
},
|
|
1124
|
+
],
|
|
1125
|
+
},
|
|
1126
|
+
}),
|
|
1127
|
+
);
|
|
1128
|
+
expect(msgs).toHaveLength(1);
|
|
1129
|
+
expect(msgs[0]).toMatchObject({
|
|
1130
|
+
type: "human",
|
|
1131
|
+
content: [
|
|
1132
|
+
{ type: "file", mimeType: "application/pdf", data: "JVBERi0xLjQK" },
|
|
1133
|
+
],
|
|
1134
|
+
});
|
|
1135
|
+
});
|
|
1136
|
+
|
|
1137
|
+
it("routes non-image fileData to a file_url part", () => {
|
|
1138
|
+
const acc = new AdkEventAccumulator();
|
|
1139
|
+
const msgs = acc.processEvent(
|
|
1140
|
+
makeEvent({
|
|
1141
|
+
author: "user",
|
|
1142
|
+
content: {
|
|
1143
|
+
role: "user",
|
|
1144
|
+
parts: [
|
|
1145
|
+
{
|
|
1146
|
+
fileData: {
|
|
1147
|
+
fileUri: "gs://bucket/report.pdf",
|
|
1148
|
+
mimeType: "application/pdf",
|
|
1149
|
+
},
|
|
1150
|
+
},
|
|
1151
|
+
],
|
|
1152
|
+
},
|
|
1153
|
+
}),
|
|
1154
|
+
);
|
|
1155
|
+
expect(msgs).toHaveLength(1);
|
|
1156
|
+
expect(msgs[0]).toMatchObject({
|
|
1157
|
+
type: "human",
|
|
1158
|
+
content: [
|
|
1159
|
+
{
|
|
1160
|
+
type: "file_url",
|
|
1161
|
+
url: "gs://bucket/report.pdf",
|
|
1162
|
+
mimeType: "application/pdf",
|
|
1163
|
+
},
|
|
1164
|
+
],
|
|
1165
|
+
});
|
|
1166
|
+
});
|
|
1167
|
+
|
|
1168
|
+
it("coerces fileData with image mime to image_url even if it originated as file_url (intentional, image mime is canonical)", () => {
|
|
1169
|
+
const acc = new AdkEventAccumulator();
|
|
1170
|
+
const msgs = acc.processEvent(
|
|
1171
|
+
makeEvent({
|
|
1172
|
+
author: "user",
|
|
1173
|
+
content: {
|
|
1174
|
+
role: "user",
|
|
1175
|
+
parts: [
|
|
1176
|
+
{
|
|
1177
|
+
fileData: {
|
|
1178
|
+
fileUri: "https://example.com/photo.jpg",
|
|
1179
|
+
mimeType: "image/jpeg",
|
|
1180
|
+
},
|
|
1181
|
+
},
|
|
1182
|
+
],
|
|
1183
|
+
},
|
|
1184
|
+
}),
|
|
1185
|
+
);
|
|
1186
|
+
expect(msgs).toHaveLength(1);
|
|
1187
|
+
expect(msgs[0]).toMatchObject({
|
|
1188
|
+
type: "human",
|
|
1189
|
+
content: [{ type: "image_url", url: "https://example.com/photo.jpg" }],
|
|
1190
|
+
});
|
|
1191
|
+
});
|
|
1192
|
+
|
|
1193
|
+
it("falls back to image_url for fileData with no mimeType (preserves legacy round-trip)", () => {
|
|
1194
|
+
const acc = new AdkEventAccumulator();
|
|
1195
|
+
const msgs = acc.processEvent(
|
|
1196
|
+
makeEvent({
|
|
1197
|
+
author: "user",
|
|
1198
|
+
content: {
|
|
1199
|
+
role: "user",
|
|
1200
|
+
parts: [{ fileData: { fileUri: "gs://bucket/unknown" } }],
|
|
1201
|
+
},
|
|
1202
|
+
}),
|
|
1203
|
+
);
|
|
1204
|
+
expect(msgs).toHaveLength(1);
|
|
1205
|
+
expect(msgs[0]).toMatchObject({
|
|
1206
|
+
type: "human",
|
|
1207
|
+
content: [{ type: "image_url", url: "gs://bucket/unknown" }],
|
|
1208
|
+
});
|
|
1209
|
+
});
|
|
1210
|
+
|
|
1211
|
+
it("routes assistant non-image inlineData to a file part", () => {
|
|
1212
|
+
const acc = new AdkEventAccumulator();
|
|
1213
|
+
const msgs = acc.processEvent(
|
|
1214
|
+
makeEvent({
|
|
1215
|
+
author: "assistant",
|
|
1216
|
+
content: {
|
|
1217
|
+
role: "model",
|
|
1218
|
+
parts: [{ inlineData: { mimeType: "audio/mpeg", data: "QUJDRA==" } }],
|
|
1219
|
+
},
|
|
1220
|
+
}),
|
|
1221
|
+
);
|
|
1222
|
+
expect(msgs).toHaveLength(1);
|
|
1223
|
+
expect(msgs[0]).toMatchObject({
|
|
1224
|
+
type: "ai",
|
|
1225
|
+
content: [{ type: "file", mimeType: "audio/mpeg", data: "QUJDRA==" }],
|
|
1226
|
+
});
|
|
1227
|
+
});
|
|
1228
|
+
|
|
1106
1229
|
it("tool result events (no author, role:'user') still create tool messages", () => {
|
|
1107
1230
|
// Regression: the user-author check must not hijack tool events.
|
|
1108
1231
|
// messageToEvent for `type:'tool'` emits events without `author`,
|
|
@@ -80,6 +80,22 @@ const finishReasonToStatus = (
|
|
|
80
80
|
return { type: "complete", reason: "stop" };
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
+
const inlineDataToPart = (
|
|
84
|
+
mimeType: string,
|
|
85
|
+
data: string,
|
|
86
|
+
): AdkMessageContentPart =>
|
|
87
|
+
mimeType.startsWith("image/")
|
|
88
|
+
? { type: "image", mimeType, data }
|
|
89
|
+
: { type: "file", mimeType, data };
|
|
90
|
+
|
|
91
|
+
const fileDataToPart = (
|
|
92
|
+
fileUri: string,
|
|
93
|
+
mimeType: string | undefined,
|
|
94
|
+
): AdkMessageContentPart =>
|
|
95
|
+
mimeType == null || mimeType.startsWith("image/")
|
|
96
|
+
? { type: "image_url", url: fileUri }
|
|
97
|
+
: { type: "file_url", url: fileUri, mimeType };
|
|
98
|
+
|
|
83
99
|
// ── Snake_case normalization ──
|
|
84
100
|
|
|
85
101
|
const normalizeEventPart = (part: AdkEventPart): AdkEventPart => {
|
|
@@ -299,16 +315,13 @@ export class AdkEventAccumulator {
|
|
|
299
315
|
if (part.text != null && !part.thought) {
|
|
300
316
|
humanParts.push({ type: "text", text: part.text });
|
|
301
317
|
} else if (part.inlineData) {
|
|
302
|
-
humanParts.push(
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
data: part.inlineData.data,
|
|
306
|
-
});
|
|
318
|
+
humanParts.push(
|
|
319
|
+
inlineDataToPart(part.inlineData.mimeType, part.inlineData.data),
|
|
320
|
+
);
|
|
307
321
|
} else if (part.fileData) {
|
|
308
|
-
humanParts.push(
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
});
|
|
322
|
+
humanParts.push(
|
|
323
|
+
fileDataToPart(part.fileData.fileUri, part.fileData.mimeType),
|
|
324
|
+
);
|
|
312
325
|
}
|
|
313
326
|
}
|
|
314
327
|
if (humanParts.length > 0) {
|
|
@@ -495,24 +508,21 @@ export class AdkEventAccumulator {
|
|
|
495
508
|
return;
|
|
496
509
|
}
|
|
497
510
|
|
|
498
|
-
// Inline data (images etc)
|
|
499
511
|
if (part.inlineData) {
|
|
500
512
|
const msg = this.getOrCreateAiMessage(event);
|
|
501
|
-
this.appendContent(
|
|
502
|
-
|
|
503
|
-
mimeType
|
|
504
|
-
|
|
505
|
-
});
|
|
513
|
+
this.appendContent(
|
|
514
|
+
msg,
|
|
515
|
+
inlineDataToPart(part.inlineData.mimeType, part.inlineData.data),
|
|
516
|
+
);
|
|
506
517
|
return;
|
|
507
518
|
}
|
|
508
519
|
|
|
509
|
-
// File data (URI reference)
|
|
510
520
|
if (part.fileData) {
|
|
511
521
|
const msg = this.getOrCreateAiMessage(event);
|
|
512
|
-
this.appendContent(
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
522
|
+
this.appendContent(
|
|
523
|
+
msg,
|
|
524
|
+
fileDataToPart(part.fileData.fileUri, part.fileData.mimeType),
|
|
525
|
+
);
|
|
516
526
|
}
|
|
517
527
|
}
|
|
518
528
|
|
|
@@ -126,7 +126,7 @@ describe("createAdkSessionAdapter - initialize", () => {
|
|
|
126
126
|
});
|
|
127
127
|
expect(JSON.parse(init?.body as string)).toEqual({});
|
|
128
128
|
expect(result).toMatchObject({
|
|
129
|
-
remoteId: "
|
|
129
|
+
remoteId: "new-session-1",
|
|
130
130
|
externalId: "new-session-1",
|
|
131
131
|
});
|
|
132
132
|
});
|
package/src/AdkSessionAdapter.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AssistantStream, AssistantStreamChunk } from "assistant-stream";
|
|
1
|
+
import type { AssistantStream, AssistantStreamChunk } from "assistant-stream";
|
|
2
2
|
import type {
|
|
3
3
|
RemoteThreadInitializeResponse,
|
|
4
4
|
RemoteThreadListAdapter,
|
|
@@ -112,7 +112,7 @@ export function createAdkSessionAdapter(
|
|
|
112
112
|
},
|
|
113
113
|
|
|
114
114
|
async initialize(
|
|
115
|
-
|
|
115
|
+
_threadId: string,
|
|
116
116
|
): Promise<RemoteThreadInitializeResponse> {
|
|
117
117
|
const headers = await getHeaders();
|
|
118
118
|
const res = await fetch(baseUrl, {
|
|
@@ -124,7 +124,7 @@ export function createAdkSessionAdapter(
|
|
|
124
124
|
throw new Error(`Failed to create session: ${res.status}`);
|
|
125
125
|
}
|
|
126
126
|
const session = (await res.json()) as { id: string };
|
|
127
|
-
return { remoteId:
|
|
127
|
+
return { remoteId: session.id, externalId: session.id };
|
|
128
128
|
},
|
|
129
129
|
|
|
130
130
|
async delete(remoteId: string): Promise<void> {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { AdkEventPart, AdkMessage, AdkMessageContentPart } from "./types";
|
|
2
|
+
|
|
3
|
+
export const contentToParts = (
|
|
4
|
+
content: AdkMessage["content"],
|
|
5
|
+
): AdkEventPart[] => {
|
|
6
|
+
if (typeof content === "string") return [{ text: content }];
|
|
7
|
+
return (content as AdkMessageContentPart[]).map((part): AdkEventPart => {
|
|
8
|
+
switch (part.type) {
|
|
9
|
+
case "text":
|
|
10
|
+
return { text: part.text };
|
|
11
|
+
case "reasoning":
|
|
12
|
+
return { text: part.text, thought: true };
|
|
13
|
+
case "image":
|
|
14
|
+
return { inlineData: { mimeType: part.mimeType, data: part.data } };
|
|
15
|
+
case "image_url":
|
|
16
|
+
return { fileData: { fileUri: part.url } };
|
|
17
|
+
case "file":
|
|
18
|
+
return { inlineData: { mimeType: part.mimeType, data: part.data } };
|
|
19
|
+
case "file_url":
|
|
20
|
+
return {
|
|
21
|
+
fileData: {
|
|
22
|
+
fileUri: part.url,
|
|
23
|
+
...(part.mimeType != null && { mimeType: part.mimeType }),
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
case "code":
|
|
27
|
+
return {
|
|
28
|
+
executableCode: { code: part.code, language: part.language },
|
|
29
|
+
};
|
|
30
|
+
case "code_result":
|
|
31
|
+
return {
|
|
32
|
+
codeExecutionResult: { output: part.output, outcome: part.outcome },
|
|
33
|
+
};
|
|
34
|
+
default:
|
|
35
|
+
return { text: "" };
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
};
|