@assistant-ui/react-google-adk 0.0.16 → 0.0.18

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 (49) hide show
  1. package/dist/AdkClient.d.ts +0 -1
  2. package/dist/AdkClient.d.ts.map +1 -1
  3. package/dist/AdkClient.js +22 -10
  4. package/dist/AdkClient.js.map +1 -1
  5. package/dist/AdkEventAccumulator.d.ts +0 -1
  6. package/dist/AdkEventAccumulator.d.ts.map +1 -1
  7. package/dist/AdkSessionAdapter.d.ts +0 -1
  8. package/dist/AdkSessionAdapter.d.ts.map +1 -1
  9. package/dist/AdkSessionAdapter.js +59 -11
  10. package/dist/AdkSessionAdapter.js.map +1 -1
  11. package/dist/adkExtras.d.ts +0 -1
  12. package/dist/adkExtras.d.ts.map +1 -1
  13. package/dist/contentToParts.d.ts +0 -1
  14. package/dist/contentToParts.d.ts.map +1 -1
  15. package/dist/convertAdkMessages.d.ts +0 -1
  16. package/dist/convertAdkMessages.d.ts.map +1 -1
  17. package/dist/hooks.d.ts +0 -1
  18. package/dist/hooks.d.ts.map +1 -1
  19. package/dist/server/adkEventStream.d.ts.map +1 -1
  20. package/dist/server/createAdkApiRoute.d.ts +0 -1
  21. package/dist/server/createAdkApiRoute.d.ts.map +1 -1
  22. package/dist/server/parseAdkRequest.d.ts +0 -1
  23. package/dist/server/parseAdkRequest.d.ts.map +1 -1
  24. package/dist/server/parseAdkRequest.js +2 -2
  25. package/dist/server/parseAdkRequest.js.map +1 -1
  26. package/dist/structuredEvents.d.ts +0 -1
  27. package/dist/structuredEvents.d.ts.map +1 -1
  28. package/dist/trimTrailingSlashes.d.ts +5 -0
  29. package/dist/trimTrailingSlashes.d.ts.map +1 -0
  30. package/dist/trimTrailingSlashes.js +10 -0
  31. package/dist/trimTrailingSlashes.js.map +1 -0
  32. package/dist/types.d.ts +1 -2
  33. package/dist/types.d.ts.map +1 -1
  34. package/dist/useAdkMessages.d.ts +1 -5
  35. package/dist/useAdkMessages.d.ts.map +1 -1
  36. package/dist/useAdkMessages.js +2 -1
  37. package/dist/useAdkMessages.js.map +1 -1
  38. package/dist/useAdkRuntime.d.ts +1 -9
  39. package/dist/useAdkRuntime.d.ts.map +1 -1
  40. package/dist/useAdkRuntime.js +2 -1
  41. package/dist/useAdkRuntime.js.map +1 -1
  42. package/package.json +7 -7
  43. package/src/AdkClient.test.ts +256 -32
  44. package/src/AdkClient.ts +41 -20
  45. package/src/AdkSessionAdapter.test.ts +225 -5
  46. package/src/AdkSessionAdapter.ts +151 -20
  47. package/src/server/parseAdkRequest.test.ts +4 -2
  48. package/src/server/parseAdkRequest.ts +4 -2
  49. package/src/trimTrailingSlashes.ts +5 -0
@@ -1,5 +1,4 @@
1
1
  import { AdkStreamCallback } from "./types.js";
2
-
3
2
  //#region src/AdkClient.d.ts
4
3
  type CreateAdkStreamOptions = {
5
4
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"AdkClient.d.ts","names":[],"sources":["../src/AdkClient.ts"],"mappings":";;;KAQY,sBAAA;;AAAZ;;;;;;;EASE,GAAA;EAmB2C;;;;EAb3C,OAAA;EAYI;;;EAPJ,MAAA;EAQkD;AAAA;AAqBpD;;EAvBE,OAAA,GACI,MAAA,0BACO,MAAA,mBAAyB,OAAA,CAAQ,MAAA;AAAA;;;;;AAuB1B;;;;;;;;;;;;;iBAFJ,eAAA,CACd,OAAA,EAAS,sBAAA,GACR,iBAAiB"}
1
+ {"version":3,"file":"AdkClient.d.ts","names":[],"sources":["../src/AdkClient.ts"],"mappings":";;KAUY;;;;;;;;;EASV;;;;;EAMA;;;;EAKA;;;;;EAMA,UACI,gCACO,yBAAyB,QAAQ;;;;;;;;;;;;;;;;;;;iBAqB9B,gBACd,SAAS,yBACR"}
package/dist/AdkClient.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import { contentToParts } from "./contentToParts.js";
2
+ import { trimTrailingSlashes } from "./trimTrailingSlashes.js";
3
+ import { SSEEventDecoder } from "assistant-stream/utils";
2
4
  //#region src/AdkClient.ts
3
5
  /**
4
6
  * Creates an `AdkStreamCallback` that connects to an ADK endpoint.
@@ -18,13 +20,15 @@ import { contentToParts } from "./contentToParts.js";
18
20
  * ```
19
21
  */
