@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
|
@@ -78,6 +78,59 @@ describe("convertAdkMessage - ai messages", () => {
|
|
|
78
78
|
});
|
|
79
79
|
});
|
|
80
80
|
|
|
81
|
+
it("converts file content parts to file message parts", () => {
|
|
82
|
+
const msg: AdkMessage = {
|
|
83
|
+
id: "m1",
|
|
84
|
+
type: "ai",
|
|
85
|
+
content: [
|
|
86
|
+
{
|
|
87
|
+
type: "file",
|
|
88
|
+
mimeType: "application/pdf",
|
|
89
|
+
data: "JVBERi0xLjQK",
|
|
90
|
+
filename: "report.pdf",
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
};
|
|
94
|
+
const result = convertAdkMessage(msg);
|
|
95
|
+
expect(result).toMatchObject({
|
|
96
|
+
content: [
|
|
97
|
+
{
|
|
98
|
+
type: "file",
|
|
99
|
+
mimeType: "application/pdf",
|
|
100
|
+
data: "JVBERi0xLjQK",
|
|
101
|
+
filename: "report.pdf",
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("converts file_url content parts to data parts", () => {
|
|
108
|
+
const msg: AdkMessage = {
|
|
109
|
+
id: "m1",
|
|
110
|
+
type: "ai",
|
|
111
|
+
content: [
|
|
112
|
+
{
|
|
113
|
+
type: "file_url",
|
|
114
|
+
url: "gs://bucket/report.pdf",
|
|
115
|
+
mimeType: "application/pdf",
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
};
|
|
119
|
+
const result = convertAdkMessage(msg);
|
|
120
|
+
expect(result).toMatchObject({
|
|
121
|
+
content: [
|
|
122
|
+
{
|
|
123
|
+
type: "data",
|
|
124
|
+
name: "file_url",
|
|
125
|
+
data: {
|
|
126
|
+
url: "gs://bucket/report.pdf",
|
|
127
|
+
mimeType: "application/pdf",
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
81
134
|
it("converts code content parts to data parts", () => {
|
|
82
135
|
const msg: AdkMessage = {
|
|
83
136
|
id: "m1",
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import type { ToolCallMessagePart } from "@assistant-ui/core";
|
|
4
|
-
import { useExternalMessageConverter } from "@assistant-ui/core/react";
|
|
4
|
+
import type { useExternalMessageConverter } from "@assistant-ui/core/react";
|
|
5
5
|
import type { AdkMessage, AdkMessageContentPart } from "./types";
|
|
6
6
|
|
|
7
7
|
type ContentPart =
|
|
8
8
|
| { type: "text"; text: string }
|
|
9
9
|
| { type: "reasoning"; text: string }
|
|
10
10
|
| { type: "image"; image: string }
|
|
11
|
+
| { type: "file"; data: string; mimeType: string; filename?: string }
|
|
11
12
|
| { type: "data"; name: string; data: unknown };
|
|
12
13
|
|
|
13
14
|
const contentToParts = (content: AdkMessage["content"]): ContentPart[] => {
|
|
@@ -28,6 +29,22 @@ const contentToParts = (content: AdkMessage["content"]): ContentPart[] => {
|
|
|
28
29
|
};
|
|
29
30
|
case "image_url":
|
|
30
31
|
return { type: "image", image: part.url };
|
|
32
|
+
case "file":
|
|
33
|
+
return {
|
|
34
|
+
type: "file",
|
|
35
|
+
data: part.data,
|
|
36
|
+
mimeType: part.mimeType,
|
|
37
|
+
...(part.filename != null && { filename: part.filename }),
|
|
38
|
+
};
|
|
39
|
+
case "file_url":
|
|
40
|
+
return {
|
|
41
|
+
type: "data",
|
|
42
|
+
name: "file_url",
|
|
43
|
+
data: {
|
|
44
|
+
url: part.url,
|
|
45
|
+
...(part.mimeType != null && { mimeType: part.mimeType }),
|
|
46
|
+
},
|
|
47
|
+
};
|
|
31
48
|
case "code":
|
|
32
49
|
return {
|
|
33
50
|
type: "data",
|
package/src/types.ts
CHANGED
|
@@ -109,6 +109,17 @@ export type AdkMessageContentPart =
|
|
|
109
109
|
| { type: "reasoning"; text: string }
|
|
110
110
|
| { type: "image"; mimeType: string; data: string }
|
|
111
111
|
| { type: "image_url"; url: string }
|
|
112
|
+
| {
|
|
113
|
+
type: "file";
|
|
114
|
+
mimeType: string;
|
|
115
|
+
data: string;
|
|
116
|
+
filename?: string | undefined;
|
|
117
|
+
}
|
|
118
|
+
| {
|
|
119
|
+
type: "file_url";
|
|
120
|
+
url: string;
|
|
121
|
+
mimeType?: string | undefined;
|
|
122
|
+
}
|
|
112
123
|
| { type: "code"; code: string; language: string }
|
|
113
124
|
| { type: "code_result"; output: string; outcome: string }
|
|
114
125
|
| { type: "activity"; message: string };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { messageToEvent } from "./useAdkMessages";
|
|
3
|
+
import type { AdkMessage } from "./types";
|
|
4
|
+
|
|
5
|
+
describe("messageToEvent (contentToParts)", () => {
|
|
6
|
+
it("serializes a file content part as inlineData", () => {
|
|
7
|
+
const msg: AdkMessage = {
|
|
8
|
+
id: "m1",
|
|
9
|
+
type: "human",
|
|
10
|
+
content: [
|
|
11
|
+
{
|
|
12
|
+
type: "file",
|
|
13
|
+
mimeType: "application/pdf",
|
|
14
|
+
data: "JVBERi0xLjQK",
|
|
15
|
+
filename: "report.pdf",
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
};
|
|
19
|
+
const event = messageToEvent(msg);
|
|
20
|
+
expect(event.content?.parts).toEqual([
|
|
21
|
+
{ inlineData: { mimeType: "application/pdf", data: "JVBERi0xLjQK" } },
|
|
22
|
+
]);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("serializes a file_url content part as fileData with mimeType", () => {
|
|
26
|
+
const msg: AdkMessage = {
|
|
27
|
+
id: "m1",
|
|
28
|
+
type: "human",
|
|
29
|
+
content: [
|
|
30
|
+
{
|
|
31
|
+
type: "file_url",
|
|
32
|
+
url: "gs://bucket/report.pdf",
|
|
33
|
+
mimeType: "application/pdf",
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
};
|
|
37
|
+
const event = messageToEvent(msg);
|
|
38
|
+
expect(event.content?.parts).toEqual([
|
|
39
|
+
{
|
|
40
|
+
fileData: {
|
|
41
|
+
fileUri: "gs://bucket/report.pdf",
|
|
42
|
+
mimeType: "application/pdf",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
]);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("serializes a file_url without mimeType as bare fileData", () => {
|
|
49
|
+
const msg: AdkMessage = {
|
|
50
|
+
id: "m1",
|
|
51
|
+
type: "human",
|
|
52
|
+
content: [{ type: "file_url", url: "gs://bucket/unknown" }],
|
|
53
|
+
};
|
|
54
|
+
const event = messageToEvent(msg);
|
|
55
|
+
expect(event.content?.parts).toEqual([
|
|
56
|
+
{ fileData: { fileUri: "gs://bucket/unknown" } },
|
|
57
|
+
]);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("serializes mixed text + file content as multiple parts", () => {
|
|
61
|
+
const msg: AdkMessage = {
|
|
62
|
+
id: "m1",
|
|
63
|
+
type: "human",
|
|
64
|
+
content: [
|
|
65
|
+
{ type: "text", text: "see attached" },
|
|
66
|
+
{ type: "file", mimeType: "image/png", data: "AAAA" },
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
const event = messageToEvent(msg);
|
|
70
|
+
expect(event.content?.parts).toEqual([
|
|
71
|
+
{ text: "see attached" },
|
|
72
|
+
{ inlineData: { mimeType: "image/png", data: "AAAA" } },
|
|
73
|
+
]);
|
|
74
|
+
});
|
|
75
|
+
});
|
package/src/useAdkMessages.ts
CHANGED
|
@@ -3,11 +3,10 @@ import { useState, useCallback, useRef, useMemo } from "react";
|
|
|
3
3
|
import { v4 as uuidv4 } from "uuid";
|
|
4
4
|
import { useAui } from "@assistant-ui/store";
|
|
5
5
|
import { AdkEventAccumulator } from "./AdkEventAccumulator";
|
|
6
|
+
import { contentToParts } from "./contentToParts";
|
|
6
7
|
import type {
|
|
7
8
|
AdkEvent,
|
|
8
|
-
AdkEventPart,
|
|
9
9
|
AdkMessage,
|
|
10
|
-
AdkMessageContentPart,
|
|
11
10
|
AdkMessageMetadata,
|
|
12
11
|
AdkSendMessageConfig,
|
|
13
12
|
AdkStreamCallback,
|
|
@@ -200,7 +199,8 @@ export const useAdkMessages = ({
|
|
|
200
199
|
};
|
|
201
200
|
};
|
|
202
201
|
|
|
203
|
-
|
|
202
|
+
/** @internal — exported for unit tests. */
|
|
203
|
+
export const messageToEvent = (msg: AdkMessage): AdkEvent => {
|
|
204
204
|
if (msg.type === "human") {
|
|
205
205
|
return {
|
|
206
206
|
id: msg.id ?? uuidv4(),
|
|
@@ -246,31 +246,3 @@ const messageToEvent = (msg: AdkMessage): AdkEvent => {
|
|
|
246
246
|
};
|
|
247
247
|
return result;
|
|
248
248
|
};
|
|
249
|
-
|
|
250
|
-
const contentToParts = (
|
|
251
|
-
content: string | AdkMessageContentPart[],
|
|
252
|
-
): AdkEventPart[] => {
|
|
253
|
-
if (typeof content === "string") return [{ text: content }];
|
|
254
|
-
return content.map((part) => {
|
|
255
|
-
switch (part.type) {
|
|
256
|
-
case "text":
|
|
257
|
-
return { text: part.text };
|
|
258
|
-
case "reasoning":
|
|
259
|
-
return { text: part.text, thought: true };
|
|
260
|
-
case "image":
|
|
261
|
-
return { inlineData: { mimeType: part.mimeType, data: part.data } };
|
|
262
|
-
case "image_url":
|
|
263
|
-
return { fileData: { fileUri: part.url } };
|
|
264
|
-
case "code":
|
|
265
|
-
return {
|
|
266
|
-
executableCode: { code: part.code, language: part.language },
|
|
267
|
-
};
|
|
268
|
-
case "code_result":
|
|
269
|
-
return {
|
|
270
|
-
codeExecutionResult: { output: part.output, outcome: part.outcome },
|
|
271
|
-
};
|
|
272
|
-
default:
|
|
273
|
-
return { text: "" };
|
|
274
|
-
}
|
|
275
|
-
});
|
|
276
|
-
};
|
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
getMessageContent,
|
|
4
|
+
getPendingCancellations,
|
|
5
|
+
getPendingToolCalls,
|
|
6
|
+
} from "./useAdkRuntime";
|
|
7
|
+
import type { AppendMessage } from "@assistant-ui/core";
|
|
3
8
|
import type { AdkMessage } from "./types";
|
|
4
9
|
|
|
10
|
+
const makeAppendMessage = (content: AppendMessage["content"]): AppendMessage =>
|
|
11
|
+
({
|
|
12
|
+
role: "user",
|
|
13
|
+
content,
|
|
14
|
+
attachments: [],
|
|
15
|
+
parentId: null,
|
|
16
|
+
sourceId: null,
|
|
17
|
+
runConfig: undefined,
|
|
18
|
+
metadata: { custom: {} },
|
|
19
|
+
}) as unknown as AppendMessage;
|
|
20
|
+
|
|
5
21
|
const aiWithToolCalls = (
|
|
6
22
|
id: string,
|
|
7
23
|
toolCalls: Array<{ id: string; name: string }>,
|
|
@@ -136,3 +152,60 @@ describe("getPendingCancellations", () => {
|
|
|
136
152
|
});
|
|
137
153
|
});
|
|
138
154
|
});
|
|
155
|
+
|
|
156
|
+
describe("getMessageContent", () => {
|
|
157
|
+
it("preserves file part data and mimeType end-to-end", () => {
|
|
158
|
+
const result = getMessageContent(
|
|
159
|
+
makeAppendMessage([
|
|
160
|
+
{ type: "text", text: "see attached" },
|
|
161
|
+
{
|
|
162
|
+
type: "file",
|
|
163
|
+
mimeType: "application/pdf",
|
|
164
|
+
data: "JVBERi0xLjQK",
|
|
165
|
+
filename: "report.pdf",
|
|
166
|
+
},
|
|
167
|
+
]),
|
|
168
|
+
);
|
|
169
|
+
expect(result).toEqual([
|
|
170
|
+
{ type: "text", text: "see attached" },
|
|
171
|
+
{
|
|
172
|
+
type: "file",
|
|
173
|
+
mimeType: "application/pdf",
|
|
174
|
+
data: "JVBERi0xLjQK",
|
|
175
|
+
filename: "report.pdf",
|
|
176
|
+
},
|
|
177
|
+
]);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("keeps file-only content as an array (does not collapse to a text marker)", () => {
|
|
181
|
+
const result = getMessageContent(
|
|
182
|
+
makeAppendMessage([
|
|
183
|
+
{
|
|
184
|
+
type: "file",
|
|
185
|
+
mimeType: "image/png",
|
|
186
|
+
data: "AAAA",
|
|
187
|
+
filename: "x.png",
|
|
188
|
+
},
|
|
189
|
+
]),
|
|
190
|
+
);
|
|
191
|
+
expect(result).toEqual([
|
|
192
|
+
{
|
|
193
|
+
type: "file",
|
|
194
|
+
mimeType: "image/png",
|
|
195
|
+
data: "AAAA",
|
|
196
|
+
filename: "x.png",
|
|
197
|
+
},
|
|
198
|
+
]);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it("omits filename when not provided", () => {
|
|
202
|
+
const result = getMessageContent(
|
|
203
|
+
makeAppendMessage([
|
|
204
|
+
{ type: "file", mimeType: "application/pdf", data: "AAAA" },
|
|
205
|
+
]),
|
|
206
|
+
);
|
|
207
|
+
expect(result).toEqual([
|
|
208
|
+
{ type: "file", mimeType: "application/pdf", data: "AAAA" },
|
|
209
|
+
]);
|
|
210
|
+
});
|
|
211
|
+
});
|
package/src/useAdkRuntime.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { useEffect, useRef, useState } from "react";
|
|
|
3
3
|
import {
|
|
4
4
|
getExternalStoreMessages,
|
|
5
5
|
type AttachmentAdapter,
|
|
6
|
+
type DictationAdapter,
|
|
6
7
|
type FeedbackAdapter,
|
|
7
8
|
type SpeechSynthesisAdapter,
|
|
8
9
|
type AppendMessage,
|
|
@@ -32,7 +33,8 @@ import { convertAdkMessage } from "./convertAdkMessages";
|
|
|
32
33
|
import { symbolAdkRuntimeExtras, type AdkRuntimeExtras } from "./hooks";
|
|
33
34
|
import { v4 as uuidv4 } from "uuid";
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
/** @internal — exported for unit tests. */
|
|
37
|
+
export const getMessageContent = (msg: AppendMessage) => {
|
|
36
38
|
const allContent = [
|
|
37
39
|
...msg.content,
|
|
38
40
|
...(msg.attachments?.flatMap((a) => a.content) ?? []),
|
|
@@ -46,19 +48,22 @@ const getMessageContent = (msg: AppendMessage) => {
|
|
|
46
48
|
return { type: "image_url" as const, url: part.image };
|
|
47
49
|
case "file":
|
|
48
50
|
return {
|
|
49
|
-
type: "
|
|
50
|
-
|
|
51
|
+
type: "file" as const,
|
|
52
|
+
mimeType: part.mimeType,
|
|
53
|
+
data: part.data,
|
|
54
|
+
...(part.filename != null && { filename: part.filename }),
|
|
51
55
|
};
|
|
52
56
|
|
|
53
57
|
case "tool-call":
|
|
54
58
|
throw new Error("Tool call appends are not supported.");
|
|
55
59
|
|
|
56
|
-
default:
|
|
60
|
+
default: {
|
|
57
61
|
const _exhaustiveCheck: "reasoning" | "source" | "audio" | "data" =
|
|
58
62
|
type;
|
|
59
63
|
throw new Error(
|
|
60
64
|
`Unsupported append message part type: ${_exhaustiveCheck}`,
|
|
61
65
|
);
|
|
66
|
+
}
|
|
62
67
|
}
|
|
63
68
|
});
|
|
64
69
|
|
|
@@ -143,6 +148,7 @@ export type UseAdkRuntimeOptions = {
|
|
|
143
148
|
| {
|
|
144
149
|
attachments?: AttachmentAdapter;
|
|
145
150
|
speech?: SpeechSynthesisAdapter;
|
|
151
|
+
dictation?: DictationAdapter;
|
|
146
152
|
feedback?: FeedbackAdapter;
|
|
147
153
|
}
|
|
148
154
|
| undefined;
|
|
@@ -163,13 +169,14 @@ export type UseAdkRuntimeOptions = {
|
|
|
163
169
|
|
|
164
170
|
const useAdkRuntimeImpl = ({
|
|
165
171
|
autoCancelPendingToolCalls,
|
|
166
|
-
adapters: { attachments, feedback, speech } = {},
|
|
172
|
+
adapters: { attachments, dictation, feedback, speech } = {},
|
|
167
173
|
unstable_allowCancellation,
|
|
168
174
|
stream,
|
|
169
175
|
load,
|
|
170
176
|
getCheckpointId,
|
|
171
177
|
eventHandlers,
|
|
172
178
|
}: UseAdkRuntimeOptions) => {
|
|
179
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
173
180
|
const aui = useAui();
|
|
174
181
|
const {
|
|
175
182
|
messages,
|
|
@@ -184,12 +191,15 @@ const useAdkRuntimeImpl = ({
|
|
|
184
191
|
sendMessage,
|
|
185
192
|
cancel,
|
|
186
193
|
replaceMessages,
|
|
194
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
187
195
|
} = useAdkMessages({
|
|
188
196
|
stream,
|
|
189
197
|
...(eventHandlers && { eventHandlers }),
|
|
190
198
|
});
|
|
191
199
|
|
|
200
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
192
201
|
const [isRunning, setIsRunning] = useState(false);
|
|
202
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
193
203
|
const [toolStatuses, setToolStatuses] = useState<
|
|
194
204
|
Record<string, ToolExecutionStatus>
|
|
195
205
|
>({});
|
|
@@ -210,21 +220,25 @@ const useAdkRuntimeImpl = ({
|
|
|
210
220
|
}
|
|
211
221
|
};
|
|
212
222
|
|
|
223
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
213
224
|
const threadMessages = useExternalMessageConverter({
|
|
214
225
|
callback: convertAdkMessage,
|
|
215
226
|
messages,
|
|
216
227
|
isRunning: effectiveIsRunning,
|
|
217
228
|
});
|
|
218
229
|
|
|
230
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
219
231
|
const threadMessagesRef = useRef(threadMessages);
|
|
220
232
|
threadMessagesRef.current = threadMessages;
|
|
221
233
|
|
|
234
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
222
235
|
const [runtimeRef] = useState(() => ({
|
|
223
236
|
get current() {
|
|
224
237
|
return runtime;
|
|
225
238
|
},
|
|
226
239
|
}));
|
|
227
240
|
|
|
241
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
228
242
|
const toolInvocations = useToolInvocations({
|
|
229
243
|
state: { messages: threadMessages, isRunning: effectiveIsRunning },
|
|
230
244
|
getTools: () => runtimeRef.current.thread.getModelContext().tools,
|
|
@@ -248,10 +262,11 @@ const useAdkRuntimeImpl = ({
|
|
|
248
262
|
setToolStatuses,
|
|
249
263
|
});
|
|
250
264
|
|
|
265
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
251
266
|
const runtime = useExternalStoreRuntime({
|
|
252
267
|
isRunning: effectiveIsRunning,
|
|
253
268
|
messages: threadMessages,
|
|
254
|
-
adapters: { attachments, feedback, speech },
|
|
269
|
+
adapters: { attachments, dictation, feedback, speech },
|
|
255
270
|
extras: {
|
|
256
271
|
[symbolAdkRuntimeExtras]: true,
|
|
257
272
|
agentInfo,
|
|
@@ -362,11 +377,14 @@ const useAdkRuntimeImpl = ({
|
|
|
362
377
|
});
|
|
363
378
|
|
|
364
379
|
{
|
|
380
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
365
381
|
const loadRef = useRef(load);
|
|
382
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
366
383
|
useEffect(() => {
|
|
367
384
|
loadRef.current = load;
|
|
368
385
|
});
|
|
369
386
|
|
|
387
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
370
388
|
useEffect(() => {
|
|
371
389
|
const loadFn = loadRef.current;
|
|
372
390
|
if (!loadFn) return;
|
|
@@ -410,6 +428,7 @@ export const useAdkRuntime = ({
|
|
|
410
428
|
|
|
411
429
|
return useRemoteThreadListRuntime({
|
|
412
430
|
runtimeHook: function RuntimeHook() {
|
|
431
|
+
// biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
|
|
413
432
|
return useAdkRuntimeImpl(options);
|
|
414
433
|
},
|
|
415
434
|
adapter,
|