@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.
Files changed (103) hide show
  1. package/dist/AdkClient.d.ts +26 -29
  2. package/dist/AdkClient.d.ts.map +1 -1
  3. package/dist/AdkClient.js +5 -3
  4. package/dist/AdkClient.js.map +1 -1
  5. package/dist/AdkEventAccumulator.d.ts +41 -45
  6. package/dist/AdkEventAccumulator.d.ts.map +1 -1
  7. package/dist/AdkEventAccumulator.js +63 -99
  8. package/dist/AdkEventAccumulator.js.map +1 -1
  9. package/dist/AdkSessionAdapter.d.ts +41 -39
  10. package/dist/AdkSessionAdapter.d.ts.map +1 -1
  11. package/dist/AdkSessionAdapter.js +11 -7
  12. package/dist/AdkSessionAdapter.js.map +1 -1
  13. package/dist/adkAuthRequest.d.ts +17 -0
  14. package/dist/adkAuthRequest.d.ts.map +1 -0
  15. package/dist/adkAuthRequest.js +45 -0
  16. package/dist/adkAuthRequest.js.map +1 -0
  17. package/dist/adkExtras.d.ts +2 -5
  18. package/dist/adkExtras.d.ts.map +1 -1
  19. package/dist/adkToolApproval.d.ts +18 -21
  20. package/dist/adkToolApproval.d.ts.map +1 -1
  21. package/dist/adkToolApproval.js +1 -3
  22. package/dist/adkToolApproval.js.map +1 -1
  23. package/dist/contentToParts.d.ts +2 -5
  24. package/dist/contentToParts.d.ts.map +1 -1
  25. package/dist/convertAdkMessages.d.ts +5 -8
  26. package/dist/convertAdkMessages.d.ts.map +1 -1
  27. package/dist/convertAdkMessages.js +4 -3
  28. package/dist/convertAdkMessages.js.map +1 -1
  29. package/dist/convertToAdkMessages.d.ts +36 -39
  30. package/dist/convertToAdkMessages.d.ts.map +1 -1
  31. package/dist/hooks.d.ts +25 -23
  32. package/dist/hooks.d.ts.map +1 -1
  33. package/dist/hooks.js +12 -10
  34. package/dist/hooks.js.map +1 -1
  35. package/dist/index.d.ts +11 -10
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/normalizeAdkPart.d.ts +2 -0
  38. package/dist/normalizeAdkPart.d.ts.map +1 -0
  39. package/dist/normalizeAdkPart.js +31 -0
  40. package/dist/normalizeAdkPart.js.map +1 -0
  41. package/dist/parseAdkEvent.d.ts +2 -5
  42. package/dist/parseAdkEvent.d.ts.map +1 -1
  43. package/dist/raceWithAbortSignal.d.ts +2 -0
  44. package/dist/raceWithAbortSignal.d.ts.map +1 -0
  45. package/dist/raceWithAbortSignal.js +45 -0
  46. package/dist/raceWithAbortSignal.js.map +1 -0
  47. package/dist/sdkIdentity.d.ts +2 -5
  48. package/dist/sdkIdentity.d.ts.map +1 -1
  49. package/dist/sdkIdentity.js +1 -1
  50. package/dist/server/adkEventStream.d.ts +25 -27
  51. package/dist/server/adkEventStream.d.ts.map +1 -1
  52. package/dist/server/adkEventStream.js +23 -15
  53. package/dist/server/adkEventStream.js.map +1 -1
  54. package/dist/server/createAdkApiRoute.d.ts +23 -25
  55. package/dist/server/createAdkApiRoute.d.ts.map +1 -1
  56. package/dist/server/index.d.ts +4 -4
  57. package/dist/server/index.d.ts.map +1 -0
  58. package/dist/server/parseAdkRequest.d.ts +18 -20
  59. package/dist/server/parseAdkRequest.d.ts.map +1 -1
  60. package/dist/structuredEvents.d.ts +2 -5
  61. package/dist/structuredEvents.d.ts.map +1 -1
  62. package/dist/structuredEvents.js +1 -1
  63. package/dist/structuredEvents.js.map +1 -1
  64. package/dist/toAdkFunctionResponse.d.ts +2 -5
  65. package/dist/toAdkFunctionResponse.d.ts.map +1 -1
  66. package/dist/trimTrailingSlashes.d.ts +1 -4
  67. package/dist/trimTrailingSlashes.d.ts.map +1 -1
  68. package/dist/types.d.ts +253 -256
  69. package/dist/types.d.ts.map +1 -1
  70. package/dist/types.js.map +1 -1
  71. package/dist/useAdkMessages.d.ts +26 -29
  72. package/dist/useAdkMessages.d.ts.map +1 -1
  73. package/dist/useAdkMessages.js +2 -0
  74. package/dist/useAdkMessages.js.map +1 -1
  75. package/dist/useAdkRuntime.d.ts +50 -52
  76. package/dist/useAdkRuntime.d.ts.map +1 -1
  77. package/dist/useAdkRuntime.js +1 -1
  78. package/package.json +10 -9
  79. package/src/AdkClient.test.ts +50 -0
  80. package/src/AdkClient.ts +10 -3
  81. package/src/AdkEventAccumulator.test.ts +312 -11
  82. package/src/AdkEventAccumulator.ts +68 -142
  83. package/src/AdkSessionAdapter.test.ts +284 -1
  84. package/src/AdkSessionAdapter.ts +32 -8
  85. package/src/adkAuthRequest.test.ts +101 -0
  86. package/src/adkAuthRequest.ts +50 -0
  87. package/src/adkToolApproval.test.ts +0 -4
  88. package/src/adkToolApproval.ts +1 -3
  89. package/src/convertAdkMessages.test.ts +41 -0
  90. package/src/convertAdkMessages.ts +19 -7
  91. package/src/hooks.render.test.tsx +95 -2
  92. package/src/hooks.ts +12 -13
  93. package/src/normalizeAdkPart.ts +35 -0
  94. package/src/raceWithAbortSignal.test.ts +73 -0
  95. package/src/raceWithAbortSignal.ts +48 -0
  96. package/src/server/adkEventStream.test.ts +147 -0
  97. package/src/server/adkEventStream.ts +27 -20
  98. package/src/structuredEvents.test.ts +69 -0
  99. package/src/structuredEvents.ts +4 -1
  100. package/src/types.ts +1 -1
  101. package/src/useAdkMessages.test.ts +102 -3
  102. package/src/useAdkMessages.ts +2 -0
  103. package/src/useAdkRuntime.replacement.test.tsx +11 -7
