@assistant-ui/react-google-adk 0.0.25 → 0.0.27

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 (58) hide show
  1. package/dist/AdkClient.d.ts.map +1 -1
  2. package/dist/AdkClient.js +13 -3
  3. package/dist/AdkClient.js.map +1 -1
  4. package/dist/AdkEventAccumulator.d.ts +2 -0
  5. package/dist/AdkEventAccumulator.d.ts.map +1 -1
  6. package/dist/AdkEventAccumulator.js +32 -10
  7. package/dist/AdkEventAccumulator.js.map +1 -1
  8. package/dist/AdkSessionAdapter.d.ts.map +1 -1
  9. package/dist/AdkSessionAdapter.js +2 -1
  10. package/dist/AdkSessionAdapter.js.map +1 -1
  11. package/dist/adkToolApproval.d.ts +40 -0
  12. package/dist/adkToolApproval.d.ts.map +1 -0
  13. package/dist/adkToolApproval.js +166 -0
  14. package/dist/adkToolApproval.js.map +1 -0
  15. package/dist/convertAdkMessages.d.ts +3 -1
  16. package/dist/convertAdkMessages.d.ts.map +1 -1
  17. package/dist/convertAdkMessages.js +27 -16
  18. package/dist/convertAdkMessages.js.map +1 -1
  19. package/dist/convertToAdkMessages.d.ts +49 -0
  20. package/dist/convertToAdkMessages.d.ts.map +1 -0
  21. package/dist/convertToAdkMessages.js +86 -0
  22. package/dist/convertToAdkMessages.js.map +1 -0
  23. package/dist/hooks.d.ts.map +1 -1
  24. package/dist/hooks.js +5 -14
  25. package/dist/hooks.js.map +1 -1
  26. package/dist/parseAdkEvent.d.ts +6 -0
  27. package/dist/parseAdkEvent.d.ts.map +1 -0
  28. package/dist/parseAdkEvent.js +16 -0
  29. package/dist/parseAdkEvent.js.map +1 -0
  30. package/dist/server/parseAdkRequest.d.ts.map +1 -1
  31. package/dist/server/parseAdkRequest.js +79 -13
  32. package/dist/server/parseAdkRequest.js.map +1 -1
  33. package/dist/useAdkMessages.d.ts.map +1 -1
  34. package/dist/useAdkMessages.js +110 -79
  35. package/dist/useAdkMessages.js.map +1 -1
  36. package/dist/useAdkRuntime.d.ts.map +1 -1
  37. package/dist/useAdkRuntime.js +44 -129
  38. package/dist/useAdkRuntime.js.map +1 -1
  39. package/package.json +6 -7
  40. package/src/AdkClient.test.ts +137 -0
  41. package/src/AdkClient.ts +15 -3
  42. package/src/AdkEventAccumulator.test.ts +161 -1
  43. package/src/AdkEventAccumulator.ts +44 -8
  44. package/src/AdkSessionAdapter.test.ts +145 -1
  45. package/src/AdkSessionAdapter.ts +7 -2
  46. package/src/adkToolApproval.test.ts +345 -0
  47. package/src/adkToolApproval.ts +215 -0
  48. package/src/convertAdkMessages.ts +72 -43
  49. package/src/{useAdkRuntime.test.ts → convertToAdkMessages.test.ts} +1 -1
  50. package/src/convertToAdkMessages.ts +139 -0
  51. package/src/hooks.ts +7 -19
  52. package/src/parseAdkEvent.ts +40 -0
  53. package/src/server/parseAdkRequest.test.ts +141 -0
  54. package/src/server/parseAdkRequest.ts +145 -13
  55. package/src/useAdkMessages.test.ts +313 -0
  56. package/src/useAdkMessages.ts +72 -25
  57. package/src/useAdkRuntime.ts +66 -188
  58. package/src/useAdkRuntimeApproval.test.tsx +344 -0
@@ -1,4 +1,57 @@
1
+ import { isRecord } from "@assistant-ui/core/internal";
1
2
  //#region src/server/parseAdkRequest.ts