20
22
  function createAdkStream(options) {
23
+ if (options.appName === "") throw new Error("createAdkStream direct mode requires a non-empty \"appName\".");
21
24
  const isDirect = options.appName != null;
25
+ if (isDirect && (options.userId == null || options.userId === "")) throw new Error("createAdkStream direct mode requires \"userId\" when \"appName\" is provided.");
22
26
  return async function* (messages, config) {
23
27
  const headers = await resolveHeaders(options.headers);
24
28
  let url;
25
29
  let body;
26
30
  if (isDirect) {
27
- url = `${options.api}/run_sse`;
31
+ url = `${trimTrailingSlashes(options.api)}/run_sse`;
28
32
  const { externalId } = await config.initialize();
29
33
  body = {
30
34
  appName: options.appName,
@@ -48,9 +52,18 @@ function createAdkStream(options) {
48
52
  signal: config.abortSignal
49
53
  });
50
54
  if (!response.ok) throw new Error(`ADK request failed: ${response.status} ${response.statusText}`);
55
+ validateEventStreamContentType(response);
51
56
  yield* parseSSEResponse(response);
52
57
  };
53
58
  }
59
+ function validateEventStreamContentType(response) {
60
+ const contentType = response.headers.get("Content-Type");
61
+ if (contentType?.split(";", 1)[0]?.trim().toLowerCase() !== "text/event-stream") {
62
+ const received = contentType ? `"${contentType}"` : "no Content-Type header";
63
+ response.body?.cancel().catch(() => void 0);
64
+ throw new Error(`Expected ADK stream response Content-Type "text/event-stream", received ${received}`);
65
+ }
66
+ }
54
67
  async function resolveHeaders(headers) {
55
68
  if (!headers) return {};
56
69
  if (typeof headers === "function") return await headers();
@@ -122,19 +135,18 @@ function messagesToProxyBody(messages, config) {
122
135
  async function* parseSSEResponse(response) {
123
136
  const reader = response.body.getReader();
124
137
  const decoder = new TextDecoder();
125
- let buffer = "";
138
+ const sseDecoder = new SSEEventDecoder({ trailing: "dispatch" });
126
139
  try {
127
140
  while (true) {
128
141
  const { done, value } = await reader.read();
129
- if (done) break;
130
- buffer += decoder.decode(value, { stream: true });
131
- const parts = buffer.split("\n\n");
132
- buffer = parts.pop() ?? "";
133
- for (const part of parts) for (const line of part.split("\n")) if (line.startsWith("data: ")) yield JSON.parse(line.slice(6));
134
- }
135
- if (buffer.trim()) {
136
- for (const line of buffer.split("\n")) if (line.startsWith("data: ")) yield JSON.parse(line.slice(6));
142
+ if (done) {
143
+ for (const event of sseDecoder.push(decoder.decode())) yield JSON.parse(event.data);
144
+ break;
145
+ }
146
+ for (const event of sseDecoder.push(decoder.decode(value, { stream: true }))) yield JSON.parse(event.data);
137
147
  }
148
+ const trailing = sseDecoder.flush();
149
+ if (trailing !== null) yield JSON.parse(trailing.data);
138
150
  } finally {
139
151
  reader.releaseLock();
140
152
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AdkClient.js","names":[],"sources":["../src/AdkClient.ts"],"sourcesContent":["import { contentToParts } from \"./contentToParts\";\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 const isDirect = options.appName != null;\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 = `${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 yield* parseSSEResponse(response);\n };\n}\n\n// ── Internal helpers ──\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,\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 let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const parts = buffer.split(\"\\n\\n\");\n buffer = parts.pop() ?? \"\";\n\n for (const part of parts) {\n for (const line of part.split(\"\\n\")) {\n if (line.startsWith(\"data: \")) {\n yield JSON.parse(line.slice(6)) as AdkEvent;\n }\n }\n }\n }\n\n // Handle remaining buffer\n if (buffer.trim()) {\n for (const line of buffer.split(\"\\n\")) {\n if (line.startsWith(\"data: \")) {\n yield JSON.parse(line.slice(6)) as AdkEvent;\n }\n }\n }\n } finally {\n reader.releaseLock();\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 { 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\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,\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 try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n for (const event of sseDecoder.push(decoder.decode())) {\n yield JSON.parse(event.data) as AdkEvent;\n }\n break;\n }\n\n for (const event of sseDecoder.push(\n decoder.decode(value, { stream: true }),\n )) {\n yield JSON.parse(event.data) as AdkEvent;\n }\n }\n\n const trailing = sseDecoder.flush();\n if (trailing !== null) yield JSON.parse(trailing.data) as AdkEvent;\n } finally {\n reader.releaseLock();\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,4 @@
1
1
  import { AdkAuthRequest, AdkEvent, AdkMessage, AdkMessageMetadata, AdkToolConfirmation } from "./types.js";
2
-
3
2
  //#region src/AdkEventAccumulator.d.ts
4
3
  /**
5
4
  * Checks if an event is a final response using the same logic as ADK's
@@ -1 +1 @@
1
- {"version":3,"file":"AdkEventAccumulator.d.ts","names":[],"sources":["../src/AdkEventAccumulator.ts"],"mappings":";;;;;AAuBA;;cAAa,eAAA,GAAmB,KAAe,EAAR,QAAQ;AAAA,cAqJlC,mBAAA;EAAA,QACH,WAAA;EAAA,QACA,gBAAA;EAAA,QACA,iBAAA;EAAA,QACA,sBAAA;EAAA,QACA,qBAAA;EAAA,QACA,wBAAA;EAAA,QACA,aAAA;EAAA,QAIA,mBAAA;EAAA,QACA,yBAAA;EAAA,QACA,iBAAA;EAAA,QACA,YAAA;EAAA,QACA,SAAA;EAAA,QACA,kBAAA;cACI,eAAA,GAAkB,UAAA;EAQ9B,YAAA,CAAa,QAAA,EAAU,QAAA,GAAW,UAAA;EAAA,QAwL1B,WAAA;EAAA,QAmJA,oBAAA;EAAA,QAmBA,eAAA;EAAA,QAMA,oBAAA;EAAA,QAuBA,aAAA;EAAA,QASA,sBAAA;EAAA,QAYA,2BAAA;EAAA,QAeA,sBAAA;EAMR,WAAA,IAAe,UAAA;EAIf,aAAA,IAAiB,MAAA;EAIjB,gBAAA,IAAoB,MAAA;EAIpB,YAAA;IAAkB,IAAA;IAA2B,MAAA;EAAA;EAI7C,sBAAA;EAIA,qBAAA;EAIA,oBAAA,IAAwB,mBAAA;EAIxB,eAAA,IAAmB,cAAA;EAInB,WAAA;EAIA,kBAAA,IAAsB,GAAA,SAAY,kBAAA;AAAA"}
1
+ {"version":3,"file":"AdkEventAccumulator.d.ts","names":[],"sources":["../src/AdkEventAccumulator.ts"],"mappings":";;;;;;cAuBa,kBAAmB,OAAO;cAqJ1B;UACH;UACA;UACA;UACA;UACA;UACA;UACA;UAIA;UACA;UACA;UACA;UACA;UACA;EACI,YAAA,kBAAkB;EAQ9B,aAAa,UAAU,WAAW;UAwL1B;UAmJA;UAmBA;UAMA;UAuBA;UASA;UAYA;UAeA;EAMR,eAAe;EAIf,iBAAiB;EAIjB,oBAAoB;EAIpB;IAAkB;IAA2B;;EAI7C;EAIA;EAIA,wBAAwB;EAIxB,mBAAmB;EAInB;EAIA,sBAAsB,YAAY"}
@@ -1,6 +1,5 @@
1
1
  import { AdkMessage } from "./types.js";
2
2
  import { RemoteThreadListAdapter } from "@assistant-ui/core";
3
-
4
3
  //#region src/AdkSessionAdapter.d.ts
5
4
  type AdkSessionAdapterOptions = {
6
5
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"AdkSessionAdapter.d.ts","names":[],"sources":["../src/AdkSessionAdapter.ts"],"mappings":";;;;KAUY,wBAAA;;AAAZ;;EAIE,MAAA;EAgBI;;;EAXJ,OAAA;EAY2C;;;EAP3C,MAAA;EAAA;;;EAKA,OAAA,GACI,MAAA,0BACO,MAAA,mBAAyB,OAAA,CAAQ,MAAA;AAAA;AAAA,KAIlC,eAAA;EACV,UAAA;IAAe,QAAA;IAAkB,IAAA;EAAA;EACjC,IAAA;AAAA;AAAA,KAGG,uBAAA;EACH,OAAA,EAAS,uBAAA;EACT,IAAA,GAAO,SAAA,aAAsB,OAAA;IAAU,QAAA,EAAU,UAAA;EAAA;EACjD,SAAA;IACE,IAAA,GAAO,SAAA,aAAsB,OAAA;IAC7B,IAAA,GACE,SAAA,UACA,YAAA,UACA,OAAA,cACG,OAAA,CAAQ,eAAA;IACb,YAAA,GACE,SAAA,UACA,YAAA,aACG,OAAA;IACL,MAAA,GAAS,SAAA,UAAmB,YAAA,aAAyB,OAAA;EAAA;AAAA;;;;;;;;;;;;;;;;;;;;iBAuBzC,uBAAA,CACd,OAAA,EAAS,wBAAA,GACR,uBAAuB"}
1
+ {"version":3,"file":"AdkSessionAdapter.d.ts","names":[],"sources":["../src/AdkSessionAdapter.ts"],"mappings":";;;KAWY;;;;EAIV;;;;EAKA;;;;EAKA;;;;EAKA,UACI,gCACO,yBAAyB,QAAQ;;KAIlC;EACV;IAAe;IAAkB;;EACjC;;KAGG;EACH,SAAS;EACT,OAAO,sBAAsB;IAAU,UAAU;;EACjD;IACE,OAAO,sBAAsB;IAC7B,OACE,mBACA,sBACA,qBACG,QAAQ;IACb,eACE,mBACA,yBACG;IACL,SAAS,mBAAmB,yBAAyB;;;;;;;;;;;;;;;;;;;;;;iBAmJzC,wBACd,SAAS,2BACR"}
@@ -1,5 +1,49 @@
1
+ import { trimTrailingSlashes } from "./trimTrailingSlashes.js";
1
2
  import { AdkEventAccumulator } from "./AdkEventAccumulator.js";
2
3
  //#region src/AdkSessionAdapter.ts
4
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
5
+ const isAdkSessionResponse = (value) => {
6
+ if (!isRecord(value)) return false;
7
+ const id = value.id;
8
+ return typeof id === "string" && id.length > 0;
9
+ };
10
+ const parseAdkSessionResponse = (value, operation) => {
11
+ if (!isAdkSessionResponse(value)) throw new Error(`Invalid ADK session ${operation} response: expected an object with a non-empty string "id".`);
12
+ return value;
13
+ };
14
+ const parseAdkSessionListResponse = (value) => {
15
+ if (!Array.isArray(value)) throw new Error("Invalid ADK session list response: expected an array of sessions.");
16
+ return value.map((session, index) => {
17
+ if (!isAdkSessionResponse(session)) throw new Error(`Invalid ADK session list response: session at index ${index} must have a non-empty string "id".`);
18
+ return session;
19
+ });
20
+ };
21
+ const parseAdkArtifactListResponse = (value) => {
22
+ if (!Array.isArray(value)) throw new Error("Invalid ADK artifact list response: expected an array of artifact names.");
23
+ return value.map((artifact, index) => {
24
+ if (typeof artifact === "string" && artifact.length > 0) return artifact;
25
+ if (isRecord(artifact)) {
26
+ const filename = artifact.filename;
27
+ if (typeof filename === "string" && filename.length > 0) return filename;
28
+ }
29
+ throw new Error(`Invalid ADK artifact list response: artifact at index ${index} must be a non-empty string or an object with a non-empty string "filename".`);
30
+ });
31
+ };
32
+ const parseAdkArtifactResponse = (value) => {
33
+ if (!isRecord(value)) throw new Error("Invalid ADK artifact load response: expected an object containing \"text\" or \"inlineData\".");
34
+ const { text, inlineData } = value;
35
+ if (text === void 0 && inlineData === void 0) throw new Error("Invalid ADK artifact load response: expected an object containing \"text\" or \"inlineData\".");
36
+ if (text !== void 0 && typeof text !== "string") throw new Error("Invalid ADK artifact load response: \"text\" must be a string when present.");
37
+ if (inlineData !== void 0 && (!isRecord(inlineData) || typeof inlineData.mimeType !== "string" || typeof inlineData.data !== "string")) throw new Error("Invalid ADK artifact load response: \"inlineData\" must contain string \"mimeType\" and \"data\" fields.");
38
+ return value;
39
+ };
40
+ const parseAdkArtifactVersionsResponse = (value) => {
41
+ if (!Array.isArray(value)) throw new Error("Invalid ADK artifact versions response: expected an array of version numbers.");
42
+ return value.map((version, index) => {
43
+ if (typeof version !== "number" || !Number.isInteger(version) || version < 0) throw new Error(`Invalid ADK artifact versions response: version at index ${index} must be a non-negative integer.`);
44
+ return version;
45
+ });
46
+ };
3
47
  /**
4
48
  * Creates a `RemoteThreadListAdapter` backed by ADK's session REST API,
5
49
  * plus a `load` function that reconstructs messages from session events.
@@ -21,7 +65,7 @@ import { AdkEventAccumulator } from "./AdkEventAccumulator.js";
21
65
  */
22
66
  function createAdkSessionAdapter(options) {
23
67
  const { apiUrl, appName, userId } = options;
24
- const baseUrl = `${apiUrl}/apps/${encodeURIComponent(appName)}/users/${encodeURIComponent(userId)}/sessions`;
68
+ const baseUrl = `${trimTrailingSlashes(apiUrl)}/apps/${encodeURIComponent(appName)}/users/${encodeURIComponent(userId)}/sessions`;
25
69
  const getHeaders = async () => {
26
70
  if (!options.headers) return {};
27
71
  if (typeof options.headers === "function") return await options.headers();
@@ -32,7 +76,7 @@ function createAdkSessionAdapter(options) {
32
76
  const headers = await getHeaders();
33
77
  const res = await fetch(baseUrl, { headers });
34
78
  if (!res.ok) throw new Error(`Failed to list sessions: ${res.status}`);
35
- return { threads: (await res.json()).map((session) => ({
79
+ return { threads: parseAdkSessionListResponse(await res.json()).map((session) => ({
36
80
  status: "regular",
37
81
  remoteId: session.id,
38
82
  externalId: session.id,
@@ -50,7 +94,7 @@ function createAdkSessionAdapter(options) {
50
94
  body: JSON.stringify({})
51
95
  });
52
96
  if (!res.ok) throw new Error(`Failed to create session: ${res.status}`);
53
- const session = await res.json();
97
+ const session = parseAdkSessionResponse(await res.json(), "create");
54
98
  return {
55
99
  remoteId: session.id,
56
100
  externalId: session.id
@@ -68,13 +112,15 @@ function createAdkSessionAdapter(options) {
68
112
  async archive() {},
69
113
  async unarchive() {},
70
114
  generateTitle() {
71
- return Promise.resolve(new ReadableStream());
115
+ return Promise.resolve(new ReadableStream({ start(controller) {
116
+ controller.close();
117
+ } }));
72
118
  },
73
119
  async fetch(threadId) {
74
120
  const headers = await getHeaders();
75
121
  const res = await fetch(`${baseUrl}/${encodeURIComponent(threadId)}`, { headers });
76
122
  if (!res.ok) throw new Error(`Session not found: ${res.status}`);
77
- const session = await res.json();
123
+ const session = parseAdkSessionResponse(await res.json(), "fetch");
78
124
  return {
79
125
  status: "regular",
80
126
  remoteId: session.id,
@@ -87,11 +133,13 @@ function createAdkSessionAdapter(options) {
87
133
  const headers = await getHeaders();
88
134
  const res = await fetch(`${baseUrl}/${encodeURIComponent(sessionId)}`, { headers });
89
135
  if (!res.ok) throw new Error(`Failed to load session: ${res.status}`);
90
- const session = await res.json();
91
- if (!session.events?.length) return { messages: [] };
136
+ const session = parseAdkSessionResponse(await res.json(), "load");
137
+ if (session.events !== void 0 && !Array.isArray(session.events)) throw new Error("Invalid ADK session load response: expected \"events\" to be an array when present.");
138
+ const events = session.events;
139
+ if (!events?.length) return { messages: [] };
92
140
  const accumulator = new AdkEventAccumulator();
93
141
  let messages = [];
94
- for (const event of session.events) messages = accumulator.processEvent(event);
142
+ for (const event of events) messages = accumulator.processEvent(event);
95
143
  return { messages };
96
144
  };
97
145
  const artifactBaseUrl = (sessionId) => `${baseUrl}/${encodeURIComponent(sessionId)}/artifacts`;
@@ -103,7 +151,7 @@ function createAdkSessionAdapter(options) {
103
151
  const headers = await getHeaders();
104
152
  const res = await fetch(artifactBaseUrl(sessionId), { headers });
105
153
  if (!res.ok) throw new Error(`Failed to list artifacts: ${res.status}`);
106
- return (await res.json()).map((a) => a.filename);
154
+ return parseAdkArtifactListResponse(await res.json());
107
155
  },
108
156
  async load(sessionId, artifactName, version) {
109
157
  const headers = await getHeaders();
@@ -111,14 +159,14 @@ function createAdkSessionAdapter(options) {
111
159
  if (version != null) url += `/versions/${version}`;
112
160
  const res = await fetch(url, { headers });
113
161
  if (!res.ok) throw new Error(`Failed to load artifact: ${res.status}`);
114
- return await res.json();
162
+ return parseAdkArtifactResponse(await res.json());
115
163
  },
116
164
  async listVersions(sessionId, artifactName) {
117
165
  const headers = await getHeaders();
118
166
  const url = `${artifactBaseUrl(sessionId)}/${encodeURIComponent(artifactName)}/versions`;
119
167
  const res = await fetch(url, { headers });
120
168
  if (!res.ok) throw new Error(`Failed to list artifact versions: ${res.status}`);
121
- return await res.json();
169
+ return parseAdkArtifactVersionsResponse(await res.json());
122
170
  },
123
171
  async delete(sessionId, artifactName) {
124
172
  const headers = await getHeaders();
@@ -1 +1 @@
1
- {"version":3,"file":"AdkSessionAdapter.js","names":[],"sources":["../src/AdkSessionAdapter.ts"],"sourcesContent":["import type { AssistantStream, AssistantStreamChunk } from \"assistant-stream\";\nimport type {\n RemoteThreadInitializeResponse,\n RemoteThreadListAdapter,\n RemoteThreadListResponse,\n RemoteThreadMetadata,\n} from \"@assistant-ui/core\";\nimport { AdkEventAccumulator } from \"./AdkEventAccumulator\";\nimport type { AdkEvent, AdkMessage } from \"./types\";\n\nexport type AdkSessionAdapterOptions = {\n /**\n * ADK server base URL (e.g. \"http://localhost:8000\").\n */\n apiUrl: string;\n\n /**\n * ADK application name.\n */\n appName: string;\n\n /**\n * ADK user ID.\n */\n userId: string;\n\n /**\n * Extra headers for API requests.\n */\n headers?:\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>)\n | undefined;\n};\n\nexport type AdkArtifactData = {\n inlineData?: { mimeType: string; data: string } | undefined;\n text?: string | undefined;\n};\n\ntype AdkSessionAdapterResult = {\n adapter: RemoteThreadListAdapter;\n load: (sessionId: string) => Promise<{ messages: AdkMessage[] }>;\n artifacts: {\n list: (sessionId: string) => Promise<string[]>;\n load: (\n sessionId: string,\n artifactName: string,\n version?: number,\n ) => Promise<AdkArtifactData>;\n listVersions: (\n sessionId: string,\n artifactName: string,\n ) => Promise<number[]>;\n delete: (sessionId: string, artifactName: string) => Promise<void>;\n };\n};\n\n/**\n * Creates a `RemoteThreadListAdapter` backed by ADK's session REST API,\n * plus a `load` function that reconstructs messages from session events.\n *\n * @example\n * ```ts\n * const { adapter, load } = createAdkSessionAdapter({\n * apiUrl: \"http://localhost:8000\",\n * appName: \"my-app\",\n * userId: \"user-1\",\n * });\n *\n * const runtime = useAdkRuntime({\n * stream: createAdkStream({ ... }),\n * sessionAdapter: adapter,\n * load,\n * });\n * ```\n */\nexport function createAdkSessionAdapter(\n options: AdkSessionAdapterOptions,\n): AdkSessionAdapterResult {\n const { apiUrl, appName, userId } = options;\n const baseUrl = `${apiUrl}/apps/${encodeURIComponent(appName)}/users/${encodeURIComponent(userId)}/sessions`;\n\n const getHeaders = async (): Promise<Record<string, string>> => {\n if (!options.headers) return {};\n if (typeof options.headers === \"function\") return await options.headers();\n return options.headers;\n };\n\n const adapter: RemoteThreadListAdapter = {\n async list(): Promise<RemoteThreadListResponse> {\n const headers = await getHeaders();\n const res = await fetch(baseUrl, { headers });\n if (!res.ok) {\n throw new Error(`Failed to list sessions: ${res.status}`);\n }\n const data = (await res.json()) as Array<{\n id: string;\n app_name?: string;\n user_id?: string;\n last_update_time?: number;\n }>;\n\n const threads: RemoteThreadMetadata[] = data.map((session) => ({\n status: \"regular\" as const,\n remoteId: session.id,\n externalId: session.id,\n title: undefined,\n }));\n\n return { threads };\n },\n\n async initialize(\n _threadId: string,\n ): Promise<RemoteThreadInitializeResponse> {\n const headers = await getHeaders();\n const res = await fetch(baseUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...headers },\n body: JSON.stringify({}),\n });\n if (!res.ok) {\n throw new Error(`Failed to create session: ${res.status}`);\n }\n const session = (await res.json()) as { id: string };\n return { remoteId: session.id, externalId: session.id };\n },\n\n async delete(remoteId: string): Promise<void> {\n const headers = await getHeaders();\n const res = await fetch(`${baseUrl}/${encodeURIComponent(remoteId)}`, {\n method: \"DELETE\",\n headers,\n });\n if (!res.ok && res.status !== 404) {\n throw new Error(`Failed to delete session: ${res.status}`);\n }\n },\n\n async rename(): Promise<void> {\n // ADK sessions don't support titles\n },\n\n async archive(): Promise<void> {\n // ADK sessions don't support archiving\n },\n\n async unarchive(): Promise<void> {\n // ADK sessions don't support archiving\n },\n\n generateTitle(): Promise<AssistantStream> {\n // Title generation not supported without assistant-cloud\n return Promise.resolve(new ReadableStream<AssistantStreamChunk>());\n },\n\n async fetch(threadId: string): Promise<RemoteThreadMetadata> {\n const headers = await getHeaders();\n const res = await fetch(`${baseUrl}/${encodeURIComponent(threadId)}`, {\n headers,\n });\n if (!res.ok) {\n throw new Error(`Session not found: ${res.status}`);\n }\n const session = (await res.json()) as { id: string };\n return {\n status: \"regular\",\n remoteId: session.id,\n externalId: session.id,\n title: undefined,\n };\n },\n };\n\n const load = async (\n sessionId: string,\n ): Promise<{ messages: AdkMessage[] }> => {\n const headers = await getHeaders();\n const res = await fetch(`${baseUrl}/${encodeURIComponent(sessionId)}`, {\n headers,\n });\n if (!res.ok) {\n throw new Error(`Failed to load session: ${res.status}`);\n }\n const session = (await res.json()) as {\n id: string;\n events?: AdkEvent[];\n };\n\n if (!session.events?.length) {\n return { messages: [] };\n }\n\n const accumulator = new AdkEventAccumulator();\n let messages: AdkMessage[] = [];\n for (const event of session.events) {\n messages = accumulator.processEvent(event);\n }\n return { messages };\n };\n\n const artifactBaseUrl = (sessionId: string) =>\n `${baseUrl}/${encodeURIComponent(sessionId)}/artifacts`;\n\n const artifacts: AdkSessionAdapterResult[\"artifacts\"] = {\n async list(sessionId) {\n const headers = await getHeaders();\n const res = await fetch(artifactBaseUrl(sessionId), { headers });\n if (!res.ok) throw new Error(`Failed to list artifacts: ${res.status}`);\n const data = (await res.json()) as Array<{ filename: string }>;\n return data.map((a) => a.filename);\n },\n\n async load(sessionId, artifactName, version?) {\n const headers = await getHeaders();\n let url = `${artifactBaseUrl(sessionId)}/${encodeURIComponent(artifactName)}`;\n if (version != null) url += `/versions/${version}`;\n const res = await fetch(url, { headers });\n if (!res.ok) throw new Error(`Failed to load artifact: ${res.status}`);\n return (await res.json()) as AdkArtifactData;\n },\n\n async listVersions(sessionId, artifactName) {\n const headers = await getHeaders();\n const url = `${artifactBaseUrl(sessionId)}/${encodeURIComponent(artifactName)}/versions`;\n const res = await fetch(url, { headers });\n if (!res.ok) {\n throw new Error(`Failed to list artifact versions: ${res.status}`);\n }\n return (await res.json()) as number[];\n },\n\n async delete(sessionId, artifactName) {\n const headers = await getHeaders();\n const url = `${artifactBaseUrl(sessionId)}/${encodeURIComponent(artifactName)}`;\n const res = await fetch(url, { method: \"DELETE\", headers });\n if (!res.ok && res.status !== 404) {\n throw new Error(`Failed to delete artifact: ${res.status}`);\n }\n },\n };\n\n return { adapter, load, artifacts };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AdkSessionAdapter.js","names":[],"sources":["../src/AdkSessionAdapter.ts"],"sourcesContent":["import type { AssistantStream, AssistantStreamChunk } from \"assistant-stream\";\nimport type {\n RemoteThreadInitializeResponse,\n RemoteThreadListAdapter,\n RemoteThreadListResponse,\n RemoteThreadMetadata,\n} from \"@assistant-ui/core\";\nimport { AdkEventAccumulator } from \"./AdkEventAccumulator\";\nimport type { AdkEvent, AdkMessage } from \"./types\";\nimport { trimTrailingSlashes } from \"./trimTrailingSlashes\";\n\nexport type AdkSessionAdapterOptions = {\n /**\n * ADK server base URL (e.g. \"http://localhost:8000\").\n */\n apiUrl: string;\n\n /**\n * ADK application name.\n */\n appName: string;\n\n /**\n * ADK user ID.\n */\n userId: string;\n\n /**\n * Extra headers for API requests.\n */\n headers?:\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>)\n | undefined;\n};\n\nexport type AdkArtifactData = {\n inlineData?: { mimeType: string; data: string } | undefined;\n text?: string | undefined;\n};\n\ntype AdkSessionAdapterResult = {\n adapter: RemoteThreadListAdapter;\n load: (sessionId: string) => Promise<{ messages: AdkMessage[] }>;\n artifacts: {\n list: (sessionId: string) => Promise<string[]>;\n load: (\n sessionId: string,\n artifactName: string,\n version?: number,\n ) => Promise<AdkArtifactData>;\n listVersions: (\n sessionId: string,\n artifactName: string,\n ) => Promise<number[]>;\n delete: (sessionId: string, artifactName: string) => Promise<void>;\n };\n};\n\ntype AdkSessionResponse = {\n id: string;\n events?: unknown;\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst isAdkSessionResponse = (value: unknown): value is AdkSessionResponse => {\n if (!isRecord(value)) return false;\n\n const id = value.id;\n return typeof id === \"string\" && id.length > 0;\n};\n\nconst parseAdkSessionResponse = (\n value: unknown,\n operation: \"create\" | \"fetch\" | \"load\",\n): AdkSessionResponse => {\n if (!isAdkSessionResponse(value)) {\n throw new Error(\n `Invalid ADK session ${operation} response: expected an object with a non-empty string \"id\".`,\n );\n }\n return value;\n};\n\nconst parseAdkSessionListResponse = (value: unknown): AdkSessionResponse[] => {\n if (!Array.isArray(value)) {\n throw new Error(\n \"Invalid ADK session list response: expected an array of sessions.\",\n );\n }\n\n return value.map((session, index) => {\n if (!isAdkSessionResponse(session)) {\n throw new Error(\n `Invalid ADK session list response: session at index ${index} must have a non-empty string \"id\".`,\n );\n }\n return session;\n });\n};\n\nconst parseAdkArtifactListResponse = (value: unknown): string[] => {\n if (!Array.isArray(value)) {\n throw new Error(\n \"Invalid ADK artifact list response: expected an array of artifact names.\",\n );\n }\n\n return value.map((artifact, index) => {\n if (typeof artifact === \"string\" && artifact.length > 0) {\n return artifact;\n }\n\n if (isRecord(artifact)) {\n const filename = artifact.filename;\n if (typeof filename === \"string\" && filename.length > 0) {\n return filename;\n }\n }\n\n throw new Error(\n `Invalid ADK artifact list response: artifact at index ${index} must be a non-empty string or an object with a non-empty string \"filename\".`,\n );\n });\n};\n\nconst parseAdkArtifactResponse = (value: unknown): AdkArtifactData => {\n if (!isRecord(value)) {\n throw new Error(\n 'Invalid ADK artifact load response: expected an object containing \"text\" or \"inlineData\".',\n );\n }\n\n const { text, inlineData } = value;\n if (text === undefined && inlineData === undefined) {\n throw new Error(\n 'Invalid ADK artifact load response: expected an object containing \"text\" or \"inlineData\".',\n );\n }\n\n if (text !== undefined && typeof text !== \"string\") {\n throw new Error(\n 'Invalid ADK artifact load response: \"text\" must be a string when present.',\n );\n }\n\n if (\n inlineData !== undefined &&\n (!isRecord(inlineData) ||\n typeof inlineData.mimeType !== \"string\" ||\n typeof inlineData.data !== \"string\")\n ) {\n throw new Error(\n 'Invalid ADK artifact load response: \"inlineData\" must contain string \"mimeType\" and \"data\" fields.',\n );\n }\n\n return value as AdkArtifactData;\n};\n\nconst parseAdkArtifactVersionsResponse = (value: unknown): number[] => {\n if (!Array.isArray(value)) {\n throw new Error(\n \"Invalid ADK artifact versions response: expected an array of version numbers.\",\n );\n }\n\n return value.map((version, index) => {\n if (\n typeof version !== \"number\" ||\n !Number.isInteger(version) ||\n version < 0\n ) {\n throw new Error(\n `Invalid ADK artifact versions response: version at index ${index} must be a non-negative integer.`,\n );\n }\n return version;\n });\n};\n\n/**\n * Creates a `RemoteThreadListAdapter` backed by ADK's session REST API,\n * plus a `load` function that reconstructs messages from session events.\n *\n * @example\n * ```ts\n * const { adapter, load } = createAdkSessionAdapter({\n * apiUrl: \"http://localhost:8000\",\n * appName: \"my-app\",\n * userId: \"user-1\",\n * });\n *\n * const runtime = useAdkRuntime({\n * stream: createAdkStream({ ... }),\n * sessionAdapter: adapter,\n * load,\n * });\n * ```\n */\nexport function createAdkSessionAdapter(\n options: AdkSessionAdapterOptions,\n): AdkSessionAdapterResult {\n const { apiUrl, appName, userId } = options;\n const normalizedApiUrl = trimTrailingSlashes(apiUrl);\n const baseUrl = `${normalizedApiUrl}/apps/${encodeURIComponent(appName)}/users/${encodeURIComponent(userId)}/sessions`;\n\n const getHeaders = async (): Promise<Record<string, string>> => {\n if (!options.headers) return {};\n if (typeof options.headers === \"function\") return await options.headers();\n return options.headers;\n };\n\n const adapter: RemoteThreadListAdapter = {\n async list(): Promise<RemoteThreadListResponse> {\n const headers = await getHeaders();\n const res = await fetch(baseUrl, { headers });\n if (!res.ok) {\n throw new Error(`Failed to list sessions: ${res.status}`);\n }\n const data = parseAdkSessionListResponse(await res.json());\n\n const threads: RemoteThreadMetadata[] = data.map((session) => ({\n status: \"regular\" as const,\n remoteId: session.id,\n externalId: session.id,\n title: undefined,\n }));\n\n return { threads };\n },\n\n async initialize(\n _threadId: string,\n ): Promise<RemoteThreadInitializeResponse> {\n const headers = await getHeaders();\n const res = await fetch(baseUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...headers },\n body: JSON.stringify({}),\n });\n if (!res.ok) {\n throw new Error(`Failed to create session: ${res.status}`);\n }\n const session = parseAdkSessionResponse(await res.json(), \"create\");\n return { remoteId: session.id, externalId: session.id };\n },\n\n async delete(remoteId: string): Promise<void> {\n const headers = await getHeaders();\n const res = await fetch(`${baseUrl}/${encodeURIComponent(remoteId)}`, {\n method: \"DELETE\",\n headers,\n });\n if (!res.ok && res.status !== 404) {\n throw new Error(`Failed to delete session: ${res.status}`);\n }\n },\n\n async rename(): Promise<void> {\n // ADK sessions don't support titles\n },\n\n async archive(): Promise<void> {\n // ADK sessions don't support archiving\n },\n\n async unarchive(): Promise<void> {\n // ADK sessions don't support archiving\n },\n\n generateTitle(): Promise<AssistantStream> {\n // Title generation not supported without assistant-cloud\n return Promise.resolve(\n new ReadableStream<AssistantStreamChunk>({\n start(controller) {\n controller.close();\n },\n }),\n );\n },\n\n async fetch(threadId: string): Promise<RemoteThreadMetadata> {\n const headers = await getHeaders();\n const res = await fetch(`${baseUrl}/${encodeURIComponent(threadId)}`, {\n headers,\n });\n if (!res.ok) {\n throw new Error(`Session not found: ${res.status}`);\n }\n const session = parseAdkSessionResponse(await res.json(), \"fetch\");\n return {\n status: \"regular\",\n remoteId: session.id,\n externalId: session.id,\n title: undefined,\n };\n },\n };\n\n const load = async (\n sessionId: string,\n ): Promise<{ messages: AdkMessage[] }> => {\n const headers = await getHeaders();\n const res = await fetch(`${baseUrl}/${encodeURIComponent(sessionId)}`, {\n headers,\n });\n if (!res.ok) {\n throw new Error(`Failed to load session: ${res.status}`);\n }\n const session = parseAdkSessionResponse(await res.json(), \"load\");\n\n if (session.events !== undefined && !Array.isArray(session.events)) {\n throw new Error(\n 'Invalid ADK session load response: expected \"events\" to be an array when present.',\n );\n }\n\n const events = session.events as AdkEvent[] | undefined;\n\n if (!events?.length) {\n return { messages: [] };\n }\n\n const accumulator = new AdkEventAccumulator();\n let messages: AdkMessage[] = [];\n for (const event of events) {\n messages = accumulator.processEvent(event);\n }\n return { messages };\n };\n\n const artifactBaseUrl = (sessionId: string) =>\n `${baseUrl}/${encodeURIComponent(sessionId)}/artifacts`;\n\n const artifacts: AdkSessionAdapterResult[\"artifacts\"] = {\n async list(sessionId) {\n const headers = await getHeaders();\n const res = await fetch(artifactBaseUrl(sessionId), { headers });\n if (!res.ok) throw new Error(`Failed to list artifacts: ${res.status}`);\n return parseAdkArtifactListResponse(await res.json());\n },\n\n async load(sessionId, artifactName, version?) {\n const headers = await getHeaders();\n let url = `${artifactBaseUrl(sessionId)}/${encodeURIComponent(artifactName)}`;\n if (version != null) url += `/versions/${version}`;\n const res = await fetch(url, { headers });\n if (!res.ok) throw new Error(`Failed to load artifact: ${res.status}`);\n return parseAdkArtifactResponse(await res.json());\n },\n\n async listVersions(sessionId, artifactName) {\n const headers = await getHeaders();\n const url = `${artifactBaseUrl(sessionId)}/${encodeURIComponent(artifactName)}/versions`;\n const res = await fetch(url, { headers });\n if (!res.ok) {\n throw new Error(`Failed to list artifact versions: ${res.status}`);\n }\n return parseAdkArtifactVersionsResponse(await res.json());\n },\n\n async delete(sessionId, artifactName) {\n const headers = await getHeaders();\n const url = `${artifactBaseUrl(sessionId)}/${encodeURIComponent(artifactName)}`;\n const res = await fetch(url, { method: \"DELETE\", headers });\n if (!res.ok && res.status !== 404) {\n throw new Error(`Failed to delete artifact: ${res.status}`);\n }\n },\n };\n\n return { adapter, load, artifacts };\n}\n"],"mappings":"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"}
@@ -1,5 +1,4 @@
1
1
  import { AdkRuntimeExtras } from "./types.js";
2
-
3
2
  //#region src/adkExtras.d.ts
4
3
  declare const adkExtras: import("@assistant-ui/core/internal").RuntimeExtras<AdkRuntimeExtras>;
5
4
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"adkExtras.d.ts","names":[],"sources":["../src/adkExtras.ts"],"mappings":";;;cAGa,SAAA,wCAAS,aAAA,CAAA,gBAAA"}
1
+ {"version":3,"file":"adkExtras.d.ts","names":[],"sources":["../src/adkExtras.ts"],"mappings":";;cAGa,iDAAS,cAAA"}
@@ -1,5 +1,4 @@
1
1
  import { AdkEventPart, AdkMessage } from "./types.js";
2
-
3
2
  //#region src/contentToParts.d.ts
4
3
  declare const contentToParts: (content: AdkMessage["content"]) => AdkEventPart[];
5
4
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"contentToParts.d.ts","names":[],"sources":["../src/contentToParts.ts"],"mappings":";;;cAEa,cAAA,GACX,OAAA,EAAS,UAAA,gBACR,YAAY"}
1
+ {"version":3,"file":"contentToParts.d.ts","names":[],"sources":["../src/contentToParts.ts"],"mappings":";;cAEa,iBACX,SAAS,0BACR"}
@@ -1,6 +1,5 @@
1
1
  import { AdkMessage } from "./types.js";
2
2
  import { useExternalMessageConverter } from "@assistant-ui/core/react";
3
-
4
3
  //#region src/convertAdkMessages.d.ts
5
4
  declare const convertAdkMessage: useExternalMessageConverter.Callback<AdkMessage>;
6
5
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"convertAdkMessages.d.ts","names":[],"sources":["../src/convertAdkMessages.ts"],"mappings":";;;;cAkEa,iBAAA,EAAmB,2BAAA,CAA4B,QAAQ,CAClE,UAAA"}
1
+ {"version":3,"file":"convertAdkMessages.d.ts","names":[],"sources":["../src/convertAdkMessages.ts"],"mappings":";;;cAkEa,mBAAmB,4BAA4B,SAC1D"}
package/dist/hooks.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { AdkAuthCredential, AdkAuthRequest, AdkMessage, AdkMessageMetadata, AdkSendMessageConfig, AdkToolConfirmation } from "./types.js";
2
2
  import { ReadonlyJSONValue } from "assistant-stream/utils";
3
-
4
3
  //#region src/hooks.d.ts
5
4
  /** Returns the name and branch of the currently active ADK agent. */
6
5
  declare const useAdkAgentInfo: () => {
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","names":[],"sources":["../src/hooks.ts"],"mappings":";;;;;cAqBa,eAAA;EACiC,IAAA;EAAA,MAAA;AAAA;;cAGjC,kBAAA,QAAkB,MAAA;AAA/B;AAAA,cAIa,UAAA,SAEH,QAAA,EAAU,UAAA,IAAc,MAAA,EAAQ,oBAAA,KAAoB,OAAA;;cAKjD,wBAAA;AAXkB;AAAA,cAelB,uBAAA,QAAuB,mBAAA;;cAIvB,kBAAA,QAAkB,cAAA;;cAIlB,eAAA,QAAe,MAAA;;cAIf,gBAAA;;cAGA,qBAAA,QAAqB,GAAA,SAAA,kBAAA;;cAMrB,iBAAA,SAGT,UAAA,UACA,SAAA,WACA,OAAA,GAAU,iBAAA,KAAiB,OAAA;;cAqBlB,gBAAA,SAEH,UAAA,UAAoB,UAAA,EAAY,iBAAA,KAAiB,OAAA;;cAiB9C,iBAAA,SAEH,UAAA,UAAoB,MAAA,EAAQ,iBAAA,KAAiB,OAAA;AAxEvD;AAAA,cA4Ga,cAAA,QAAc,MAAA;;cAOd,eAAA,QAAe,MAAA;AAlH6C;AAAA,cAyH5D,eAAA,QAAe,MAAA"}
1
+ {"version":3,"file":"hooks.d.ts","names":[],"sources":["../src/hooks.ts"],"mappings":";;;;cAqBa;EAAA;EAAA;;;cAIA,0BAAkB;;cAIlB,mBAEH,UAAU,cAAc,QAAQ,yBAAoB;;cAKjD;;cAIA,+BAAuB;;cAIvB,0BAAkB;;cAIlB,uBAAe;;cAIf;;cAGA,6BAAqB,YAAA;;cAMrB,0BAGT,oBACA,oBACA,UAAU,sBAAiB;;cAqBlB,yBAEH,oBAAoB,YAAY,sBAAiB;;cAiB9C,0BAEH,oBAAoB,QAAQ,sBAAiB;;cAoC1C,sBAAc;;cAOd,uBAAe;;cAOf,uBAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"adkEventStream.d.ts","names":[],"sources":["../../src/server/adkEventStream.ts"],"mappings":";;;;KAKK,WAAA;EACH,EAAA;EACA,YAAA;EACA,MAAA;EACA,MAAA;EACA,OAAA;EACA,YAAA;EACA,WAAA;EACA,YAAA;EACA,SAAA;EACA,OAAA;IACE,IAAA;IACA,KAAA,GAAQ,KAAA,CAAM,MAAA;EAAA;EAEhB,OAAA,GAAU,MAAA;EACV,kBAAA;EACA,SAAA;EACA,YAAA;EACA,iBAAA;EACA,gBAAA;EACA,aAAA;EACA,cAAA,GAAiB,MAAA;AAAA;AAAA,KAyEP,qBAAA;EACV,OAAA,IAAW,KAAc;AAAA;;;;;;;AA1EF;AAyEzB;;;cAca,cAAA,GACX,MAAA,EAAQ,cAAA,CAAe,WAAA,oBACvB,OAAA,GAAU,qBAAA,KACT,QAAA"}
1
+ {"version":3,"file":"adkEventStream.d.ts","names":[],"sources":["../../src/server/adkEventStream.ts"],"mappings":";;;;KAKK;EACH;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;IACE;IACA,QAAQ,MAAM;;EAEhB,UAAU;EACV;EACA;EACA;EACA;EACA;EACA;EACA,iBAAiB;;KAyEP;EACV,WAAW;;;;;;;;;;;;cAaA,iBACX,QAAQ,eAAe,+BACvB,UAAU,0BACT"}
@@ -1,5 +1,4 @@
1
1
  import { AdkEventStreamOptions } from "./adkEventStream.js";
2
-
3
2
  //#region src/server/createAdkApiRoute.d.ts
4
3
  /**
5
4
  * Loose runner type matching the ADK SDK's Runner interface.
@@ -1 +1 @@
1
- {"version":3,"file":"createAdkApiRoute.d.ts","names":[],"sources":["../../src/server/createAdkApiRoute.ts"],"mappings":";;;;;AAC8E;;KAMzE,SAAA;EACH,QAAA,CACE,OAAA,EAAS,MAAA,oBACR,cAAc;AAAA;AAAA,KAGP,wBAAA;EAJR;;;EAQF,MAAA,EAAQ,SAAA;EAJE;;;;EAUV,MAAA,aAAmB,GAAA,EAAK,OAAA,cAAqB,OAAA;EAAA;;;;EAM7C,SAAA,aAAsB,GAAA,EAAK,OAAA,cAAqB,OAAA;EAKjB;;;EAA/B,OAAA,GAAU,qBAAA;AAAA;;;;;;;;;;AAAqB;AAmBjC;;;;;;iBAAgB,iBAAA,CACd,OAAA,EAAS,wBAAA,IACP,GAAA,EAAK,OAAA,KAAY,OAAA,CAAQ,QAAA"}
1
+ {"version":3,"file":"createAdkApiRoute.d.ts","names":[],"sources":["../../src/server/createAdkApiRoute.ts"],"mappings":";;;;;;KAOK;EACH,SACE,SAAS,0BACR;;KAGO;;;;EAIV,QAAQ;;;;;EAMR,mBAAmB,KAAK,qBAAqB;;;;;EAM7C,sBAAsB,KAAK,qBAAqB;;;;EAKhD,UAAU;;;;;;;;;;;;;;;;;;iBAmBI,kBACd,SAAS,4BACP,KAAK,YAAY,QAAQ"}
@@ -1,5 +1,4 @@
1
1
  import { AdkSendMessageConfig } from "../types.js";
2
-
3
2
  //#region src/server/parseAdkRequest.d.ts
4
3
  type ParsedAdkRequest = {
5
4
  type: "message";
@@ -1 +1 @@
1
- {"version":3,"file":"parseAdkRequest.d.ts","names":[],"sources":["../../src/server/parseAdkRequest.ts"],"mappings":";;;KAEK,gBAAA;EAEC,IAAA;EACA,IAAA;EACA,KAAA,GAAQ,KAAA,CAAM,MAAA;EACd,MAAA,EAAQ,oBAAA;EACR,UAAA,GAAa,MAAA;AAAA;EAGb,IAAA;EACA,UAAA;EACA,QAAA;EACA,MAAA;EACA,OAAA;EACA,MAAA,EAAQ,oBAAA;EACR,UAAA,GAAa,MAAA;AAAA;;;;;;;;;;;;;;;;;;AAAM;AAwBzB;;;cAAa,eAAA,GACX,OAAA,EAAS,OAAA,KACR,OAAA,CAAQ,gBAAA;;;;;;;;;;AAAgB;AAsD3B;;cAAa,YAAA,GACX,MAAA,EAAQ,gBAAA;EACL,IAAA;EAAc,KAAA,EAAO,KAAA,CAAM,MAAA;AAAA"}
1
+ {"version":3,"file":"parseAdkRequest.d.ts","names":[],"sources":["../../src/server/parseAdkRequest.ts"],"mappings":";;KAEK;EAEC;EACA;EACA,QAAQ,MAAM;EACd,QAAQ;EACR,aAAa;;EAGb;EACA;EACA;EACA;EACA;EACA,QAAQ;EACR,aAAa;;;;;;;;;;;;;;;;;;;;;;;cAwBN,kBACX,SAAS,YACR,QAAQ;;;;;;;;;;;;;cAwDE,eACX,QAAQ;EACL;EAAc,OAAO,MAAM"}
@@ -25,9 +25,9 @@ const parseAdkRequest = async (request) => {
25
25
  try {
26
26
  body = await request.json();
27
27
  } catch {
28
- throw new Error("Invalid JSON in request body");
28
+ throw new Error("Invalid JSON in Google ADK proxy request body. Expected a JSON object like {\"message\":\"Hello\"} or {\"type\":\"tool-result\",...}.");
29
29
  }
30
- if (!body || typeof body !== "object" || Array.isArray(body)) throw new Error("Request body must be a JSON object");
30
+ if (!body || typeof body !== "object" || Array.isArray(body)) throw new Error("Google ADK proxy request body must be a JSON object");
31
31
  const config = {};
32
32
  if (body.runConfig !== void 0) config.runConfig = body.runConfig;
33
33
  if (body.checkpointId !== void 0) config.checkpointId = body.checkpointId;
@@ -1 +1 @@
1
- {"version":3,"file":"parseAdkRequest.js","names":[],"sources":["../../src/server/parseAdkRequest.ts"],"sourcesContent":["import type { AdkSendMessageConfig } from \"../types\";\n\ntype ParsedAdkRequest =\n | {\n type: \"message\";\n text: string;\n parts?: Array<Record<string, unknown>> | undefined;\n config: AdkSendMessageConfig;\n stateDelta?: Record<string, unknown> | undefined;\n }\n | {\n type: \"tool-result\";\n toolCallId: string;\n toolName: string;\n result: unknown;\n isError: boolean;\n config: AdkSendMessageConfig;\n stateDelta?: Record<string, unknown> | undefined;\n };\n\n/**\n * Parses an incoming HTTP request into a structured ADK request.\n *\n * Supports two request shapes:\n *\n * 1. User message:\n * ```json\n * { \"message\": \"Hello\", \"runConfig\": {}, \"stateDelta\": {} }\n * ```\n *\n * 2. Tool result:\n * ```json\n * {\n * \"type\": \"tool-result\",\n * \"toolCallId\": \"call_123\",\n * \"toolName\": \"search\",\n * \"result\": { ... },\n * \"isError\": false\n * }\n * ```\n */\nexport const parseAdkRequest = async (\n request: Request,\n): Promise<ParsedAdkRequest> => {\n let body: Record<string, unknown>;\n try {\n body = (await request.json()) as Record<string, unknown>;\n } catch {\n throw new Error(\"Invalid JSON in request body\");\n }\n\n if (!body || typeof body !== \"object\" || Array.isArray(body)) {\n throw new Error(\"Request body must be a JSON object\");\n }\n\n const config: AdkSendMessageConfig = {};\n if (body.runConfig !== undefined) config.runConfig = body.runConfig;\n if (body.checkpointId !== undefined)\n config.checkpointId = body.checkpointId as string;\n\n const stateDelta = body.stateDelta as Record<string, unknown> | undefined;\n\n if (body.type === \"tool-result\") {\n return {\n type: \"tool-result\",\n toolCallId: (body.toolCallId as string) ?? \"\",\n toolName: (body.toolName as string) ?? \"\",\n result: body.result,\n isError: (body.isError as boolean) ?? false,\n config,\n ...(stateDelta != null && { stateDelta }),\n };\n }\n\n return {\n type: \"message\",\n text: (body.message as string) ?? \"\",\n ...(body.parts != null && {\n parts: body.parts as Array<Record<string, unknown>>,\n }),\n config,\n ...(stateDelta != null && { stateDelta }),\n };\n};\n\n/**\n * Converts a parsed ADK request into a Google GenAI Content object\n * suitable for `Runner.runAsync({ newMessage })`.\n *\n * @example\n * ```ts\n * const parsed = await parseAdkRequest(req);\n * const newMessage = toAdkContent(parsed);\n * const events = runner.runAsync({ userId, sessionId, newMessage, stateDelta: parsed.stateDelta });\n * return adkEventStream(events);\n * ```\n */\nexport const toAdkContent = (\n parsed: ParsedAdkRequest,\n): { role: string; parts: Array<Record<string, unknown>> } => {\n if (parsed.type === \"tool-result\") {\n return {\n role: \"user\",\n parts: [\n {\n functionResponse: {\n name: parsed.toolName,\n id: parsed.toolCallId,\n response: parsed.result,\n },\n },\n ],\n };\n }\n\n // If raw parts are provided (multimodal), use them directly\n if (parsed.parts?.length) {\n return { role: \"user\", parts: parsed.parts };\n }\n\n return { role: \"user\", parts: [{ text: parsed.text }] };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAyCA,MAAa,kBAAkB,OAC7B,YAC8B;CAC9B,IAAI;CACJ,IAAI;EACF,OAAQ,MAAM,QAAQ,KAAK;CAC7B,QAAQ;EACN,MAAM,IAAI,MAAM,8BAA8B;CAChD;CAEA,IAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,GACzD,MAAM,IAAI,MAAM,oCAAoC;CAGtD,MAAM,SAA+B,CAAC;CACtC,IAAI,KAAK,cAAc,KAAA,GAAW,OAAO,YAAY,KAAK;CAC1D,IAAI,KAAK,iBAAiB,KAAA,GACxB,OAAO,eAAe,KAAK;CAE7B,MAAM,aAAa,KAAK;CAExB,IAAI,KAAK,SAAS,eAChB,OAAO;EACL,MAAM;EACN,YAAa,KAAK,cAAyB;EAC3C,UAAW,KAAK,YAAuB;EACvC,QAAQ,KAAK;EACb,SAAU,KAAK,WAAuB;EACtC;EACA,GAAI,cAAc,QAAQ,EAAE,WAAW;CACzC;CAGF,OAAO;EACL,MAAM;EACN,MAAO,KAAK,WAAsB;EAClC,GAAI,KAAK,SAAS,QAAQ,EACxB,OAAO,KAAK,MACd;EACA;EACA,GAAI,cAAc,QAAQ,EAAE,WAAW;CACzC;AACF;;;;;;;;;;;;;AAcA,MAAa,gBACX,WAC4D;CAC5D,IAAI,OAAO,SAAS,eAClB,OAAO;EACL,MAAM;EACN,OAAO,CACL,EACE,kBAAkB;GAChB,MAAM,OAAO;GACb,IAAI,OAAO;GACX,UAAU,OAAO;EACnB,EACF,CACF;CACF;CAIF,IAAI,OAAO,OAAO,QAChB,OAAO;EAAE,MAAM;EAAQ,OAAO,OAAO;CAAM;CAG7C,OAAO;EAAE,MAAM;EAAQ,OAAO,CAAC,EAAE,MAAM,OAAO,KAAK,CAAC;CAAE;AACxD"}
1
+ {"version":3,"file":"parseAdkRequest.js","names":[],"sources":["../../src/server/parseAdkRequest.ts"],"sourcesContent":["import type { AdkSendMessageConfig } from \"../types\";\n\ntype ParsedAdkRequest =\n | {\n type: \"message\";\n text: string;\n parts?: Array<Record<string, unknown>> | undefined;\n config: AdkSendMessageConfig;\n stateDelta?: Record<string, unknown> | undefined;\n }\n | {\n type: \"tool-result\";\n toolCallId: string;\n toolName: string;\n result: unknown;\n isError: boolean;\n config: AdkSendMessageConfig;\n stateDelta?: Record<string, unknown> | undefined;\n };\n\n/**\n * Parses an incoming HTTP request into a structured ADK request.\n *\n * Supports two request shapes:\n *\n * 1. User message:\n * ```json\n * { \"message\": \"Hello\", \"runConfig\": {}, \"stateDelta\": {} }\n * ```\n *\n * 2. Tool result:\n * ```json\n * {\n * \"type\": \"tool-result\",\n * \"toolCallId\": \"call_123\",\n * \"toolName\": \"search\",\n * \"result\": { ... },\n * \"isError\": false\n * }\n * ```\n */\nexport const parseAdkRequest = async (\n request: Request,\n): Promise<ParsedAdkRequest> => {\n let body: Record<string, unknown>;\n try {\n body = (await request.json()) as Record<string, unknown>;\n } catch {\n throw new Error(\n 'Invalid JSON in Google ADK proxy request body. Expected a JSON object like {\"message\":\"Hello\"} or {\"type\":\"tool-result\",...}.',\n );\n }\n\n if (!body || typeof body !== \"object\" || Array.isArray(body)) {\n throw new Error(\"Google ADK proxy request body must be a JSON object\");\n }\n\n const config: AdkSendMessageConfig = {};\n if (body.runConfig !== undefined) config.runConfig = body.runConfig;\n if (body.checkpointId !== undefined)\n config.checkpointId = body.checkpointId as string;\n\n const stateDelta = body.stateDelta as Record<string, unknown> | undefined;\n\n if (body.type === \"tool-result\") {\n return {\n type: \"tool-result\",\n toolCallId: (body.toolCallId as string) ?? \"\",\n toolName: (body.toolName as string) ?? \"\",\n result: body.result,\n isError: (body.isError as boolean) ?? false,\n config,\n ...(stateDelta != null && { stateDelta }),\n };\n }\n\n return {\n type: \"message\",\n text: (body.message as string) ?? \"\",\n ...(body.parts != null && {\n parts: body.parts as Array<Record<string, unknown>>,\n }),\n config,\n ...(stateDelta != null && { stateDelta }),\n };\n};\n\n/**\n * Converts a parsed ADK request into a Google GenAI Content object\n * suitable for `Runner.runAsync({ newMessage })`.\n *\n * @example\n * ```ts\n * const parsed = await parseAdkRequest(req);\n * const newMessage = toAdkContent(parsed);\n * const events = runner.runAsync({ userId, sessionId, newMessage, stateDelta: parsed.stateDelta });\n * return adkEventStream(events);\n * ```\n */\nexport const toAdkContent = (\n parsed: ParsedAdkRequest,\n): { role: string; parts: Array<Record<string, unknown>> } => {\n if (parsed.type === \"tool-result\") {\n return {\n role: \"user\",\n parts: [\n {\n functionResponse: {\n name: parsed.toolName,\n id: parsed.toolCallId,\n response: parsed.result,\n },\n },\n ],\n };\n }\n\n // If raw parts are provided (multimodal), use them directly\n if (parsed.parts?.length) {\n return { role: \"user\", parts: parsed.parts };\n }\n\n return { role: \"user\", parts: [{ text: parsed.text }] };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAyCA,MAAa,kBAAkB,OAC7B,YAC8B;CAC9B,IAAI;CACJ,IAAI;EACF,OAAQ,MAAM,QAAQ,KAAK;CAC7B,QAAQ;EACN,MAAM,IAAI,MACR,uIACF;CACF;CAEA,IAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,GACzD,MAAM,IAAI,MAAM,qDAAqD;CAGvE,MAAM,SAA+B,CAAC;CACtC,IAAI,KAAK,cAAc,KAAA,GAAW,OAAO,YAAY,KAAK;CAC1D,IAAI,KAAK,iBAAiB,KAAA,GACxB,OAAO,eAAe,KAAK;CAE7B,MAAM,aAAa,KAAK;CAExB,IAAI,KAAK,SAAS,eAChB,OAAO;EACL,MAAM;EACN,YAAa,KAAK,cAAyB;EAC3C,UAAW,KAAK,YAAuB;EACvC,QAAQ,KAAK;EACb,SAAU,KAAK,WAAuB;EACtC;EACA,GAAI,cAAc,QAAQ,EAAE,WAAW;CACzC;CAGF,OAAO;EACL,MAAM;EACN,MAAO,KAAK,WAAsB;EAClC,GAAI,KAAK,SAAS,QAAQ,EACxB,OAAO,KAAK,MACd;EACA;EACA,GAAI,cAAc,QAAQ,EAAE,WAAW;CACzC;AACF;;;;;;;;;;;;;AAcA,MAAa,gBACX,WAC4D;CAC5D,IAAI,OAAO,SAAS,eAClB,OAAO;EACL,MAAM;EACN,OAAO,CACL,EACE,kBAAkB;GAChB,MAAM,OAAO;GACb,IAAI,OAAO;GACX,UAAU,OAAO;EACnB,EACF,CACF;CACF;CAIF,IAAI,OAAO,OAAO,QAChB,OAAO;EAAE,MAAM;EAAQ,OAAO,OAAO;CAAM;CAG7C,OAAO;EAAE,MAAM;EAAQ,OAAO,CAAC,EAAE,MAAM,OAAO,KAAK,CAAC;CAAE;AACxD"}
@@ -1,5 +1,4 @@
1
1
  import { AdkEvent, AdkStructuredEvent } from "./types.js";
2
-
3
2
  //#region src/structuredEvents.d.ts
4
3
  /**
5
4
  * Converts a raw `AdkEvent` into an array of structured, typed events.
@@ -1 +1 @@
1
- {"version":3,"file":"structuredEvents.d.ts","names":[],"sources":["../src/structuredEvents.ts"],"mappings":";;;;;AAOA;;iBAAgB,qBAAA,CAAsB,KAAA,EAAO,QAAA,GAAW,kBAAkB"}
1
+ {"version":3,"file":"structuredEvents.d.ts","names":[],"sources":["../src/structuredEvents.ts"],"mappings":";;;;;;iBAOgB,sBAAsB,OAAO,WAAW"}
@@ -0,0 +1,5 @@
1
+ //#region src/trimTrailingSlashes.d.ts
2
+ declare const trimTrailingSlashes: (value: string) => string;
3
+ //#endregion
4
+ export { trimTrailingSlashes };
5
+ //# sourceMappingURL=trimTrailingSlashes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trimTrailingSlashes.d.ts","names":[],"sources":["../src/trimTrailingSlashes.ts"],"mappings":";cAAa,sBAAuB"}
@@ -0,0 +1,10 @@
1
+ //#region src/trimTrailingSlashes.ts
2
+ const trimTrailingSlashes = (value) => {
3
+ let end = value.length;
4
+ while (end > 0 && value[end - 1] === "/") end -= 1;
5
+ return value.slice(0, end);
6
+ };
7
+ //#endregion
8
+ export { trimTrailingSlashes };
9
+
10
+ //# sourceMappingURL=trimTrailingSlashes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trimTrailingSlashes.js","names":[],"sources":["../src/trimTrailingSlashes.ts"],"sourcesContent":["export const trimTrailingSlashes = (value: string) => {\n let end = value.length;\n while (end > 0 && value[end - 1] === \"/\") end -= 1;\n return value.slice(0, end);\n};\n"],"mappings":";AAAA,MAAa,uBAAuB,UAAkB;CACpD,IAAI,MAAM,MAAM;CAChB,OAAO,MAAM,KAAK,MAAM,MAAM,OAAO,KAAK,OAAO;CACjD,OAAO,MAAM,MAAM,GAAG,GAAG;AAC3B"}
package/dist/types.d.ts CHANGED
@@ -1,6 +1,5 @@
1
- import { MessageStatus } from "@assistant-ui/core";
2
1
  import { ReadonlyJSONObject } from "assistant-stream/utils";
3
-
2
+ import { MessageStatus } from "@assistant-ui/core";
4
3
  //#region src/types.d.ts
5
4
  type AdkEventPart = {
6
5
  text?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"mappings":";;;KAKY;EACV;EACA;EACA;IACE;IACA;IACA,MAAM;;EAER;IACE;IACA;IACA;;EAEF;IACE;IACA;;EAEF;IACE;IACA;;EAEF;IACE;IACA;;EAEF;IACE;IACA;;;KAIQ;EACV,aAAa;EACb,gBAAgB;EAChB;EACA;EACA;EACA,uBAAuB;EACvB,6BAA6B;;KAGnB;EACV;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;IAEM;IACA,QAAQ;;EAGd,UAAU;EACV;EACA;EACA;EACA;EACA;EACA;EACA,iBAAiB;;KAKP;EACV;EACA;EACA,MAAM;EACN;;KAGU;EAEN;EACA;EACA,kBAAkB;;EAGlB;EACA;EACA,kBAAkB;EAClB,aAAa;EACb;EACA;EACA,SAAS;;EAGT;EACA;EACA;EACA;EACA;EACA;EACA;;KAGM;EACN;EAAc;;EACd;EAAmB;;EACnB;EAAe;EAAkB;;EACjC;EAAmB;;EAEnB;EACA;EACA;EACA;;EAGA;EACA;EACA;;EAEA;EAAc;EAAc;;EAC5B;EAAqB;EAAgB;;EACrC;EAAkB;;KAIZ;EACV;EACA;EACA,MAAM;EACN;EACA;EACA;;KAGU;KAOA;EACV,UAAU;EACV;EACA;EACA;IAEM;IACA;MACE;MACA;MACA;;;EAIR;IAEM;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;EAGN;;KAGU;EACV;EACA;;KAGU;EACV;EACA;EACA;;KAKU;EACV;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;KAKU;;;;;;EAMV;EACA;EACA,aAAa;;cAKF;;;;;;;;;;;;KAaD;EACN;EAAiB;;EACjB;EAAiB;;EAEjB;EACA;IAAQ;IAAc;IAAa,MAAM;;;EAGzC;EACA;IAAU;IAAc;IAAa;;;EAErC;EAAmB;IAAQ;IAAc;;;EACzC;EAAqB;IAAU;IAAgB;;;EAC/C;EAAe;EAAoB;;EACnC;EAAkB;;EAElB;EACA,eAAe;;EAEf;;KAEM,qBACV,UAAU,cACV,QAAQ;EACN,aAAa;EACb,kBAAkB;IAChB;IACA;;MAGD,QAAQ,eAAe,aAAa,eAAe;KAI5C,sBAAsB,0BAA0B;KAEhD,4BACV,cACA,yBACU;KAEA,8BACV,2BACU;;KAGA;EACV,OAAO,UAAU,cAAc,QAAQ,yBAAyB;EAChE;IAAa;IAA2B;;EACxC,YAAY;EACZ,eAAe;EACf;EACA,mBAAmB;EACnB,cAAc;EACd;EACA,iBAAiB,YAAY"}
@@ -1,5 +1,4 @@
1
1
  import { AdkAuthRequest, AdkMessage, AdkMessageMetadata, AdkSendMessageConfig, AdkStreamCallback, AdkToolConfirmation, OnAdkAgentTransferCallback, OnAdkCustomEventCallback, OnAdkErrorCallback } from "./types.js";
2
-
3
2
  //#region src/useAdkMessages.d.ts
4
3
  type UseAdkMessagesOptions = {
5
4
  stream: AdkStreamCallback;
@@ -9,10 +8,7 @@ type UseAdkMessagesOptions = {
9
8
  onAgentTransfer?: OnAdkAgentTransferCallback;
10
9
  };
11
10
  };
12
- declare const useAdkMessages: ({
13
- stream,
14
- eventHandlers
15
- }: UseAdkMessagesOptions) => {
11
+ declare const useAdkMessages: ({ stream, eventHandlers }: UseAdkMessagesOptions) => {
16
12
  messages: AdkMessage[];
17
13
  stateDelta: Record<string, unknown>;
18
14
  agentInfo: {
@@ -1 +1 @@
1
- {"version":3,"file":"useAdkMessages.d.ts","names":[],"sources":["../src/useAdkMessages.ts"],"mappings":";;;KAkBY,qBAAA;EACV,MAAA,EAAQ,iBAAA;EACR,aAAA;IACE,OAAA,GAAU,kBAAA;IACV,aAAA,GAAgB,wBAAA;IAChB,eAAA,GAAkB,0BAAA;EAAA;AAAA;AAAA,cAIT,cAAA;EAAkB,MAAA;EAAA;AAAA,GAG5B,qBAAA;;;;;;;;;;;;;6BA2DqB,UAAA,IAAY,MAAA,EAAU,oBAAA,KAAoB,OAAA;;sBA9BhB,UAAA;0BAUvC,UAAA;AAAA"}
1
+ {"version":3,"file":"useAdkMessages.d.ts","names":[],"sources":["../src/useAdkMessages.ts"],"mappings":";;KAkBY;EACV,QAAQ;EACR;IACE,UAAU;IACV,gBAAgB;IAChB,kBAAkB;;;cAIT,mBAAkB,QAAA,iBAG5B;;;;IAIQ;IACE;;;;;;;;EAsDW,cAAA,aAAA,cAAY,QAAU,yBAAoB;;EA9BhB,cAAA,MAAA;EAUvC,kBAAA,MAAA"}
@@ -67,7 +67,8 @@ const useAdkMessages = ({ stream, eventHandlers }) => {
67
67
  }
68
68
  });
69
69
  for await (const event of response) {
70
- setMessagesImmediate(accumulator.processEvent(event));
70
+ const updatedMessages = accumulator.processEvent(event);
71
+ setMessagesImmediate(updatedMessages);
71
72
  setStateDelta({
72
73
  ...stateDeltaRef.current,
73
74
  ...accumulator.getStateDelta()