@@ -1,29 +1,28 @@
1
- import { AdkStreamCallback } from "./types.js";
2
- //#region src/AdkClient.d.ts
3
- type CreateAdkStreamOptions = {
4
- /**
5
- * URL to POST to. Either a proxy route (e.g. "/api/adk") or
6
- * an ADK server base URL (e.g. "http://localhost:8000").
7
- *
8
- * When `appName` and `userId` are provided, POSTs to `${api}/run_sse`
9
- * in ADK-native format. Otherwise POSTs directly to `api` in proxy format
10
- * (compatible with `parseAdkRequest`).
11
- */
12
- api: string;
13
- /**
14
- * ADK application name. When provided along with `userId`,
15
- * enables direct connection to an ADK server.
16
- */
17
- appName?: string | undefined;
18
- /**
19
- * ADK user ID. Required when `appName` is provided.
20
- */
21
- userId?: string | undefined;
22
- /**
23
- * Extra headers to send with every request.
24
- * Can be a static object or an async function for dynamic auth tokens.
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
@@ -1 +1 @@
1
- {"version":3,"file":"AdkClient.d.ts","names":[],"sources":["../src/AdkClient.ts"],"mappings":";;KAYY;;;;;;;;;EASV;;;;;EAMA;;;;EAKA;;;;;EAMA,UACI,gCACO,yBAAyB,QAAQ;;;;;;;;;;;;;;;;;;;iBAqB9B,gBACd,SAAS,yBACR"}
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" });
@@ -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 { AdkAuthRequest, AdkEvent, AdkMessage, AdkMessageMetadata, AdkToolConfirmation } from "./types.js";
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
- private messagesMap;
10
- private currentMessageId;
11
- private partialTextBuffer;
12
- private finalTextReplacedThisEvent;
13
- private finalReasoningReplacedThisEvent;
14
- private partialReasoningBuffer;
15
- private accumulatedStateDelta;
16
- private accumulatedArtifactDelta;
17
- private lastAgentInfo;
18
- private lastTransferToAgent;
19
- private pendingLongRunningToolIds;
20
- private toolConfirmations;
21
- private authRequests;
22
- private escalated;
23
- private messageMetadataMap;
24
- private aiMessageOrdinals;
25
- constructor(initialMessages?: AdkMessage[], initialLongRunningToolIds?: readonly string[]);
26
- processEvent(rawEvent: AdkEvent): AdkMessage[];
27
- private processPart;
28
- private trackMessageMetadata;
29
- private getContentArray;
30
- private getOrCreateAiMessage;
31
- private appendContent;
32
- private replaceLastTextContent;
33
- private replaceLastReasoningContent;
34
- private finalizeCurrentMessage;
35
- getMessages(): AdkMessage[];
36
- getStateDelta(): Record<string, unknown>;
37
- getArtifactDelta(): Record<string, number>;
38
- getAgentInfo(): {
39
- name?: string | undefined;
40
- branch?: string | undefined;
41
- };
42
- getLastTransferToAgent(): string | undefined;
43
- getLongRunningToolIds(): string[];
44
- getToolConfirmations(): AdkToolConfirmation[];
45
- getAuthRequests(): AdkAuthRequest[];
46
- isEscalated(): boolean;
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","names":[],"sources":["../src/AdkEventAccumulator.ts"],"mappings":";;;;;;cA0Ca,kBAAmB,OAAO;cAoK1B;UACH;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UAEA;UAIA;UACA;UACA;UACA;UACA;UACA;UAGA;EAEN,YAAA,kBAAkB,cAClB;EAYF,aAAa,UAAU,WAAW;UAwN1B;UA+JA;UAmBA;UAMA;UAyBA;UASA;UAYA;UAeA;EAMR,eAAe;EAIf,iBAAiB;EAIjB,oBAAoB;EAIpB;IAAkB;IAA2B;;EAI7C;EAIA;EAIA,wBAAwB;EAIxB,mBAAmB;EAInB;EAIA,sBAAsB,YAAY"}
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 inlineDataToPart = (mimeType, data) => mimeType.startsWith("image/") ? {
63
- type: "image",
64
- mimeType,
65
- data
66
- } : {
67
- type: "file",
68
- mimeType,
69
- data
70
- };
71
- const fileDataToPart = (fileUri, mimeType) => mimeType == null || mimeType.startsWith("image/") ? {
72
- type: "image_url",
73
- url: fileUri
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 ("executable_code" in p && !("executableCode" in p)) result.executableCode = p.executable_code;
102
- if ("code_execution_result" in p && !("codeExecutionResult" in p)) result.codeExecutionResult = p.code_execution_result;
103
- return result;
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(normalizeEventPart)
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) humanParts.push(inlineDataToPart(part.inlineData.mimeType, part.inlineData.data));
238
- else if (part.fileData) humanParts.push(fileDataToPart(part.fileData.fileUri, part.fileData.mimeType));
239
- else if (part.functionResponse?.id) {
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
- if (part.inlineData) {
396
- const msg = this.getOrCreateAiMessage(event);
397
- this.appendContent(msg, inlineDataToPart(part.inlineData.mimeType, part.inlineData.data));
398
- return;
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
- return [...this.toolConfirmations];
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
- return [...this.authRequests];
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;