3
+ const invalidField = (field, expectation) => /* @__PURE__ */ new Error(`Invalid Google ADK proxy request field "${field}": expected ${expectation}.`);
4
+ const readString = (body, field) => {
5
+ const value = body[field];
6
+ if (typeof value !== "string") throw invalidField(field, "a string");
7
+ return value;
8
+ };
9
+ const readOptionalString = (body, field) => {
10
+ const value = body[field];
11
+ if (value === void 0) return void 0;
12
+ if (typeof value !== "string") throw invalidField(field, "a string");
13
+ return value;
14
+ };
15
+ const validateOptionalPartString = (part, key, field) => {
16
+ if (part[key] !== void 0 && typeof part[key] !== "string") throw invalidField(field, "a string");
17
+ };
18
+ const validatePart = (part, index) => {
19
+ const field = (name) => `parts[${index}].${name}`;
20
+ if (Object.keys(part).length === 0) throw invalidField(`parts[${index}]`, "a non-empty part object");
21
+ if (part.thought !== void 0 && typeof part.thought !== "boolean") throw invalidField(field("thought"), "a boolean");
22
+ if (part.text !== void 0 && typeof part.text !== "string") throw invalidField(field("text"), "a string");
23
+ const validateRecordField = (key, validateContent) => {
24
+ const value = part[key];
25
+ if (value === void 0) return;
26
+ if (!isRecord(value)) throw invalidField(field(key), "an object");
27
+ validateContent(value);
28
+ };
29
+ validateRecordField("functionCall", (content) => {
30
+ validateOptionalPartString(content, "name", field("functionCall.name"));
31
+ validateOptionalPartString(content, "id", field("functionCall.id"));
32
+ if (content.args !== void 0 && !isRecord(content.args)) throw invalidField(field("functionCall.args"), "an object");
33
+ });
34
+ validateRecordField("functionResponse", (content) => {
35
+ validateOptionalPartString(content, "name", field("functionResponse.name"));
36
+ validateOptionalPartString(content, "id", field("functionResponse.id"));
37
+ });
38
+ validateRecordField("executableCode", (content) => {
39
+ validateOptionalPartString(content, "code", field("executableCode.code"));
40
+ validateOptionalPartString(content, "language", field("executableCode.language"));
41
+ });
42
+ validateRecordField("codeExecutionResult", (content) => {
43
+ validateOptionalPartString(content, "output", field("codeExecutionResult.output"));
44
+ validateOptionalPartString(content, "outcome", field("codeExecutionResult.outcome"));
45
+ });
46
+ validateRecordField("inlineData", (content) => {
47
+ validateOptionalPartString(content, "mimeType", field("inlineData.mimeType"));
48
+ validateOptionalPartString(content, "data", field("inlineData.data"));
49
+ });
50
+ validateRecordField("fileData", (content) => {
51
+ validateOptionalPartString(content, "fileUri", field("fileData.fileUri"));
52
+ validateOptionalPartString(content, "mimeType", field("fileData.mimeType"));
53
+ });
54
+ };
2
55
  /**
3
56
  * Parses an incoming HTTP request into a structured ADK request.
4
57
  *
@@ -27,24 +80,37 @@ const parseAdkRequest = async (request) => {
27
80
  } catch {
28
81
  throw new Error("Invalid JSON in Google ADK proxy request body. Expected a JSON object like {\"message\":\"Hello\"} or {\"type\":\"tool-result\",...}.");
29
82
  }
30
- if (!body || typeof body !== "object" || Array.isArray(body)) throw new Error("Google ADK proxy request body must be a JSON object");
83
+ if (!isRecord(body)) throw new Error("Google ADK proxy request body must be a JSON object");
31
84
  const config = {};
32
85
  if (body.runConfig !== void 0) config.runConfig = body.runConfig;
33
- if (body.checkpointId !== void 0) config.checkpointId = body.checkpointId;
86
+ const checkpointId = readOptionalString(body, "checkpointId");
87
+ if (checkpointId !== void 0) config.checkpointId = checkpointId;
34
88
  const stateDelta = body.stateDelta;
35
- if (body.type === "tool-result") return {
36
- type: "tool-result",
37
- toolCallId: body.toolCallId ?? "",
38
- toolName: body.toolName ?? "",
39
- result: body.result,
40
- isError: body.isError ?? false,
41
- config,
42
- ...stateDelta != null && { stateDelta }
43
- };
89
+ if (stateDelta !== void 0 && !isRecord(stateDelta)) throw invalidField("stateDelta", "an object");
90
+ if (body.type === "tool-result") {
91
+ if (!("result" in body)) throw invalidField("result", "a value");
92
+ if (body.isError !== void 0 && typeof body.isError !== "boolean") throw invalidField("isError", "a boolean");
93
+ return {
94
+ type: "tool-result",
95
+ toolCallId: readString(body, "toolCallId"),
96
+ toolName: readString(body, "toolName"),
97
+ result: body.result,
98
+ isError: body.isError ?? false,
99
+ config,
100
+ ...stateDelta != null && { stateDelta }
101
+ };
102
+ }
103
+ if (body.type !== void 0 && body.type !== "message") throw invalidField("type", "\"message\", \"tool-result\", or omitted");
104
+ const text = body.message;
105
+ if (text !== void 0 && typeof text !== "string") throw invalidField("message", "a string");
106
+ const parts = body.parts;
107
+ if (parts !== void 0 && (!Array.isArray(parts) || !parts.every(isRecord))) throw invalidField("parts", "an array of objects");
108
+ parts?.forEach(validatePart);
109
+ if (!("message" in body) && !("parts" in body)) throw new Error("Invalid Google ADK proxy request: expected a \"message\" string or a \"parts\" array.");
44
110
  return {
45
111
  type: "message",
46
- text: body.message ?? "",
47
- ...body.parts != null && { parts: body.parts },
112
+ text: text ?? "",
113
+ ...parts !== void 0 && { parts },
48
114
  config,
49
115
  ...stateDelta != null && { stateDelta }
50
116
  };
@@ -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(\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
+ {"version":3,"file":"parseAdkRequest.js","names":[],"sources":["../../src/server/parseAdkRequest.ts"],"sourcesContent":["import { isRecord } from \"@assistant-ui/core/internal\";\nimport 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\nconst invalidField = (field: string, expectation: string): Error =>\n new Error(\n `Invalid Google ADK proxy request field \"${field}\": expected ${expectation}.`,\n );\n\nconst readString = (body: Record<string, unknown>, field: string): string => {\n const value = body[field];\n if (typeof value !== \"string\") throw invalidField(field, \"a string\");\n return value;\n};\n\nconst readOptionalString = (\n body: Record<string, unknown>,\n field: string,\n): string | undefined => {\n const value = body[field];\n if (value === undefined) return undefined;\n if (typeof value !== \"string\") throw invalidField(field, \"a string\");\n return value;\n};\n\nconst validateOptionalPartString = (\n part: Record<string, unknown>,\n key: string,\n field: string,\n) => {\n if (part[key] !== undefined && typeof part[key] !== \"string\") {\n throw invalidField(field, \"a string\");\n }\n};\n\n// Nested fields are validated only when present: ADK serializes with\n// exclude_none semantics and the Part vocabulary grows upstream, so absent\n// fields and unknown part kinds pass through to the runner untouched.\nconst validatePart = (part: Record<string, unknown>, index: number) => {\n const field = (name: string) => `parts[${index}].${name}`;\n if (Object.keys(part).length === 0) {\n throw invalidField(`parts[${index}]`, \"a non-empty part object\");\n }\n if (part.thought !== undefined && typeof part.thought !== \"boolean\") {\n throw invalidField(field(\"thought\"), \"a boolean\");\n }\n if (part.text !== undefined && typeof part.text !== \"string\") {\n throw invalidField(field(\"text\"), \"a string\");\n }\n\n const validateRecordField = (\n key: string,\n validateContent: (content: Record<string, unknown>) => void,\n ) => {\n const value = part[key];\n if (value === undefined) return;\n if (!isRecord(value)) throw invalidField(field(key), \"an object\");\n validateContent(value);\n };\n\n validateRecordField(\"functionCall\", (content) => {\n validateOptionalPartString(content, \"name\", field(\"functionCall.name\"));\n validateOptionalPartString(content, \"id\", field(\"functionCall.id\"));\n if (content.args !== undefined && !isRecord(content.args)) {\n throw invalidField(field(\"functionCall.args\"), \"an object\");\n }\n });\n validateRecordField(\"functionResponse\", (content) => {\n validateOptionalPartString(content, \"name\", field(\"functionResponse.name\"));\n validateOptionalPartString(content, \"id\", field(\"functionResponse.id\"));\n });\n validateRecordField(\"executableCode\", (content) => {\n validateOptionalPartString(content, \"code\", field(\"executableCode.code\"));\n validateOptionalPartString(\n content,\n \"language\",\n field(\"executableCode.language\"),\n );\n });\n validateRecordField(\"codeExecutionResult\", (content) => {\n validateOptionalPartString(\n content,\n \"output\",\n field(\"codeExecutionResult.output\"),\n );\n validateOptionalPartString(\n content,\n \"outcome\",\n field(\"codeExecutionResult.outcome\"),\n );\n });\n validateRecordField(\"inlineData\", (content) => {\n validateOptionalPartString(\n content,\n \"mimeType\",\n field(\"inlineData.mimeType\"),\n );\n validateOptionalPartString(content, \"data\", field(\"inlineData.data\"));\n });\n validateRecordField(\"fileData\", (content) => {\n validateOptionalPartString(content, \"fileUri\", field(\"fileData.fileUri\"));\n validateOptionalPartString(content, \"mimeType\", field(\"fileData.mimeType\"));\n });\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: unknown;\n try {\n body = await request.json();\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 (!isRecord(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 const checkpointId = readOptionalString(body, \"checkpointId\");\n if (checkpointId !== undefined) config.checkpointId = checkpointId;\n\n const stateDelta = body.stateDelta;\n if (stateDelta !== undefined && !isRecord(stateDelta)) {\n throw invalidField(\"stateDelta\", \"an object\");\n }\n\n if (body.type === \"tool-result\") {\n if (!(\"result\" in body)) {\n throw invalidField(\"result\", \"a value\");\n }\n if (body.isError !== undefined && typeof body.isError !== \"boolean\") {\n throw invalidField(\"isError\", \"a boolean\");\n }\n return {\n type: \"tool-result\",\n toolCallId: readString(body, \"toolCallId\"),\n toolName: readString(body, \"toolName\"),\n result: body.result,\n isError: body.isError ?? false,\n config,\n ...(stateDelta != null && { stateDelta }),\n };\n }\n\n if (body.type !== undefined && body.type !== \"message\") {\n throw invalidField(\"type\", '\"message\", \"tool-result\", or omitted');\n }\n\n const text = body.message;\n if (text !== undefined && typeof text !== \"string\") {\n throw invalidField(\"message\", \"a string\");\n }\n\n const parts = body.parts;\n if (\n parts !== undefined &&\n (!Array.isArray(parts) || !parts.every(isRecord))\n ) {\n throw invalidField(\"parts\", \"an array of objects\");\n }\n parts?.forEach(validatePart);\n if (!(\"message\" in body) && !(\"parts\" in body)) {\n throw new Error(\n 'Invalid Google ADK proxy request: expected a \"message\" string or a \"parts\" array.',\n );\n }\n\n return {\n type: \"message\",\n text: text ?? \"\",\n ...(parts !== undefined && { parts }),\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":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useAdkMessages.d.ts","names":[],"sources":["../src/useAdkMessages.ts"],"mappings":";;KAmBY;EACV,QAAQ;EACR;IACE,UAAU;IACV,gBAAgB;IAChB,kBAAkB;;;cA0BT,mBAAkB,QAAA,iBAG5B;;;;IAIQ;IACE;;;;;;;;EA2EW,cAAA,aAAA,cAAY,QAAU,yBAAoB;;EAnDhB,cAAA,MAAA;EA+BvC,kBAAA,MAAA;EAnBI,gBAAA,UAAA"}
1
+ {"version":3,"file":"useAdkMessages.d.ts","names":[],"sources":["../src/useAdkMessages.ts"],"mappings":";;KAoBY;EACV,QAAQ;EACR;IACE,UAAU;IACV,gBAAgB;IAChB,kBAAkB;;;cAcT,mBAAkB,QAAA,iBAG5B;;;;IAIQ;IACE;;;;;;;;EA2EW,cAAA,aAAA,cAAY,QAAU,yBAAoB;;EAnDhB,cAAA,MAAA;EA+BvC,kBAAA,MAAA;EAnBI,gBAAA,UAAA"}
@@ -1,21 +1,12 @@
1
1
  import { contentToParts } from "./contentToParts.js";
2
2
  import { AdkEventAccumulator } from "./AdkEventAccumulator.js";
3
- import { v4 } from "uuid";
3
+ import { generateId } from "@assistant-ui/core";
4
+ import { invokeUserCallback } from "@assistant-ui/core/internal";
4
5
  import { useAui } from "@assistant-ui/store";
5
- import { useCallback, useMemo, useRef, useState } from "react";
6
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
6
7
  //#region src/useAdkMessages.ts
7
- const reportCallbackError = (name, error) => {
8
- console.error(`[react-google-adk] ${name} callback threw an error`, error);
9
- };
10
8
  const invokeAdkRuntimeCallback = (name, callback, ...args) => {
11
- if (!callback) return;
12
- try {
13
- Promise.resolve(callback(...args)).catch((error) => {
14
- reportCallbackError(name, error);
15
- });
16
- } catch (error) {
17
- reportCallbackError(name, error);
18
- }
9
+ invokeUserCallback("react-google-adk", name, callback, ...args);
19
10
  };
20
11
  const useAdkMessages = ({ stream, eventHandlers }) => {
21
12
  const [messages, _setMessages] = useState([]);
@@ -68,6 +59,70 @@ const useAdkMessages = ({ stream, eventHandlers }) => {
68
59
  const abortControllerRef = useRef(null);
69
60
  const { onError, onCustomEvent, onAgentTransfer } = useMemo(() => eventHandlers ?? {}, [eventHandlers]);
70
61
  const aui = useAui();
62
+ const sendMessage = useCallback(async (newMessages, config) => {
63
+ const newMessagesWithId = newMessages.map((m) => m.id ? m : {
64
+ ...m,
65
+ id: generateId()
66
+ });
67
+ const resentIds = new Set(newMessagesWithId.map((m) => m.id));
68
+ const accumulator = new AdkEventAccumulator(messagesRef.current.filter((m) => !resentIds.has(m.id)));
69
+ for (const event of messagesToEvents(newMessagesWithId)) accumulator.processEvent(event);
70
+ setMessagesImmediate(accumulator.getMessages());
71
+ const abortController = new AbortController();
72
+ abortControllerRef.current = abortController;
73
+ try {
74
+ const response = await stream(newMessagesWithId, {
75
+ ...config,
76
+ abortSignal: abortController.signal,
77
+ initialize: async () => {
78
+ return await aui.threadListItem.initialize();
79
+ }
80
+ });
81
+ for await (const event of response) {
82
+ const updatedMessages = accumulator.processEvent(event);
83
+ setMessagesImmediate(updatedMessages);
84
+ setStateDelta({
85
+ ...stateDeltaRef.current,
86
+ ...accumulator.getStateDelta()
87
+ });
88
+ setAgentInfo(accumulator.getAgentInfo());
89
+ setLongRunningToolIds(accumulator.getLongRunningToolIds());
90
+ setArtifactDelta({
91
+ ...artifactDeltaRef.current,
92
+ ...accumulator.getArtifactDelta()
93
+ });
94
+ setToolConfirmations(accumulator.getToolConfirmations());
95
+ setAuthRequests(accumulator.getAuthRequests());
96
+ setEscalated(accumulator.isEscalated());
97
+ {
98
+ const newMeta = accumulator.getMessageMetadata();
99
+ if (newMeta.size > 0) setMessageMetadata(new Map([...messageMetadataRef.current, ...newMeta]));
100
+ }
101
+ const transfer = accumulator.getLastTransferToAgent();
102
+ if (transfer && transfer !== lastTransferToAgentRef.current) {
103
+ lastTransferToAgentRef.current = transfer;
104
+ invokeAdkRuntimeCallback("onAgentTransfer", onAgentTransfer, transfer);
105
+ }
106
+ if (event.customMetadata && onCustomEvent) for (const [key, value] of Object.entries(event.customMetadata)) invokeAdkRuntimeCallback("onCustomEvent", onCustomEvent, key, value);
107
+ if (event.errorCode || event.errorMessage) invokeAdkRuntimeCallback("onError", onError, event.errorMessage ?? event.errorCode);
108
+ }
109
+ } catch (error) {
110
+ if (!abortController.signal.aborted && !(error instanceof Error && error.name === "AbortError")) throw error;
111
+ } finally {
112
+ if (abortControllerRef.current === abortController) abortControllerRef.current = null;
113
+ }
114
+ }, [
115
+ aui,
116
+ setMessagesImmediate,
117
+ stream,
118
+ onError,
119
+ onCustomEvent,
120
+ onAgentTransfer
121
+ ]);
122
+ const cancel = useCallback(() => {
123
+ if (abortControllerRef.current) abortControllerRef.current.abort();
124
+ }, []);
125
+ useEffect(() => cancel, [cancel]);
71
126
  return {
72
127
  messages,
73
128
  stateDelta,
@@ -78,77 +133,53 @@ const useAdkMessages = ({ stream, eventHandlers }) => {
78
133
  authRequests,
79
134
  escalated,
80
135
  messageMetadata,
81
- sendMessage: useCallback(async (newMessages, config) => {
82
- const newMessagesWithId = newMessages.map((m) => m.id ? m : {
83
- ...m,
84
- id: v4()
85
- });
86
- const accumulator = new AdkEventAccumulator(messagesRef.current);
87
- for (const msg of newMessagesWithId) accumulator.processEvent(messageToEvent(msg));
88
- setMessagesImmediate(accumulator.getMessages());
89
- const abortController = new AbortController();
90
- abortControllerRef.current = abortController;
91
- try {
92
- const response = await stream(newMessagesWithId, {
93
- ...config,
94
- abortSignal: abortController.signal,
95
- initialize: async () => {
96
- return await aui.threadListItem.initialize();
97
- }
98
- });
99
- for await (const event of response) {
100
- const updatedMessages = accumulator.processEvent(event);
101
- setMessagesImmediate(updatedMessages);
102
- setStateDelta({
103
- ...stateDeltaRef.current,
104
- ...accumulator.getStateDelta()
105
- });
106
- setAgentInfo(accumulator.getAgentInfo());
107
- setLongRunningToolIds(accumulator.getLongRunningToolIds());
108
- setArtifactDelta({
109
- ...artifactDeltaRef.current,
110
- ...accumulator.getArtifactDelta()
111
- });
112
- setToolConfirmations(accumulator.getToolConfirmations());
113
- setAuthRequests(accumulator.getAuthRequests());
114
- setEscalated(accumulator.isEscalated());
115
- {
116
- const newMeta = accumulator.getMessageMetadata();
117
- if (newMeta.size > 0) setMessageMetadata(new Map([...messageMetadataRef.current, ...newMeta]));
118
- }
119
- const transfer = accumulator.getLastTransferToAgent();
120
- if (transfer && transfer !== lastTransferToAgentRef.current) {
121
- lastTransferToAgentRef.current = transfer;
122
- invokeAdkRuntimeCallback("onAgentTransfer", onAgentTransfer, transfer);
123
- }
124
- if (event.customMetadata && onCustomEvent) for (const [key, value] of Object.entries(event.customMetadata)) invokeAdkRuntimeCallback("onCustomEvent", onCustomEvent, key, value);
125
- if (event.errorCode || event.errorMessage) invokeAdkRuntimeCallback("onError", onError, event.errorMessage ?? event.errorCode);
126
- }
127
- } catch (error) {
128
- if (!abortController.signal.aborted && !(error instanceof Error && error.name === "AbortError")) throw error;
129
- } finally {
130
- if (abortControllerRef.current === abortController) abortControllerRef.current = null;
131
- }
132
- }, [
133
- aui,
134
- setMessagesImmediate,
135
- stream,
136
- onError,
137
- onCustomEvent,
138
- onAgentTransfer
139
- ]),
140
- cancel: useCallback(() => {
141
- if (abortControllerRef.current) abortControllerRef.current.abort();
142
- }, []),
136
+ sendMessage,
137
+ cancel,
143
138
  setMessages: setMessagesImmediate,
144
139
  replaceMessages,
145
140
  applySnapshot
146
141
  };
147
142
  };
143
+ /**
144
+ * Transport sends every human and tool message of one `send` call as a single
145
+ * ADK `Content`, and ADK parses that event's function responses before running
146
+ * any tool, so the batch runs whole or not at all. The optimistic projection
147
+ * has to sit on the same boundary, so a run of those messages becomes one
148
+ * synthetic event whose parts come from the same per-message conversion.
149
+ *
150
+ * The transport drops `ai` messages from that `Content`, so one interleaved
151
+ * between two replies does not split the batch on the wire and must not split
152
+ * it here either. It still becomes its own event, placed after the merged one,
153
+ * so the optimistic projection keeps the assistant turn.
154
+ *
155
+ * @internal — exported for unit tests.
156
+ */
157
+ const messagesToEvents = (messages) => {
158
+ if (messages.length === 0) return [];
159
+ const events = [];
160
+ const run = [];
161
+ let runIndex = 0;
162
+ for (const msg of messages) if (msg.type === "ai") events.push(messageToEvent(msg));
163
+ else {
164
+ if (run.length === 0) runIndex = events.length;
165
+ run.push(msg);
166
+ }
167
+ const parts = run.flatMap((m) => messageToEvent(m).content?.parts ?? []);
168
+ const human = run.find((m) => m.type === "human");
169
+ if (parts.length === 0) parts.push({ text: "" });
170
+ const event = { id: (human ?? run[0])?.id ?? generateId() };
171
+ if (human || run.length === 0) event.author = "user";
172
+ event.content = {
173
+ role: "user",
174
+ parts
175
+ };
176
+ events.splice(run.length > 0 ? runIndex : events.length, 0, event);
177
+ return events;
178
+ };
148
179
  /** @internal — exported for unit tests. */
