@assistant-ui/react-google-adk 0.0.30 → 0.0.32
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 +26 -29
- package/dist/AdkClient.d.ts.map +1 -1
- package/dist/AdkClient.js +5 -3
- package/dist/AdkClient.js.map +1 -1
- package/dist/AdkEventAccumulator.d.ts +41 -45
- package/dist/AdkEventAccumulator.d.ts.map +1 -1
- package/dist/AdkEventAccumulator.js +63 -99
- package/dist/AdkEventAccumulator.js.map +1 -1
- package/dist/AdkSessionAdapter.d.ts +41 -39
- package/dist/AdkSessionAdapter.d.ts.map +1 -1
- package/dist/AdkSessionAdapter.js +11 -7
- package/dist/AdkSessionAdapter.js.map +1 -1
- package/dist/adkAuthRequest.d.ts +17 -0
- package/dist/adkAuthRequest.d.ts.map +1 -0
- package/dist/adkAuthRequest.js +45 -0
- package/dist/adkAuthRequest.js.map +1 -0
- package/dist/adkExtras.d.ts +2 -5
- package/dist/adkExtras.d.ts.map +1 -1
- package/dist/adkToolApproval.d.ts +18 -21
- package/dist/adkToolApproval.d.ts.map +1 -1
- package/dist/adkToolApproval.js +1 -3
- package/dist/adkToolApproval.js.map +1 -1
- package/dist/contentToParts.d.ts +2 -5
- package/dist/contentToParts.d.ts.map +1 -1
- package/dist/convertAdkMessages.d.ts +5 -8
- package/dist/convertAdkMessages.d.ts.map +1 -1
- package/dist/convertAdkMessages.js +4 -3
- package/dist/convertAdkMessages.js.map +1 -1
- package/dist/convertToAdkMessages.d.ts +36 -39
- package/dist/convertToAdkMessages.d.ts.map +1 -1
- package/dist/hooks.d.ts +25 -23
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +12 -10
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +11 -10
- package/dist/index.d.ts.map +1 -0
- package/dist/normalizeAdkPart.d.ts +2 -0
- package/dist/normalizeAdkPart.d.ts.map +1 -0
- package/dist/normalizeAdkPart.js +31 -0
- package/dist/normalizeAdkPart.js.map +1 -0
- package/dist/parseAdkEvent.d.ts +2 -5
- package/dist/parseAdkEvent.d.ts.map +1 -1
- package/dist/raceWithAbortSignal.d.ts +2 -0
- package/dist/raceWithAbortSignal.d.ts.map +1 -0
- package/dist/raceWithAbortSignal.js +45 -0
- package/dist/raceWithAbortSignal.js.map +1 -0
- package/dist/sdkIdentity.d.ts +2 -5
- package/dist/sdkIdentity.d.ts.map +1 -1
- package/dist/sdkIdentity.js +1 -1
- package/dist/server/adkEventStream.d.ts +25 -27
- package/dist/server/adkEventStream.d.ts.map +1 -1
- package/dist/server/adkEventStream.js +23 -15
- package/dist/server/adkEventStream.js.map +1 -1
- package/dist/server/createAdkApiRoute.d.ts +23 -25
- package/dist/server/createAdkApiRoute.d.ts.map +1 -1
- package/dist/server/index.d.ts +4 -4
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/parseAdkRequest.d.ts +18 -20
- package/dist/server/parseAdkRequest.d.ts.map +1 -1
- package/dist/structuredEvents.d.ts +2 -5
- package/dist/structuredEvents.d.ts.map +1 -1
- package/dist/structuredEvents.js +1 -1
- package/dist/structuredEvents.js.map +1 -1
- package/dist/toAdkFunctionResponse.d.ts +2 -5
- package/dist/toAdkFunctionResponse.d.ts.map +1 -1
- package/dist/trimTrailingSlashes.d.ts +1 -4
- package/dist/trimTrailingSlashes.d.ts.map +1 -1
- package/dist/types.d.ts +253 -256
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/useAdkMessages.d.ts +26 -29
- package/dist/useAdkMessages.d.ts.map +1 -1
- package/dist/useAdkMessages.js +2 -0
- package/dist/useAdkMessages.js.map +1 -1
- package/dist/useAdkRuntime.d.ts +50 -52
- package/dist/useAdkRuntime.d.ts.map +1 -1
- package/dist/useAdkRuntime.js +1 -1
- package/package.json +10 -9
- package/src/AdkClient.test.ts +50 -0
- package/src/AdkClient.ts +10 -3
- package/src/AdkEventAccumulator.test.ts +312 -11
- package/src/AdkEventAccumulator.ts +68 -142
- package/src/AdkSessionAdapter.test.ts +284 -1
- package/src/AdkSessionAdapter.ts +32 -8
- package/src/adkAuthRequest.test.ts +101 -0
- package/src/adkAuthRequest.ts +50 -0
- package/src/adkToolApproval.test.ts +0 -4
- package/src/adkToolApproval.ts +1 -3
- package/src/convertAdkMessages.test.ts +41 -0
- package/src/convertAdkMessages.ts +19 -7
- package/src/hooks.render.test.tsx +95 -2
- package/src/hooks.ts +12 -13
- package/src/normalizeAdkPart.ts +35 -0
- package/src/raceWithAbortSignal.test.ts +73 -0
- package/src/raceWithAbortSignal.ts +48 -0
- package/src/server/adkEventStream.test.ts +147 -0
- package/src/server/adkEventStream.ts +27 -20
- package/src/structuredEvents.test.ts +69 -0
- package/src/structuredEvents.ts +4 -1
- package/src/types.ts +1 -1
- package/src/useAdkMessages.test.ts +102 -3
- package/src/useAdkMessages.ts +2 -0
- package/src/useAdkRuntime.replacement.test.tsx +11 -7
package/dist/AdkClient.d.ts
CHANGED
|
@@ -1,29 +1,28 @@
|
|
|
1
|
-
import { AdkStreamCallback } from "./types.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>) | undefined;
|
|
1
|
+
import type { AdkStreamCallback } from "./types.js";
|
|
2
|
+
export type CreateAdkStreamOptions = {
|
|
3
|
+
/**
|
|
4
|
+
* URL to POST to. Either a proxy route (e.g. "/api/adk") or
|
|
5
|
+
* an ADK server base URL (e.g. "http://localhost:8000").
|
|
6
|
+
*
|
|
7
|
+
* When `appName` and `userId` are provided, POSTs to `${api}/run_sse`
|
|
8
|
+
* in ADK-native format. Otherwise POSTs directly to `api` in proxy format
|
|
9
|
+
* (compatible with `parseAdkRequest`).
|
|
10
|
+
*/
|
|
11
|
+
api: string;
|
|
12
|
+
/**
|
|
13
|
+
* ADK application name. When provided along with `userId`,
|
|
14
|
+
* enables direct connection to an ADK server.
|
|
15
|
+
*/
|
|
16
|
+
appName?: string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* ADK user ID. Required when `appName` is provided.
|
|
19
|
+
*/
|
|
20
|
+
userId?: string | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Extra headers to send with every request.
|
|
23
|
+
* Can be a static object or an async function for dynamic auth tokens.
|
|
24
|
+
*/
|
|
25
|
+
headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>) | undefined;
|
|
27
26
|
};
|
|
28
27
|
/**
|
|
29
28
|
* Creates an `AdkStreamCallback` that connects to an ADK endpoint.
|
|
@@ -42,7 +41,5 @@ type CreateAdkStreamOptions = {
|
|
|
42
41
|
* });
|
|
43
42
|
* ```
|
|
44
43
|
*/
|
|
45
|
-
declare function createAdkStream(options: CreateAdkStreamOptions): AdkStreamCallback;
|
|
46
|
-
//#endregion
|
|
47
|
-
export { CreateAdkStreamOptions, createAdkStream };
|
|
44
|
+
export declare function createAdkStream(options: CreateAdkStreamOptions): AdkStreamCallback;
|
|
48
45
|
//# sourceMappingURL=AdkClient.d.ts.map
|
package/dist/AdkClient.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdkClient.d.ts","
|
|
1
|
+
{"version":3,"file":"AdkClient.d.ts","sourceRoot":"","sources":["../src/AdkClient.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAIV,iBAAiB,EAClB,mBAAgB;AAEjB,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;;;;;OAOG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE7B;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE5B;;;OAGG;IACH,OAAO,CAAC,EACJ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtB,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAChE,SAAS,CAAC;CACf,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,sBAAsB,GAC9B,iBAAiB,CAsDnB"}
|
package/dist/AdkClient.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { contentToParts } from "./contentToParts.js";
|
|
2
2
|
import { parseAdkEventValue } from "./parseAdkEvent.js";
|
|
3
|
+
import { raceWithAbortSignal } from "./raceWithAbortSignal.js";
|
|
3
4
|
import { toAdkFunctionResponse } from "./toAdkFunctionResponse.js";
|
|
4
5
|
import { trimTrailingSlashes } from "./trimTrailingSlashes.js";
|
|
5
6
|
import { SSEEventDecoder } from "assistant-stream/utils";
|
|
@@ -26,7 +27,7 @@ function createAdkStream(options) {
|
|
|
26
27
|
const isDirect = options.appName != null;
|
|
27
28
|
if (isDirect && (options.userId == null || options.userId === "")) throw new Error("createAdkStream direct mode requires \"userId\" when \"appName\" is provided.");
|
|
28
29
|
return async function* (messages, config) {
|
|
29
|
-
const headers = await resolveHeaders(options.headers);
|
|
30
|
+
const headers = await resolveHeaders(options.headers, config.abortSignal);
|
|
30
31
|
let url;
|
|
31
32
|
let body;
|
|
32
33
|
if (isDirect) {
|
|
@@ -75,9 +76,9 @@ function parseAdkEvent(data) {
|
|
|
75
76
|
}
|
|
76
77
|
return parseAdkEventValue(value, "Invalid ADK stream event");
|
|
77
78
|
}
|
|
78
|
-
async function resolveHeaders(headers) {
|
|
79
|
+
async function resolveHeaders(headers, signal) {
|
|
79
80
|
if (!headers) return {};
|
|
80
|
-
if (typeof headers === "function") return await headers
|
|
81
|
+
if (typeof headers === "function") return await raceWithAbortSignal(signal, headers);
|
|
81
82
|
return headers;
|
|
82
83
|
}
|
|
83
84
|
/**
|
|
@@ -144,6 +145,7 @@ function messagesToProxyBody(messages, config) {
|
|
|
144
145
|
return body;
|
|
145
146
|
}
|
|
146
147
|
async function* parseSSEResponse(response) {
|
|
148
|
+
if (!response.body) throw new Error("Expected ADK stream response body, received no body");
|
|
147
149
|
const reader = response.body.getReader();
|
|
148
150
|
const decoder = new TextDecoder();
|
|
149
151
|
const sseDecoder = new SSEEventDecoder({ trailing: "dispatch" });
|
package/dist/AdkClient.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdkClient.js","names":[],"sources":["../src/AdkClient.ts"],"sourcesContent":["import { SSEEventDecoder } from \"assistant-stream/utils\";\nimport { contentToParts } from \"./contentToParts\";\nimport { parseAdkEventValue } from \"./parseAdkEvent\";\nimport { toAdkFunctionResponse } from \"./toAdkFunctionResponse\";\nimport { trimTrailingSlashes } from \"./trimTrailingSlashes\";\nimport type {\n AdkEvent,\n AdkEventPart,\n AdkMessage,\n AdkStreamCallback,\n} from \"./types\";\n\nexport type CreateAdkStreamOptions = {\n /**\n * URL to POST to. Either a proxy route (e.g. \"/api/adk\") or\n * an ADK server base URL (e.g. \"http://localhost:8000\").\n *\n * When `appName` and `userId` are provided, POSTs to `${api}/run_sse`\n * in ADK-native format. Otherwise POSTs directly to `api` in proxy format\n * (compatible with `parseAdkRequest`).\n */\n api: string;\n\n /**\n * ADK application name. When provided along with `userId`,\n * enables direct connection to an ADK server.\n */\n appName?: string | undefined;\n\n /**\n * ADK user ID. Required when `appName` is provided.\n */\n userId?: string | undefined;\n\n /**\n * Extra headers to send with every request.\n * Can be a static object or an async function for dynamic auth tokens.\n */\n headers?:\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>)\n | undefined;\n};\n\n/**\n * Creates an `AdkStreamCallback` that connects to an ADK endpoint.\n *\n * @example Proxy mode (with a Next.js API route)\n * ```ts\n * const stream = createAdkStream({ api: \"/api/adk\" });\n * ```\n *\n * @example Direct mode (connecting to ADK server)\n * ```ts\n * const stream = createAdkStream({\n * api: \"http://localhost:8000\",\n * appName: \"my-app\",\n * userId: \"user-1\",\n * });\n * ```\n */\nexport function createAdkStream(\n options: CreateAdkStreamOptions,\n): AdkStreamCallback {\n if (options.appName === \"\") {\n throw new Error(\n 'createAdkStream direct mode requires a non-empty \"appName\".',\n );\n }\n\n const isDirect = options.appName != null;\n if (isDirect && (options.userId == null || options.userId === \"\")) {\n throw new Error(\n 'createAdkStream direct mode requires \"userId\" when \"appName\" is provided.',\n );\n }\n\n return async function* (messages, config) {\n const headers = await resolveHeaders(options.headers);\n\n let url: string;\n let body: unknown;\n\n if (isDirect) {\n // Direct mode: POST to ADK server's /run_sse\n url = `${trimTrailingSlashes(options.api)}/run_sse`;\n const { externalId } = await config.initialize();\n body = {\n appName: options.appName,\n userId: options.userId,\n sessionId: externalId,\n newMessage: messagesToContent(messages),\n streaming: true,\n ...(config.stateDelta != null && { stateDelta: config.stateDelta }),\n };\n } else {\n // Proxy mode: POST in parseAdkRequest-compatible format\n url = options.api;\n body = messagesToProxyBody(messages, config);\n }\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...headers },\n body: JSON.stringify(body),\n signal: config.abortSignal,\n });\n\n if (!response.ok) {\n throw new Error(\n `ADK request failed: ${response.status} ${response.statusText}`,\n );\n }\n\n validateEventStreamContentType(response);\n yield* parseSSEResponse(response);\n };\n}\n\n// ── Internal helpers ──\n\nfunction validateEventStreamContentType(response: Response): void {\n const contentType = response.headers.get(\"Content-Type\");\n const mediaType = contentType?.split(\";\", 1)[0]?.trim().toLowerCase();\n if (mediaType !== \"text/event-stream\") {\n const received = contentType\n ? `\"${contentType}\"`\n : \"no Content-Type header\";\n void response.body?.cancel().catch(() => undefined);\n throw new Error(\n `Expected ADK stream response Content-Type \"text/event-stream\", received ${received}`,\n );\n }\n}\n\nfunction parseAdkEvent(data: string): AdkEvent {\n let value: unknown;\n try {\n value = JSON.parse(data);\n } catch {\n throw new Error(\"Invalid ADK stream event: expected valid JSON.\");\n }\n\n return parseAdkEventValue(value, \"Invalid ADK stream event\");\n}\n\nasync function resolveHeaders(\n headers:\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>)\n | undefined,\n): Promise<Record<string, string>> {\n if (!headers) return {};\n if (typeof headers === \"function\") return await headers();\n return headers;\n}\n\n/**\n * Converts AdkMessage[] (new messages) into ADK Content format\n * for the direct `/run_sse` endpoint.\n */\nfunction messagesToContent(messages: AdkMessage[]): {\n role: string;\n parts: AdkEventPart[];\n} {\n const parts: AdkEventPart[] = [];\n\n for (const msg of messages) {\n if (msg.type === \"human\") {\n for (const part of contentToParts(msg.content)) {\n parts.push(part);\n }\n } else if (msg.type === \"tool\") {\n let response: unknown;\n try {\n response = JSON.parse(msg.content);\n } catch {\n response = msg.content;\n }\n parts.push({\n functionResponse: {\n name: msg.name,\n id: msg.tool_call_id,\n response: toAdkFunctionResponse(response, msg.status === \"error\"),\n },\n });\n }\n }\n\n if (parts.length === 0) {\n parts.push({ text: \"\" });\n }\n\n return { role: \"user\", parts };\n}\n\n/**\n * Converts AdkMessage[] into the proxy request body format\n * (compatible with `parseAdkRequest`).\n */\nfunction messagesToProxyBody(\n messages: AdkMessage[],\n config: {\n runConfig?: unknown;\n checkpointId?: string | undefined;\n stateDelta?: Record<string, unknown> | undefined;\n },\n): Record<string, unknown> {\n const body: Record<string, unknown> = {};\n\n if (config.runConfig != null) body.runConfig = config.runConfig;\n if (config.checkpointId != null) body.checkpointId = config.checkpointId;\n if (config.stateDelta != null) body.stateDelta = config.stateDelta;\n\n // Check if there's a tool result\n const toolMsg = messages.find((m) => m.type === \"tool\");\n if (toolMsg && toolMsg.type === \"tool\") {\n // If there are also other messages (e.g. cancellations), send as parts\n if (messages.length > 1) {\n body.parts = messagesToContent(messages).parts;\n return body;\n }\n\n let result: unknown;\n try {\n result = JSON.parse(toolMsg.content);\n } catch {\n result = toolMsg.content;\n }\n body.type = \"tool-result\";\n body.toolCallId = toolMsg.tool_call_id;\n body.toolName = toolMsg.name;\n body.result = result;\n body.isError = toolMsg.status === \"error\";\n return body;\n }\n\n // Human message(s) - possibly with cancellation tool results prepended\n if (messages.length === 1 && messages[0]!.type === \"human\") {\n const msg = messages[0]!;\n if (typeof msg.content === \"string\") {\n body.message = msg.content;\n } else {\n body.parts = contentToParts(msg.content);\n }\n return body;\n }\n\n // Multiple messages (e.g. cancellations + human): send as parts array\n body.parts = messagesToContent(messages).parts;\n return body;\n}\n\nasync function* parseSSEResponse(response: Response): AsyncGenerator<AdkEvent> {\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n const sseDecoder = new SSEEventDecoder({ trailing: \"dispatch\" });\n\n let shouldCancel = true;\n try {\n while (true) {\n let result: ReadableStreamReadResult<Uint8Array>;\n try {\n result = await reader.read();\n } catch (error) {\n shouldCancel = false;\n throw error;\n }\n\n const { done, value } = result;\n if (done) {\n shouldCancel = false;\n for (const event of sseDecoder.push(decoder.decode())) {\n yield parseAdkEvent(event.data);\n }\n break;\n }\n\n for (const event of sseDecoder.push(\n decoder.decode(value, { stream: true }),\n )) {\n yield parseAdkEvent(event.data);\n }\n }\n\n const trailing = sseDecoder.flush();\n if (trailing !== null) yield parseAdkEvent(trailing.data);\n } finally {\n try {\n if (shouldCancel) await reader.cancel().catch(() => undefined);\n } finally {\n reader.releaseLock();\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AdkClient.js","names":[],"sources":["../src/AdkClient.ts"],"sourcesContent":["import { SSEEventDecoder } from \"assistant-stream/utils\";\nimport { contentToParts } from \"./contentToParts\";\nimport { parseAdkEventValue } from \"./parseAdkEvent\";\nimport { raceWithAbortSignal } from \"./raceWithAbortSignal\";\nimport { toAdkFunctionResponse } from \"./toAdkFunctionResponse\";\nimport { trimTrailingSlashes } from \"./trimTrailingSlashes\";\nimport type {\n AdkEvent,\n AdkEventPart,\n AdkMessage,\n AdkStreamCallback,\n} from \"./types\";\n\nexport type CreateAdkStreamOptions = {\n /**\n * URL to POST to. Either a proxy route (e.g. \"/api/adk\") or\n * an ADK server base URL (e.g. \"http://localhost:8000\").\n *\n * When `appName` and `userId` are provided, POSTs to `${api}/run_sse`\n * in ADK-native format. Otherwise POSTs directly to `api` in proxy format\n * (compatible with `parseAdkRequest`).\n */\n api: string;\n\n /**\n * ADK application name. When provided along with `userId`,\n * enables direct connection to an ADK server.\n */\n appName?: string | undefined;\n\n /**\n * ADK user ID. Required when `appName` is provided.\n */\n userId?: string | undefined;\n\n /**\n * Extra headers to send with every request.\n * Can be a static object or an async function for dynamic auth tokens.\n */\n headers?:\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>)\n | undefined;\n};\n\n/**\n * Creates an `AdkStreamCallback` that connects to an ADK endpoint.\n *\n * @example Proxy mode (with a Next.js API route)\n * ```ts\n * const stream = createAdkStream({ api: \"/api/adk\" });\n * ```\n *\n * @example Direct mode (connecting to ADK server)\n * ```ts\n * const stream = createAdkStream({\n * api: \"http://localhost:8000\",\n * appName: \"my-app\",\n * userId: \"user-1\",\n * });\n * ```\n */\nexport function createAdkStream(\n options: CreateAdkStreamOptions,\n): AdkStreamCallback {\n if (options.appName === \"\") {\n throw new Error(\n 'createAdkStream direct mode requires a non-empty \"appName\".',\n );\n }\n\n const isDirect = options.appName != null;\n if (isDirect && (options.userId == null || options.userId === \"\")) {\n throw new Error(\n 'createAdkStream direct mode requires \"userId\" when \"appName\" is provided.',\n );\n }\n\n return async function* (messages, config) {\n const headers = await resolveHeaders(options.headers, config.abortSignal);\n\n let url: string;\n let body: unknown;\n\n if (isDirect) {\n // Direct mode: POST to ADK server's /run_sse\n url = `${trimTrailingSlashes(options.api)}/run_sse`;\n const { externalId } = await config.initialize();\n body = {\n appName: options.appName,\n userId: options.userId,\n sessionId: externalId,\n newMessage: messagesToContent(messages),\n streaming: true,\n ...(config.stateDelta != null && { stateDelta: config.stateDelta }),\n };\n } else {\n // Proxy mode: POST in parseAdkRequest-compatible format\n url = options.api;\n body = messagesToProxyBody(messages, config);\n }\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...headers },\n body: JSON.stringify(body),\n signal: config.abortSignal,\n });\n\n if (!response.ok) {\n throw new Error(\n `ADK request failed: ${response.status} ${response.statusText}`,\n );\n }\n\n validateEventStreamContentType(response);\n yield* parseSSEResponse(response);\n };\n}\n\n// ── Internal helpers ──\n\nfunction validateEventStreamContentType(response: Response): void {\n const contentType = response.headers.get(\"Content-Type\");\n const mediaType = contentType?.split(\";\", 1)[0]?.trim().toLowerCase();\n if (mediaType !== \"text/event-stream\") {\n const received = contentType\n ? `\"${contentType}\"`\n : \"no Content-Type header\";\n void response.body?.cancel().catch(() => undefined);\n throw new Error(\n `Expected ADK stream response Content-Type \"text/event-stream\", received ${received}`,\n );\n }\n}\n\nfunction parseAdkEvent(data: string): AdkEvent {\n let value: unknown;\n try {\n value = JSON.parse(data);\n } catch {\n throw new Error(\"Invalid ADK stream event: expected valid JSON.\");\n }\n\n return parseAdkEventValue(value, \"Invalid ADK stream event\");\n}\n\nasync function resolveHeaders(\n headers:\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>)\n | undefined,\n signal?: AbortSignal,\n): Promise<Record<string, string>> {\n if (!headers) return {};\n if (typeof headers === \"function\") {\n return await raceWithAbortSignal(signal, headers);\n }\n return headers;\n}\n\n/**\n * Converts AdkMessage[] (new messages) into ADK Content format\n * for the direct `/run_sse` endpoint.\n */\nfunction messagesToContent(messages: AdkMessage[]): {\n role: string;\n parts: AdkEventPart[];\n} {\n const parts: AdkEventPart[] = [];\n\n for (const msg of messages) {\n if (msg.type === \"human\") {\n for (const part of contentToParts(msg.content)) {\n parts.push(part);\n }\n } else if (msg.type === \"tool\") {\n let response: unknown;\n try {\n response = JSON.parse(msg.content);\n } catch {\n response = msg.content;\n }\n parts.push({\n functionResponse: {\n name: msg.name,\n id: msg.tool_call_id,\n response: toAdkFunctionResponse(response, msg.status === \"error\"),\n },\n });\n }\n }\n\n if (parts.length === 0) {\n parts.push({ text: \"\" });\n }\n\n return { role: \"user\", parts };\n}\n\n/**\n * Converts AdkMessage[] into the proxy request body format\n * (compatible with `parseAdkRequest`).\n */\nfunction messagesToProxyBody(\n messages: AdkMessage[],\n config: {\n runConfig?: unknown;\n checkpointId?: string | undefined;\n stateDelta?: Record<string, unknown> | undefined;\n },\n): Record<string, unknown> {\n const body: Record<string, unknown> = {};\n\n if (config.runConfig != null) body.runConfig = config.runConfig;\n if (config.checkpointId != null) body.checkpointId = config.checkpointId;\n if (config.stateDelta != null) body.stateDelta = config.stateDelta;\n\n // Check if there's a tool result\n const toolMsg = messages.find((m) => m.type === \"tool\");\n if (toolMsg && toolMsg.type === \"tool\") {\n // If there are also other messages (e.g. cancellations), send as parts\n if (messages.length > 1) {\n body.parts = messagesToContent(messages).parts;\n return body;\n }\n\n let result: unknown;\n try {\n result = JSON.parse(toolMsg.content);\n } catch {\n result = toolMsg.content;\n }\n body.type = \"tool-result\";\n body.toolCallId = toolMsg.tool_call_id;\n body.toolName = toolMsg.name;\n body.result = result;\n body.isError = toolMsg.status === \"error\";\n return body;\n }\n\n // Human message(s) - possibly with cancellation tool results prepended\n if (messages.length === 1 && messages[0]!.type === \"human\") {\n const msg = messages[0]!;\n if (typeof msg.content === \"string\") {\n body.message = msg.content;\n } else {\n body.parts = contentToParts(msg.content);\n }\n return body;\n }\n\n // Multiple messages (e.g. cancellations + human): send as parts array\n body.parts = messagesToContent(messages).parts;\n return body;\n}\n\nasync function* parseSSEResponse(response: Response): AsyncGenerator<AdkEvent> {\n if (!response.body) {\n throw new Error(\"Expected ADK stream response body, received no body\");\n }\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n const sseDecoder = new SSEEventDecoder({ trailing: \"dispatch\" });\n\n let shouldCancel = true;\n try {\n while (true) {\n let result: ReadableStreamReadResult<Uint8Array>;\n try {\n result = await reader.read();\n } catch (error) {\n shouldCancel = false;\n throw error;\n }\n\n const { done, value } = result;\n if (done) {\n shouldCancel = false;\n for (const event of sseDecoder.push(decoder.decode())) {\n yield parseAdkEvent(event.data);\n }\n break;\n }\n\n for (const event of sseDecoder.push(\n decoder.decode(value, { stream: true }),\n )) {\n yield parseAdkEvent(event.data);\n }\n }\n\n const trailing = sseDecoder.flush();\n if (trailing !== null) yield parseAdkEvent(trailing.data);\n } finally {\n try {\n if (shouldCancel) await reader.cancel().catch(() => undefined);\n } finally {\n reader.releaseLock();\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,51 +1,47 @@
|
|
|
1
|
-
import {
|
|
2
|
-
//#region src/AdkEventAccumulator.d.ts
|
|
1
|
+
import type { AdkEvent, AdkMessage, AdkToolConfirmation, AdkAuthRequest, AdkMessageMetadata } from "./types.js";
|
|
3
2
|
/**
|
|
4
3
|
* Checks if an event is a final response using the same logic as ADK's
|
|
5
4
|
* `isFinalResponse()`.
|
|
6
5
|
*/
|
|
7
|
-
declare const isFinalResponse: (event: AdkEvent) => boolean;
|
|
8
|
-
declare class AdkEventAccumulator {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
getMessageMetadata(): Map<string, AdkMessageMetadata>;
|
|
6
|
+
export declare const isFinalResponse: (event: AdkEvent) => boolean;
|
|
7
|
+
export declare class AdkEventAccumulator {
|
|
8
|
+
private messagesMap;
|
|
9
|
+
private currentMessageId;
|
|
10
|
+
private partialTextBuffer;
|
|
11
|
+
private finalTextReplacedThisEvent;
|
|
12
|
+
private finalReasoningReplacedThisEvent;
|
|
13
|
+
private partialReasoningBuffer;
|
|
14
|
+
private accumulatedStateDelta;
|
|
15
|
+
private accumulatedArtifactDelta;
|
|
16
|
+
private lastAgentInfo;
|
|
17
|
+
private lastTransferToAgent;
|
|
18
|
+
private pendingLongRunningToolIds;
|
|
19
|
+
private escalated;
|
|
20
|
+
private messageMetadataMap;
|
|
21
|
+
private aiMessageOrdinals;
|
|
22
|
+
constructor(initialMessages?: AdkMessage[], initialLongRunningToolIds?: readonly string[]);
|
|
23
|
+
processEvent(rawEvent: AdkEvent): AdkMessage[];
|
|
24
|
+
private processPart;
|
|
25
|
+
private trackMessageMetadata;
|
|
26
|
+
private getContentArray;
|
|
27
|
+
private getOrCreateAiMessage;
|
|
28
|
+
private appendContent;
|
|
29
|
+
private replaceLastTextContent;
|
|
30
|
+
private replaceLastReasoningContent;
|
|
31
|
+
private finalizeCurrentMessage;
|
|
32
|
+
private getRequestCalls;
|
|
33
|
+
getMessages(): AdkMessage[];
|
|
34
|
+
getStateDelta(): Record<string, unknown>;
|
|
35
|
+
getArtifactDelta(): Record<string, number>;
|
|
36
|
+
getAgentInfo(): {
|
|
37
|
+
name?: string | undefined;
|
|
38
|
+
branch?: string | undefined;
|
|
39
|
+
};
|
|
40
|
+
getLastTransferToAgent(): string | undefined;
|
|
41
|
+
getLongRunningToolIds(): string[];
|
|
42
|
+
getToolConfirmations(): AdkToolConfirmation[];
|
|
43
|
+
getAuthRequests(): AdkAuthRequest[];
|
|
44
|
+
isEscalated(): boolean;
|
|
45
|
+
getMessageMetadata(): Map<string, AdkMessageMetadata>;
|
|
48
46
|
}
|
|
49
|
-
//#endregion
|
|
50
|
-
export { AdkEventAccumulator, isFinalResponse };
|
|
51
47
|
//# sourceMappingURL=AdkEventAccumulator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdkEventAccumulator.d.ts","
|
|
1
|
+
{"version":3,"file":"AdkEventAccumulator.d.ts","sourceRoot":"","sources":["../src/AdkEventAccumulator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,QAAQ,EAER,UAAU,EAGV,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EACnB,mBAAgB;AA4BjB;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,QAAQ,KAAG,OAgBjD,CAAC;AAuHF,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,iBAAiB,CAAM;IAC/B,OAAO,CAAC,0BAA0B,CAAS;IAC3C,OAAO,CAAC,+BAA+B,CAAS;IAChD,OAAO,CAAC,sBAAsB,CAAM;IACpC,OAAO,CAAC,qBAAqB,CAAgD;IAC7E,OAAO,CAAC,wBAAwB,CACV;IACtB,OAAO,CAAC,aAAa,CAGd;IACP,OAAO,CAAC,mBAAmB,CAAqB;IAChD,OAAO,CAAC,yBAAyB,CAAqB;IACtD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,kBAAkB,CAAyC;IAGnE,OAAO,CAAC,iBAAiB,CAA6B;gBAEpD,eAAe,CAAC,EAAE,UAAU,EAAE,EAC9B,yBAAyB,CAAC,EAAE,SAAS,MAAM,EAAE;IAY/C,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,UAAU,EAAE;IAyL9C,OAAO,CAAC,WAAW;IA4GnB,OAAO,CAAC,oBAAoB;IAmB5B,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,oBAAoB;IAyB5B,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,sBAAsB;IAY9B,OAAO,CAAC,2BAA2B;IAenC,OAAO,CAAC,sBAAsB;IAO9B,OAAO,CAAC,eAAe;IAWvB,WAAW,IAAI,UAAU,EAAE;IAI3B,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAIxC,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAI1C,YAAY,IAAI;QAAE,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE;IAI1E,sBAAsB,IAAI,MAAM,GAAG,SAAS;IAI5C,qBAAqB,IAAI,MAAM,EAAE;IAIjC,oBAAoB,IAAI,mBAAmB,EAAE;IAoB7C,eAAe,IAAI,cAAc,EAAE;IAanC,WAAW,IAAI,OAAO;IAItB,kBAAkB,IAAI,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC;CAGtD"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { isAdkFunctionError } from "./toAdkFunctionResponse.js";
|
|
2
|
+
import { normalizeAdkPart } from "./normalizeAdkPart.js";
|
|
3
|
+
import { projectAdkToolApprovals } from "./adkToolApproval.js";
|
|
2
4
|
import { isRecord } from "@assistant-ui/core/internal";
|
|
3
5
|
import { generateId } from "@assistant-ui/core";
|
|
4
6
|
//#region src/AdkEventAccumulator.ts
|
|
@@ -59,48 +61,31 @@ const finishReasonToStatus = (finishReason) => {
|
|
|
59
61
|
reason: "stop"
|
|
60
62
|
};
|
|
61
63
|
};
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
} : {
|
|
75
|
-
type: "file_url",
|
|
76
|
-
url: fileUri,
|
|
77
|
-
mimeType
|
|
78
|
-
};
|
|
79
|
-
const normalizeEventPart = (part) => {
|
|
80
|
-
const p = part;
|
|
81
|
-
const result = { ...p };
|
|
82
|
-
if ("function_call" in p && !("functionCall" in p)) result.functionCall = p.function_call;
|
|
83
|
-
if ("function_response" in p && !("functionResponse" in p)) result.functionResponse = p.function_response;
|
|
84
|
-
if ("inline_data" in p && !("inlineData" in p)) result.inlineData = p.inline_data;
|
|
85
|
-
if ("file_data" in p && !("fileData" in p)) result.fileData = p.file_data;
|
|
86
|
-
if (isRecord(result.inlineData)) {
|
|
87
|
-
const data = result.inlineData;
|
|
88
|
-
if ("mime_type" in data && !("mimeType" in data)) result.inlineData = {
|
|
89
|
-
...data,
|
|
90
|
-
mimeType: data.mime_type
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
if (isRecord(result.fileData)) {
|
|
94
|
-
const data = result.fileData;
|
|
95
|
-
result.fileData = {
|
|
96
|
-
...data,
|
|
97
|
-
..."mime_type" in data && !("mimeType" in data) && { mimeType: data.mime_type },
|
|
98
|
-
..."file_uri" in data && !("fileUri" in data) && { fileUri: data.file_uri }
|
|
64
|
+
const mediaToContentPart = ({ inlineData, fileData }) => {
|
|
65
|
+
if (isRecord(inlineData)) {
|
|
66
|
+
const { mimeType, data } = inlineData;
|
|
67
|
+
if (typeof mimeType !== "string" || typeof data !== "string") return;
|
|
68
|
+
return mimeType.startsWith("image/") ? {
|
|
69
|
+
type: "image",
|
|
70
|
+
mimeType,
|
|
71
|
+
data
|
|
72
|
+
} : {
|
|
73
|
+
type: "file",
|
|
74
|
+
mimeType,
|
|
75
|
+
data
|
|
99
76
|
};
|
|
100
77
|
}
|
|
101
|
-
if (
|
|
102
|
-
|
|
103
|
-
return
|
|
78
|
+
if (!isRecord(fileData)) return;
|
|
79
|
+
const { fileUri, mimeType } = fileData;
|
|
80
|
+
if (typeof fileUri !== "string") return;
|
|
81
|
+
return typeof mimeType !== "string" || mimeType.startsWith("image/") ? {
|
|
82
|
+
type: "image_url",
|
|
83
|
+
url: fileUri
|
|
84
|
+
} : {
|
|
85
|
+
type: "file_url",
|
|
86
|
+
url: fileUri,
|
|
87
|
+
mimeType
|
|
88
|
+
};
|
|
104
89
|
};
|
|
105
90
|
const normalizeEvent = (event) => {
|
|
106
91
|
const e = event;
|
|
@@ -131,7 +116,7 @@ const normalizeEvent = (event) => {
|
|
|
131
116
|
const parts = content.parts;
|
|
132
117
|
result.content = {
|
|
133
118
|
...content,
|
|
134
|
-
parts: parts.map(
|
|
119
|
+
parts: parts.map(normalizeAdkPart)
|
|
135
120
|
};
|
|
136
121
|
}
|
|
137
122
|
return result;
|
|
@@ -148,8 +133,6 @@ var AdkEventAccumulator = class {
|
|
|
148
133
|
lastAgentInfo = {};
|
|
149
134
|
lastTransferToAgent;
|
|
150
135
|
pendingLongRunningToolIds = /* @__PURE__ */ new Set();
|
|
151
|
-
toolConfirmations = [];
|
|
152
|
-
authRequests = [];
|
|
153
136
|
escalated = false;
|
|
154
137
|
messageMetadataMap = /* @__PURE__ */ new Map();
|
|
155
138
|
aiMessageOrdinals = /* @__PURE__ */ new Map();
|
|
@@ -164,21 +147,6 @@ var AdkEventAccumulator = class {
|
|
|
164
147
|
if (event.actions?.escalate) this.escalated = true;
|
|
165
148
|
if (event.actions?.transferToAgent) this.lastTransferToAgent = event.actions.transferToAgent;
|
|
166
149
|
if (event.longRunningToolIds?.length) for (const id of event.longRunningToolIds) this.pendingLongRunningToolIds.add(id);
|
|
167
|
-
if (event.actions?.requestedToolConfirmations) for (const [tcId, conf] of Object.entries(event.actions.requestedToolConfirmations)) {
|
|
168
|
-
const c = conf;
|
|
169
|
-
this.toolConfirmations.push({
|
|
170
|
-
toolCallId: tcId,
|
|
171
|
-
toolName: "",
|
|
172
|
-
args: {},
|
|
173
|
-
hint: c.hint ?? "",
|
|
174
|
-
confirmed: false,
|
|
175
|
-
payload: c.payload
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
if (event.actions?.requestedAuthConfigs) for (const [tcId, authConf] of Object.entries(event.actions.requestedAuthConfigs)) this.authRequests.push({
|
|
179
|
-
toolCallId: tcId,
|
|
180
|
-
authConfig: authConf
|
|
181
|
-
});
|
|
182
150
|
if (event.author && event.author !== "user") this.lastAgentInfo = {
|
|
183
151
|
name: event.author ?? void 0,
|
|
184
152
|
branch: event.branch ?? void 0
|
|
@@ -234,9 +202,10 @@ var AdkEventAccumulator = class {
|
|
|
234
202
|
type: "text",
|
|
235
203
|
text: part.text
|
|
236
204
|
});
|
|
237
|
-
else if (part.inlineData
|
|
238
|
-
|
|
239
|
-
|
|
205
|
+
else if (part.inlineData || part.fileData) {
|
|
206
|
+
const mediaPart = mediaToContentPart(part);
|
|
207
|
+
if (mediaPart) humanParts.push(mediaPart);
|
|
208
|
+
} else if (part.functionResponse?.id) {
|
|
240
209
|
toolMessages.push({
|
|
241
210
|
id: toolMessageId(event, index),
|
|
242
211
|
type: "tool",
|
|
@@ -285,31 +254,6 @@ var AdkEventAccumulator = class {
|
|
|
285
254
|
return this.getMessages();
|
|
286
255
|
}
|
|
287
256
|
processPart(part, event, partIndex) {
|
|
288
|
-
if (part.functionCall && !event.partial) {
|
|
289
|
-
const name = part.functionCall.name;
|
|
290
|
-
if (name === ADK_REQUEST_CONFIRMATION) {
|
|
291
|
-
const callArgs = part.functionCall.args;
|
|
292
|
-
const original = callArgs.originalFunctionCall ?? callArgs.original_function_call;
|
|
293
|
-
const conf = callArgs.toolConfirmation ?? callArgs.tool_confirmation;
|
|
294
|
-
this.toolConfirmations.push({
|
|
295
|
-
toolCallId: part.functionCall.id ?? "",
|
|
296
|
-
toolName: original?.name ?? "",
|
|
297
|
-
args: original?.args ?? {},
|
|
298
|
-
hint: conf?.hint ?? "",
|
|
299
|
-
confirmed: false,
|
|
300
|
-
payload: conf?.payload
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
if (name === ADK_REQUEST_CREDENTIAL) {
|
|
304
|
-
const credArgs = part.functionCall.args;
|
|
305
|
-
const originalToolCallId = credArgs.function_call_id ?? part.functionCall.id ?? "";
|
|
306
|
-
const authConfig = credArgs.auth_config ?? credArgs;
|
|
307
|
-
this.authRequests.push({
|
|
308
|
-
toolCallId: originalToolCallId,
|
|
309
|
-
authConfig
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
257
|
if (part.text != null && part.thought) {
|
|
314
258
|
const msg = this.getOrCreateAiMessage(event);
|
|
315
259
|
if (event.partial) {
|
|
@@ -346,8 +290,8 @@ var AdkEventAccumulator = class {
|
|
|
346
290
|
const toolCall = {
|
|
347
291
|
id: part.functionCall.id ?? generateId(),
|
|
348
292
|
name: part.functionCall.name,
|
|
349
|
-
args: part.functionCall.args,
|
|
350
|
-
argsText: JSON.stringify(part.functionCall.args)
|
|
293
|
+
args: part.functionCall.args ?? {},
|
|
294
|
+
argsText: JSON.stringify(part.functionCall.args ?? {})
|
|
351
295
|
};
|
|
352
296
|
const existing = [...msg.tool_calls ?? []];
|
|
353
297
|
const idx = existing.findIndex((tc) => tc.id === toolCall.id);
|
|
@@ -392,15 +336,10 @@ var AdkEventAccumulator = class {
|
|
|
392
336
|
});
|
|
393
337
|
return;
|
|
394
338
|
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
}
|
|
400
|
-
if (part.fileData) {
|
|
401
|
-
const msg = this.getOrCreateAiMessage(event);
|
|
402
|
-
this.appendContent(msg, fileDataToPart(part.fileData.fileUri, part.fileData.mimeType));
|
|
403
|
-
}
|
|
339
|
+
const mediaPart = mediaToContentPart(part);
|
|
340
|
+
if (!mediaPart) return;
|
|
341
|
+
const msg = this.getOrCreateAiMessage(event);
|
|
342
|
+
this.appendContent(msg, mediaPart);
|
|
404
343
|
}
|
|
405
344
|
trackMessageMetadata(event) {
|
|
406
345
|
if (!this.currentMessageId || !event.groundingMetadata && !event.citationMetadata && !event.usageMetadata) return;
|
|
@@ -481,6 +420,14 @@ var AdkEventAccumulator = class {
|
|
|
481
420
|
this.partialReasoningBuffer = "";
|
|
482
421
|
this.currentMessageId = null;
|
|
483
422
|
}
|
|
423
|
+
getRequestCalls(name) {
|
|
424
|
+
const calls = /* @__PURE__ */ new Map();
|
|
425
|
+
for (const msg of this.messagesMap.values()) {
|
|
426
|
+
if (msg.type !== "ai") continue;
|
|
427
|
+
for (const call of msg.tool_calls ?? []) if (call.name === name && !calls.has(call.id)) calls.set(call.id, call);
|
|
428
|
+
}
|
|
429
|
+
return [...calls.values()];
|
|
430
|
+
}
|
|
484
431
|
getMessages() {
|
|
485
432
|
return [...this.messagesMap.values()];
|
|
486
433
|
}
|
|
@@ -500,10 +447,27 @@ var AdkEventAccumulator = class {
|
|
|
500
447
|
return [...this.pendingLongRunningToolIds];
|
|
501
448
|
}
|
|
502
449
|
getToolConfirmations() {
|
|
503
|
-
|
|
450
|
+
const { approvals } = projectAdkToolApprovals(this.getMessages());
|
|
451
|
+
return this.getRequestCalls(ADK_REQUEST_CONFIRMATION).filter(({ id }) => approvals.get(id)?.approved === void 0).map(({ id, args = {} }) => {
|
|
452
|
+
const original = args.originalFunctionCall ?? args.original_function_call;
|
|
453
|
+
const confirmation = args.toolConfirmation ?? args.tool_confirmation;
|
|
454
|
+
return {
|
|
455
|
+
toolCallId: id,
|
|
456
|
+
toolName: original?.name ?? "",
|
|
457
|
+
args: original?.args ?? {},
|
|
458
|
+
hint: confirmation?.hint ?? "",
|
|
459
|
+
confirmed: false,
|
|
460
|
+
payload: confirmation?.payload
|
|
461
|
+
};
|
|
462
|
+
});
|
|
504
463
|
}
|
|
505
464
|
getAuthRequests() {
|
|
506
|
-
|
|
465
|
+
const answered = /* @__PURE__ */ new Set();
|
|
466
|
+
for (const msg of this.messagesMap.values()) if (msg.type === "tool") answered.add(msg.tool_call_id);
|
|
467
|
+
return this.getRequestCalls(ADK_REQUEST_CREDENTIAL).filter(({ id }) => !answered.has(id)).map(({ id, args = {} }) => ({
|
|
468
|
+
toolCallId: id,
|
|
469
|
+
authConfig: args.auth_config ?? args.authConfig
|
|
470
|
+
}));
|
|
507
471
|
}
|
|
508
472
|
isEscalated() {
|
|
509
473
|
return this.escalated;
|