149
180
  const messageToEvent = (msg) => {
150
181
  if (msg.type === "human") return {
151
- id: msg.id ?? v4(),
182
+ id: msg.id ?? generateId(),
152
183
  author: "user",
153
184
  content: {
154
185
  role: "user",
@@ -163,7 +194,7 @@ const messageToEvent = (msg) => {
163
194
  response = msg.content;
164
195
  }
165
196
  return {
166
- id: msg.id ?? v4(),
197
+ id: msg.id ?? generateId(),
167
198
  content: {
168
199
  role: "user",
169
200
  parts: [{ functionResponse: {
@@ -174,7 +205,7 @@ const messageToEvent = (msg) => {
174
205
  }
175
206
  };
176
207
  }
177
- const result = { id: msg.id ?? v4() };
208
+ const result = { id: msg.id ?? generateId() };
178
209
  if (msg.author != null) result.author = msg.author;
179
210
  result.content = {
180
211
  role: "model",
@@ -187,6 +218,6 @@ const messageToEvent = (msg) => {
187
218
  return result;
188
219
  };
189
220
  //#endregion
190
- export { messageToEvent, useAdkMessages };
221
+ export { messageToEvent, messagesToEvents, useAdkMessages };
191
222
 
192
223
  //# sourceMappingURL=useAdkMessages.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useAdkMessages.js","names":["uuidv4"],"sources":["../src/useAdkMessages.ts"],"sourcesContent":["import { useState, useCallback, useRef, useMemo } from \"react\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { useAui } from \"@assistant-ui/store\";\nimport { AdkEventAccumulator } from \"./AdkEventAccumulator\";\nimport { contentToParts } from \"./contentToParts\";\nimport type {\n AdkEvent,\n AdkMessage,\n AdkMessageMetadata,\n AdkSendMessageConfig,\n AdkStreamCallback,\n AdkToolConfirmation,\n AdkAuthRequest,\n AdkThreadSnapshot,\n OnAdkErrorCallback,\n OnAdkCustomEventCallback,\n OnAdkAgentTransferCallback,\n} from \"./types\";\n\nexport type UseAdkMessagesOptions = {\n stream: AdkStreamCallback;\n eventHandlers?: {\n onError?: OnAdkErrorCallback;\n onCustomEvent?: OnAdkCustomEventCallback;\n onAgentTransfer?: OnAdkAgentTransferCallback;\n };\n};\n\ntype AdkRuntimeCallbackName = \"onError\" | \"onCustomEvent\" | \"onAgentTransfer\";\n\nconst reportCallbackError = (name: AdkRuntimeCallbackName, error: unknown) => {\n console.error(`[react-google-adk] ${name} callback threw an error`, error);\n};\n\nconst invokeAdkRuntimeCallback = <TArgs extends unknown[]>(\n name: AdkRuntimeCallbackName,\n callback: ((...args: TArgs) => void | Promise<void>) | undefined,\n ...args: TArgs\n) => {\n if (!callback) return;\n\n try {\n void Promise.resolve(callback(...args)).catch((error) => {\n reportCallbackError(name, error);\n });\n } catch (error) {\n reportCallbackError(name, error);\n }\n};\n\nexport const useAdkMessages = ({\n stream,\n eventHandlers,\n}: UseAdkMessagesOptions) => {\n const [messages, _setMessages] = useState<AdkMessage[]>([]);\n const [stateDelta, setStateDelta] = useState<Record<string, unknown>>({});\n const [agentInfo, setAgentInfo] = useState<{\n name?: string | undefined;\n branch?: string | undefined;\n }>({});\n const [longRunningToolIds, setLongRunningToolIds] = useState<string[]>([]);\n const [artifactDelta, setArtifactDelta] = useState<Record<string, number>>(\n {},\n );\n const [toolConfirmations, setToolConfirmations] = useState<\n AdkToolConfirmation[]\n >([]);\n const [authRequests, setAuthRequests] = useState<AdkAuthRequest[]>([]);\n const [escalated, setEscalated] = useState(false);\n const [messageMetadata, setMessageMetadata] = useState<\n Map<string, AdkMessageMetadata>\n >(new Map());\n const lastTransferToAgentRef = useRef<string | undefined>(undefined);\n const messagesRef = useRef(messages);\n messagesRef.current = messages;\n const stateDeltaRef = useRef(stateDelta);\n stateDeltaRef.current = stateDelta;\n const artifactDeltaRef = useRef(artifactDelta);\n artifactDeltaRef.current = artifactDelta;\n const messageMetadataRef = useRef(messageMetadata);\n messageMetadataRef.current = messageMetadata;\n\n const setMessagesImmediate = useCallback((msgs: AdkMessage[]) => {\n messagesRef.current = msgs;\n _setMessages(msgs);\n }, []);\n\n /**\n * Swap the thread over to a loaded snapshot in one commit. Unlike\n * {@link replaceMessages} this never passes through a cleared state, so a\n * refetch that lands while a confirmation is on screen replaces it rather\n * than blanking it first.\n */\n const applySnapshot = useCallback(\n (snapshot: AdkThreadSnapshot) => {\n setMessagesImmediate(snapshot.messages);\n setLongRunningToolIds(snapshot.longRunningToolIds ?? []);\n setToolConfirmations(snapshot.toolConfirmations ?? []);\n setAuthRequests(snapshot.authRequests ?? []);\n setEscalated(snapshot.escalated ?? false);\n setMessageMetadata(snapshot.messageMetadata ?? new Map());\n setStateDelta(snapshot.stateDelta ?? {});\n setArtifactDelta(snapshot.artifactDelta ?? {});\n setAgentInfo(snapshot.agentInfo ?? {});\n },\n [setMessagesImmediate],\n );\n\n // Replace the message list AND reset derived per-turn HITL state.\n // Used by truncation paths (edit, reload) so that stale interrupt\n // markers and per-message metadata from the removed messages don't leak\n // into the next turn.\n const replaceMessages = useCallback(\n (msgs: AdkMessage[]) => {\n setMessagesImmediate(msgs);\n setLongRunningToolIds([]);\n setToolConfirmations([]);\n setAuthRequests([]);\n setEscalated(false);\n setMessageMetadata(new Map());\n },\n [setMessagesImmediate],\n );\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const { onError, onCustomEvent, onAgentTransfer } = useMemo(\n () => eventHandlers ?? {},\n [eventHandlers],\n );\n\n const aui = useAui();\n const sendMessage = useCallback(\n async (newMessages: AdkMessage[], config: AdkSendMessageConfig) => {\n const newMessagesWithId = newMessages.map((m) =>\n m.id ? m : { ...m, id: uuidv4() },\n ) as AdkMessage[];\n\n const accumulator = new AdkEventAccumulator(messagesRef.current);\n for (const msg of newMessagesWithId) {\n accumulator.processEvent(messageToEvent(msg));\n }\n setMessagesImmediate(accumulator.getMessages());\n\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n\n try {\n const response = await stream(newMessagesWithId, {\n ...config,\n abortSignal: abortController.signal,\n initialize: async () => {\n return await aui.threadListItem.initialize();\n },\n });\n\n for await (const event of response) {\n const updatedMessages = accumulator.processEvent(event);\n setMessagesImmediate(updatedMessages);\n setStateDelta({\n ...stateDeltaRef.current,\n ...accumulator.getStateDelta(),\n });\n setAgentInfo(accumulator.getAgentInfo());\n setLongRunningToolIds(accumulator.getLongRunningToolIds());\n setArtifactDelta({\n ...artifactDeltaRef.current,\n ...accumulator.getArtifactDelta(),\n });\n setToolConfirmations(accumulator.getToolConfirmations());\n setAuthRequests(accumulator.getAuthRequests());\n setEscalated(accumulator.isEscalated());\n {\n const newMeta = accumulator.getMessageMetadata();\n if (newMeta.size > 0) {\n setMessageMetadata(\n new Map([...messageMetadataRef.current, ...newMeta]),\n );\n }\n }\n\n const transfer = accumulator.getLastTransferToAgent();\n if (transfer && transfer !== lastTransferToAgentRef.current) {\n lastTransferToAgentRef.current = transfer;\n invokeAdkRuntimeCallback(\n \"onAgentTransfer\",\n onAgentTransfer,\n transfer,\n );\n }\n\n // Fire custom event callback for events with customMetadata\n if (event.customMetadata && onCustomEvent) {\n for (const [key, value] of Object.entries(event.customMetadata)) {\n invokeAdkRuntimeCallback(\n \"onCustomEvent\",\n onCustomEvent,\n key,\n value,\n );\n }\n }\n\n if (event.errorCode || event.errorMessage) {\n invokeAdkRuntimeCallback(\n \"onError\",\n onError,\n event.errorMessage ?? event.errorCode,\n );\n }\n }\n } catch (error) {\n if (\n !abortController.signal.aborted &&\n !(error instanceof Error && error.name === \"AbortError\")\n ) {\n throw error;\n }\n } finally {\n if (abortControllerRef.current === abortController) {\n abortControllerRef.current = null;\n }\n }\n },\n [\n aui,\n setMessagesImmediate,\n stream,\n onError,\n onCustomEvent,\n onAgentTransfer,\n ],\n );\n\n const cancel = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n }, []);\n\n return {\n messages,\n stateDelta,\n agentInfo,\n longRunningToolIds,\n artifactDelta,\n toolConfirmations,\n authRequests,\n escalated,\n messageMetadata,\n sendMessage,\n cancel,\n setMessages: setMessagesImmediate,\n replaceMessages,\n applySnapshot,\n };\n};\n\n/** @internal — exported for unit tests. */\nexport const messageToEvent = (msg: AdkMessage): AdkEvent => {\n if (msg.type === \"human\") {\n return {\n id: msg.id ?? uuidv4(),\n author: \"user\",\n content: { role: \"user\", parts: contentToParts(msg.content) },\n };\n }\n\n if (msg.type === \"tool\") {\n let response: unknown;\n try {\n response = JSON.parse(msg.content);\n } catch {\n response = msg.content;\n }\n return {\n id: msg.id ?? uuidv4(),\n content: {\n role: \"user\",\n parts: [\n {\n functionResponse: {\n name: msg.name,\n id: msg.tool_call_id,\n response,\n },\n },\n ],\n },\n };\n }\n\n const result: AdkEvent = { id: msg.id ?? uuidv4() };\n if (msg.author != null) result.author = msg.author;\n result.content = {\n role: \"model\",\n parts: [\n ...contentToParts(msg.content),\n ...(msg.tool_calls?.map((tc) => ({\n functionCall: { name: tc.name, id: tc.id, args: { ...tc.args } },\n })) ?? []),\n ],\n };\n return result;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"useAdkMessages.js","names":[],"sources":["../src/useAdkMessages.ts"],"sourcesContent":["import { useState, useCallback, useEffect, useRef, useMemo } from \"react\";\nimport { generateId } from \"@assistant-ui/core\";\nimport { useAui } from \"@assistant-ui/store\";\nimport { invokeUserCallback } from \"@assistant-ui/core/internal\";\nimport { AdkEventAccumulator } from \"./AdkEventAccumulator\";\nimport { contentToParts } from \"./contentToParts\";\nimport type {\n AdkEvent,\n AdkMessage,\n AdkMessageMetadata,\n AdkSendMessageConfig,\n AdkStreamCallback,\n AdkToolConfirmation,\n AdkAuthRequest,\n AdkThreadSnapshot,\n OnAdkErrorCallback,\n OnAdkCustomEventCallback,\n OnAdkAgentTransferCallback,\n} from \"./types\";\n\nexport type UseAdkMessagesOptions = {\n stream: AdkStreamCallback;\n eventHandlers?: {\n onError?: OnAdkErrorCallback;\n onCustomEvent?: OnAdkCustomEventCallback;\n onAgentTransfer?: OnAdkAgentTransferCallback;\n };\n};\n\ntype AdkRuntimeCallbackName = \"onError\" | \"onCustomEvent\" | \"onAgentTransfer\";\n\nconst invokeAdkRuntimeCallback = <TArgs extends readonly unknown[]>(\n name: AdkRuntimeCallbackName,\n callback: ((...args: TArgs) => unknown) | undefined,\n ...args: TArgs\n): void => {\n void invokeUserCallback(\"react-google-adk\", name, callback, ...args);\n};\n\nexport const useAdkMessages = ({\n stream,\n eventHandlers,\n}: UseAdkMessagesOptions) => {\n const [messages, _setMessages] = useState<AdkMessage[]>([]);\n const [stateDelta, setStateDelta] = useState<Record<string, unknown>>({});\n const [agentInfo, setAgentInfo] = useState<{\n name?: string | undefined;\n branch?: string | undefined;\n }>({});\n const [longRunningToolIds, setLongRunningToolIds] = useState<string[]>([]);\n const [artifactDelta, setArtifactDelta] = useState<Record<string, number>>(\n {},\n );\n const [toolConfirmations, setToolConfirmations] = useState<\n AdkToolConfirmation[]\n >([]);\n const [authRequests, setAuthRequests] = useState<AdkAuthRequest[]>([]);\n const [escalated, setEscalated] = useState(false);\n const [messageMetadata, setMessageMetadata] = useState<\n Map<string, AdkMessageMetadata>\n >(new Map());\n const lastTransferToAgentRef = useRef<string | undefined>(undefined);\n const messagesRef = useRef(messages);\n messagesRef.current = messages;\n const stateDeltaRef = useRef(stateDelta);\n stateDeltaRef.current = stateDelta;\n const artifactDeltaRef = useRef(artifactDelta);\n artifactDeltaRef.current = artifactDelta;\n const messageMetadataRef = useRef(messageMetadata);\n messageMetadataRef.current = messageMetadata;\n\n const setMessagesImmediate = useCallback((msgs: AdkMessage[]) => {\n messagesRef.current = msgs;\n _setMessages(msgs);\n }, []);\n\n /**\n * Swap the thread over to a loaded snapshot in one commit. Unlike\n * {@link replaceMessages} this never passes through a cleared state, so a\n * refetch that lands while a confirmation is on screen replaces it rather\n * than blanking it first.\n */\n const applySnapshot = useCallback(\n (snapshot: AdkThreadSnapshot) => {\n setMessagesImmediate(snapshot.messages);\n setLongRunningToolIds(snapshot.longRunningToolIds ?? []);\n setToolConfirmations(snapshot.toolConfirmations ?? []);\n setAuthRequests(snapshot.authRequests ?? []);\n setEscalated(snapshot.escalated ?? false);\n setMessageMetadata(snapshot.messageMetadata ?? new Map());\n setStateDelta(snapshot.stateDelta ?? {});\n setArtifactDelta(snapshot.artifactDelta ?? {});\n setAgentInfo(snapshot.agentInfo ?? {});\n },\n [setMessagesImmediate],\n );\n\n // Replace the message list AND reset derived per-turn HITL state.\n // Used by truncation paths (edit, reload) so that stale interrupt\n // markers and per-message metadata from the removed messages don't leak\n // into the next turn.\n const replaceMessages = useCallback(\n (msgs: AdkMessage[]) => {\n setMessagesImmediate(msgs);\n setLongRunningToolIds([]);\n setToolConfirmations([]);\n setAuthRequests([]);\n setEscalated(false);\n setMessageMetadata(new Map());\n },\n [setMessagesImmediate],\n );\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const { onError, onCustomEvent, onAgentTransfer } = useMemo(\n () => eventHandlers ?? {},\n [eventHandlers],\n );\n\n const aui = useAui();\n const sendMessage = useCallback(\n async (newMessages: AdkMessage[], config: AdkSendMessageConfig) => {\n const newMessagesWithId = newMessages.map((m) =>\n m.id ? m : { ...m, id: generateId() },\n ) as AdkMessage[];\n\n // A staged message is already in the thread under its own id, and the\n // merged event below re-emits the whole batch under the first one. Seeding\n // with the originals would leave every later staged id beside the merged\n // copy of itself.\n const resentIds = new Set(newMessagesWithId.map((m) => m.id));\n const accumulator = new AdkEventAccumulator(\n messagesRef.current.filter((m) => !resentIds.has(m.id)),\n );\n for (const event of messagesToEvents(newMessagesWithId)) {\n accumulator.processEvent(event);\n }\n setMessagesImmediate(accumulator.getMessages());\n\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n\n try {\n const response = await stream(newMessagesWithId, {\n ...config,\n abortSignal: abortController.signal,\n initialize: async () => {\n return await aui.threadListItem.initialize();\n },\n });\n\n for await (const event of response) {\n const updatedMessages = accumulator.processEvent(event);\n setMessagesImmediate(updatedMessages);\n setStateDelta({\n ...stateDeltaRef.current,\n ...accumulator.getStateDelta(),\n });\n setAgentInfo(accumulator.getAgentInfo());\n setLongRunningToolIds(accumulator.getLongRunningToolIds());\n setArtifactDelta({\n ...artifactDeltaRef.current,\n ...accumulator.getArtifactDelta(),\n });\n setToolConfirmations(accumulator.getToolConfirmations());\n setAuthRequests(accumulator.getAuthRequests());\n setEscalated(accumulator.isEscalated());\n {\n const newMeta = accumulator.getMessageMetadata();\n if (newMeta.size > 0) {\n setMessageMetadata(\n new Map([...messageMetadataRef.current, ...newMeta]),\n );\n }\n }\n\n const transfer = accumulator.getLastTransferToAgent();\n if (transfer && transfer !== lastTransferToAgentRef.current) {\n lastTransferToAgentRef.current = transfer;\n invokeAdkRuntimeCallback(\n \"onAgentTransfer\",\n onAgentTransfer,\n transfer,\n );\n }\n\n // Fire custom event callback for events with customMetadata\n if (event.customMetadata && onCustomEvent) {\n for (const [key, value] of Object.entries(event.customMetadata)) {\n invokeAdkRuntimeCallback(\n \"onCustomEvent\",\n onCustomEvent,\n key,\n value,\n );\n }\n }\n\n if (event.errorCode || event.errorMessage) {\n invokeAdkRuntimeCallback(\n \"onError\",\n onError,\n event.errorMessage ?? event.errorCode,\n );\n }\n }\n } catch (error) {\n if (\n !abortController.signal.aborted &&\n !(error instanceof Error && error.name === \"AbortError\")\n ) {\n throw error;\n }\n } finally {\n if (abortControllerRef.current === abortController) {\n abortControllerRef.current = null;\n }\n }\n },\n [\n aui,\n setMessagesImmediate,\n stream,\n onError,\n onCustomEvent,\n onAgentTransfer,\n ],\n );\n\n const cancel = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n }, []);\n\n useEffect(() => cancel, [cancel]);\n\n return {\n messages,\n stateDelta,\n agentInfo,\n longRunningToolIds,\n artifactDelta,\n toolConfirmations,\n authRequests,\n escalated,\n messageMetadata,\n sendMessage,\n cancel,\n setMessages: setMessagesImmediate,\n replaceMessages,\n applySnapshot,\n };\n};\n\n/**\n * Transport sends every human and tool message of one `send` call as a single\n * ADK `Content`, and ADK parses that event's function responses before running\n * any tool, so the batch runs whole or not at all. The optimistic projection\n * has to sit on the same boundary, so a run of those messages becomes one\n * synthetic event whose parts come from the same per-message conversion.\n *\n * The transport drops `ai` messages from that `Content`, so one interleaved\n * between two replies does not split the batch on the wire and must not split\n * it here either. It still becomes its own event, placed after the merged one,\n * so the optimistic projection keeps the assistant turn.\n *\n * @internal — exported for unit tests.\n */\nexport const messagesToEvents = (messages: AdkMessage[]): AdkEvent[] => {\n // A reload sends no messages at all, and the empty user content the transport\n // puts on the wire for it is not part of the optimistic view: projecting one\n // would put an empty user bubble above every regenerated turn.\n if (messages.length === 0) return [];\n\n const events: AdkEvent[] = [];\n const run: AdkMessage[] = [];\n let runIndex = 0;\n\n for (const msg of messages) {\n if (msg.type === \"ai\") {\n events.push(messageToEvent(msg));\n } else {\n if (run.length === 0) runIndex = events.length;\n run.push(msg);\n }\n }\n\n const parts = run.flatMap((m) => messageToEvent(m).content?.parts ?? []);\n const human = run.find((m) => m.type === \"human\");\n\n // A batch that contributes no part still reaches the wire: the transport\n // sends an empty user `Content`, which a reload replays as an empty human\n // message. Emitting it here keeps the optimistic view equal to that replay.\n if (parts.length === 0) parts.push({ text: \"\" });\n\n const event: AdkEvent = { id: (human ?? run[0])?.id ?? generateId() };\n if (human || run.length === 0) event.author = \"user\";\n event.content = { role: \"user\", parts };\n events.splice(run.length > 0 ? runIndex : events.length, 0, event);\n\n return events;\n};\n\n/** @internal — exported for unit tests. */\nexport const messageToEvent = (msg: AdkMessage): AdkEvent => {\n if (msg.type === \"human\") {\n return {\n id: msg.id ?? generateId(),\n author: \"user\",\n content: { role: \"user\", parts: contentToParts(msg.content) },\n };\n }\n\n if (msg.type === \"tool\") {\n let response: unknown;\n try {\n response = JSON.parse(msg.content);\n } catch {\n response = msg.content;\n }\n return {\n id: msg.id ?? generateId(),\n content: {\n role: \"user\",\n parts: [\n {\n functionResponse: {\n name: msg.name,\n id: msg.tool_call_id,\n response,\n },\n },\n ],\n },\n };\n }\n\n const result: AdkEvent = { id: msg.id ?? generateId() };\n if (msg.author != null) result.author = msg.author;\n result.content = {\n role: \"model\",\n parts: [\n ...contentToParts(msg.content),\n ...(msg.tool_calls?.map((tc) => ({\n functionCall: { name: tc.name, id: tc.id, args: { ...tc.args } },\n })) ?? []),\n ],\n };\n return result;\n};\n"],"mappings":";;;;;;;AA+BA,MAAM,4BACJ,MACA,UACA,GAAG,SACM;CACT,mBAAwB,oBAAoB,MAAM,UAAU,GAAG,IAAI;AACrE;AAEA,MAAa,kBAAkB,EAC7B,QACA,oBAC2B;CAC3B,MAAM,CAAC,UAAU,gBAAgB,SAAuB,CAAC,CAAC;CAC1D,MAAM,CAAC,YAAY,iBAAiB,SAAkC,CAAC,CAAC;CACxE,MAAM,CAAC,WAAW,gBAAgB,SAG/B,CAAC,CAAC;CACL,MAAM,CAAC,oBAAoB,yBAAyB,SAAmB,CAAC,CAAC;CACzE,MAAM,CAAC,eAAe,oBAAoB,SACxC,CAAC,CACH;CACA,MAAM,CAAC,mBAAmB,wBAAwB,SAEhD,CAAC,CAAC;CACJ,MAAM,CAAC,cAAc,mBAAmB,SAA2B,CAAC,CAAC;CACrE,MAAM,CAAC,WAAW,gBAAgB,SAAS,KAAK;CAChD,MAAM,CAAC,iBAAiB,sBAAsB,yBAE5C,IAAI,IAAI,CAAC;CACX,MAAM,yBAAyB,OAA2B,KAAA,CAAS;CACnE,MAAM,cAAc,OAAO,QAAQ;CACnC,YAAY,UAAU;CACtB,MAAM,gBAAgB,OAAO,UAAU;CACvC,cAAc,UAAU;CACxB,MAAM,mBAAmB,OAAO,aAAa;CAC7C,iBAAiB,UAAU;CAC3B,MAAM,qBAAqB,OAAO,eAAe;CACjD,mBAAmB,UAAU;CAE7B,MAAM,uBAAuB,aAAa,SAAuB;EAC/D,YAAY,UAAU;EACtB,aAAa,IAAI;CACnB,GAAG,CAAC,CAAC;;;;;;;CAQL,MAAM,gBAAgB,aACnB,aAAgC;EAC/B,qBAAqB,SAAS,QAAQ;EACtC,sBAAsB,SAAS,sBAAsB,CAAC,CAAC;EACvD,qBAAqB,SAAS,qBAAqB,CAAC,CAAC;EACrD,gBAAgB,SAAS,gBAAgB,CAAC,CAAC;EAC3C,aAAa,SAAS,aAAa,KAAK;EACxC,mBAAmB,SAAS,mCAAmB,IAAI,IAAI,CAAC;EACxD,cAAc,SAAS,cAAc,CAAC,CAAC;EACvC,iBAAiB,SAAS,iBAAiB,CAAC,CAAC;EAC7C,aAAa,SAAS,aAAa,CAAC,CAAC;CACvC,GACA,CAAC,oBAAoB,CACvB;CAMA,MAAM,kBAAkB,aACrB,SAAuB;EACtB,qBAAqB,IAAI;EACzB,sBAAsB,CAAC,CAAC;EACxB,qBAAqB,CAAC,CAAC;EACvB,gBAAgB,CAAC,CAAC;EAClB,aAAa,KAAK;EAClB,mCAAmB,IAAI,IAAI,CAAC;CAC9B,GACA,CAAC,oBAAoB,CACvB;CAEA,MAAM,qBAAqB,OAA+B,IAAI;CAE9D,MAAM,EAAE,SAAS,eAAe,oBAAoB,cAC5C,iBAAiB,CAAC,GACxB,CAAC,aAAa,CAChB;CAEA,MAAM,MAAM,OAAO;CACnB,MAAM,cAAc,YAClB,OAAO,aAA2B,WAAiC;EACjE,MAAM,oBAAoB,YAAY,KAAK,MACzC,EAAE,KAAK,IAAI;GAAE,GAAG;GAAG,IAAI,WAAW;EAAE,CACtC;EAMA,MAAM,YAAY,IAAI,IAAI,kBAAkB,KAAK,MAAM,EAAE,EAAE,CAAC;EAC5D,MAAM,cAAc,IAAI,oBACtB,YAAY,QAAQ,QAAQ,MAAM,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC,CACxD;EACA,KAAK,MAAM,SAAS,iBAAiB,iBAAiB,GACpD,YAAY,aAAa,KAAK;EAEhC,qBAAqB,YAAY,YAAY,CAAC;EAE9C,MAAM,kBAAkB,IAAI,gBAAgB;EAC5C,mBAAmB,UAAU;EAE7B,IAAI;GACF,MAAM,WAAW,MAAM,OAAO,mBAAmB;IAC/C,GAAG;IACH,aAAa,gBAAgB;IAC7B,YAAY,YAAY;KACtB,OAAO,MAAM,IAAI,eAAe,WAAW;IAC7C;GACF,CAAC;GAED,WAAW,MAAM,SAAS,UAAU;IAClC,MAAM,kBAAkB,YAAY,aAAa,KAAK;IACtD,qBAAqB,eAAe;IACpC,cAAc;KACZ,GAAG,cAAc;KACjB,GAAG,YAAY,cAAc;IAC/B,CAAC;IACD,aAAa,YAAY,aAAa,CAAC;IACvC,sBAAsB,YAAY,sBAAsB,CAAC;IACzD,iBAAiB;KACf,GAAG,iBAAiB;KACpB,GAAG,YAAY,iBAAiB;IAClC,CAAC;IACD,qBAAqB,YAAY,qBAAqB,CAAC;IACvD,gBAAgB,YAAY,gBAAgB,CAAC;IAC7C,aAAa,YAAY,YAAY,CAAC;IACtC;KACE,MAAM,UAAU,YAAY,mBAAmB;KAC/C,IAAI,QAAQ,OAAO,GACjB,mBACE,IAAI,IAAI,CAAC,GAAG,mBAAmB,SAAS,GAAG,OAAO,CAAC,CACrD;IAEJ;IAEA,MAAM,WAAW,YAAY,uBAAuB;IACpD,IAAI,YAAY,aAAa,uBAAuB,SAAS;KAC3D,uBAAuB,UAAU;KACjC,yBACE,mBACA,iBACA,QACF;IACF;IAGA,IAAI,MAAM,kBAAkB,eAC1B,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,cAAc,GAC5D,yBACE,iBACA,eACA,KACA,KACF;IAIJ,IAAI,MAAM,aAAa,MAAM,cAC3B,yBACE,WACA,SACA,MAAM,gBAAgB,MAAM,SAC9B;GAEJ;EACF,SAAS,OAAO;GACd,IACE,CAAC,gBAAgB,OAAO,WACxB,EAAE,iBAAiB,SAAS,MAAM,SAAS,eAE3C,MAAM;EAEV,UAAU;GACR,IAAI,mBAAmB,YAAY,iBACjC,mBAAmB,UAAU;EAEjC;CACF,GACA;EACE;EACA;EACA;EACA;EACA;EACA;CACF,CACF;CAEA,MAAM,SAAS,kBAAkB;EAC/B,IAAI,mBAAmB,SACrB,mBAAmB,QAAQ,MAAM;CAErC,GAAG,CAAC,CAAC;CAEL,gBAAgB,QAAQ,CAAC,MAAM,CAAC;CAEhC,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,aAAa;EACb;EACA;CACF;AACF;;;;;;;;;;;;;;;AAgBA,MAAa,oBAAoB,aAAuC;CAItE,IAAI,SAAS,WAAW,GAAG,OAAO,CAAC;CAEnC,MAAM,SAAqB,CAAC;CAC5B,MAAM,MAAoB,CAAC;CAC3B,IAAI,WAAW;CAEf,KAAK,MAAM,OAAO,UAChB,IAAI,IAAI,SAAS,MACf,OAAO,KAAK,eAAe,GAAG,CAAC;MAC1B;EACL,IAAI,IAAI,WAAW,GAAG,WAAW,OAAO;EACxC,IAAI,KAAK,GAAG;CACd;CAGF,MAAM,QAAQ,IAAI,SAAS,MAAM,eAAe,CAAC,CAAC,CAAC,SAAS,SAAS,CAAC,CAAC;CACvE,MAAM,QAAQ,IAAI,MAAM,MAAM,EAAE,SAAS,OAAO;CAKhD,IAAI,MAAM,WAAW,GAAG,MAAM,KAAK,EAAE,MAAM,GAAG,CAAC;CAE/C,MAAM,QAAkB,EAAE,KAAK,SAAS,IAAI,GAAA,EAAK,MAAM,WAAW,EAAE;CACpE,IAAI,SAAS,IAAI,WAAW,GAAG,MAAM,SAAS;CAC9C,MAAM,UAAU;EAAE,MAAM;EAAQ;CAAM;CACtC,OAAO,OAAO,IAAI,SAAS,IAAI,WAAW,OAAO,QAAQ,GAAG,KAAK;CAEjE,OAAO;AACT;;AAGA,MAAa,kBAAkB,QAA8B;CAC3D,IAAI,IAAI,SAAS,SACf,OAAO;EACL,IAAI,IAAI,MAAM,WAAW;EACzB,QAAQ;EACR,SAAS;GAAE,MAAM;GAAQ,OAAO,eAAe,IAAI,OAAO;EAAE;CAC9D;CAGF,IAAI,IAAI,SAAS,QAAQ;EACvB,IAAI;EACJ,IAAI;GACF,WAAW,KAAK,MAAM,IAAI,OAAO;EACnC,QAAQ;GACN,WAAW,IAAI;EACjB;EACA,OAAO;GACL,IAAI,IAAI,MAAM,WAAW;GACzB,SAAS;IACP,MAAM;IACN,OAAO,CACL,EACE,kBAAkB;KAChB,MAAM,IAAI;KACV,IAAI,IAAI;KACR;IACF,EACF,CACF;GACF;EACF;CACF;CAEA,MAAM,SAAmB,EAAE,IAAI,IAAI,MAAM,WAAW,EAAE;CACtD,IAAI,IAAI,UAAU,MAAM,OAAO,SAAS,IAAI;CAC5C,OAAO,UAAU;EACf,MAAM;EACN,OAAO,CACL,GAAG,eAAe,IAAI,OAAO,GAC7B,GAAI,IAAI,YAAY,KAAK,QAAQ,EAC/B,cAAc;GAAE,MAAM,GAAG;GAAM,IAAI,GAAG;GAAI,MAAM,EAAE,GAAG,GAAG,KAAK;EAAE,EACjE,EAAE,KAAK,CAAC,CACV;CACF;CACA,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"useAdkRuntime.d.ts","names":[],"sources":["../src/useAdkRuntime.ts"],"mappings":";;;;KAsKY,uBAAuB;EACjC,QAAQ;;;;;;;;;EASR,qBAAqB;EACrB;EACA;EACA,mBACE,kBACA,gBAAgB,iBACb;;;;;;;EAOL,QACE,kBACA;IAAY,SAAS;QAClB,QAAQ;EACb,eAAe;IAAU;;EACzB,UAAU,qBAAqB;EAC/B;IAEM,cAAc;IACd,SAAS;IACT,YAAY;IACZ,QAAQ;IACR,WAAW;;EAGjB;IAEM,UAAU;IACV,gBAAgB;IAChB,kBAAkB;;EAGxB,QAAQ;;;;;EAKR,iBAAiB;;cAmWN,kBAAiB,OAAA,gBAAA,QAAA,QAAA,UAAA,qBAAA,WAO3B,sDAAoB"}
1
+ {"version":3,"file":"useAdkRuntime.d.ts","names":[],"sources":["../src/useAdkRuntime.ts"],"mappings":";;;;KAoDY,uBAAuB;EACjC,QAAQ;;;;;;;;;EASR,qBAAqB;EACrB;EACA;EACA,mBACE,kBACA,gBAAgB,iBACb;;;;;;;EAOL,QACE,kBACA;IAAY,SAAS;QAClB,QAAQ;EACb,eAAe;IAAU;;EACzB,UAAU,qBAAqB;EAC/B;IAEM,cAAc;IACd,SAAS;IACT,YAAY;IACZ,QAAQ;IACR,WAAW;;EAGjB;IAEM,UAAU;IACV,gBAAgB;IAChB,kBAAkB;;EAGxB,QAAQ;;;;;EAKR,iBAAiB;;cA4VN,kBAAiB,OAAA,gBAAA,QAAA,QAAA,UAAA,qBAAA,WAO3B,sDAAoB"}