@assistant-ui/react-google-adk 0.0.8 → 0.0.11

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 (63) hide show
  1. package/README.md +15 -128
  2. package/dist/AdkClient.d.ts +30 -26
  3. package/dist/AdkClient.d.ts.map +1 -1
  4. package/dist/AdkClient.js +131 -165
  5. package/dist/AdkClient.js.map +1 -1
  6. package/dist/AdkEventAccumulator.d.ts +43 -39
  7. package/dist/AdkEventAccumulator.d.ts.map +1 -1
  8. package/dist/AdkEventAccumulator.js +446 -531
  9. package/dist/AdkEventAccumulator.js.map +1 -1
  10. package/dist/AdkSessionAdapter.d.ts +40 -37
  11. package/dist/AdkSessionAdapter.d.ts.map +1 -1
  12. package/dist/AdkSessionAdapter.js +134 -155
  13. package/dist/AdkSessionAdapter.js.map +1 -1
  14. package/dist/contentToParts.d.ts +6 -2
  15. package/dist/contentToParts.d.ts.map +1 -1
  16. package/dist/contentToParts.js +37 -34
  17. package/dist/contentToParts.js.map +1 -1
  18. package/dist/convertAdkMessages.d.ts +7 -3
  19. package/dist/convertAdkMessages.d.ts.map +1 -1
  20. package/dist/convertAdkMessages.js +93 -86
  21. package/dist/convertAdkMessages.js.map +1 -1
  22. package/dist/hooks.d.ts +38 -34
  23. package/dist/hooks.d.ts.map +1 -1
  24. package/dist/hooks.js +132 -155
  25. package/dist/hooks.js.map +1 -1
  26. package/dist/index.d.ts +10 -11
  27. package/dist/index.js +10 -10
  28. package/dist/server/adkEventStream.d.ts +27 -25
  29. package/dist/server/adkEventStream.d.ts.map +1 -1
  30. package/dist/server/adkEventStream.js +91 -126
  31. package/dist/server/adkEventStream.js.map +1 -1
  32. package/dist/server/createAdkApiRoute.d.ts +26 -23
  33. package/dist/server/createAdkApiRoute.d.ts.map +1 -1
  34. package/dist/server/createAdkApiRoute.js +34 -37
  35. package/dist/server/createAdkApiRoute.js.map +1 -1
  36. package/dist/server/index.d.ts +4 -4
  37. package/dist/server/index.js +4 -4
  38. package/dist/server/parseAdkRequest.d.ts +21 -18
  39. package/dist/server/parseAdkRequest.d.ts.map +1 -1
  40. package/dist/server/parseAdkRequest.js +80 -88
  41. package/dist/server/parseAdkRequest.js.map +1 -1
  42. package/dist/structuredEvents.d.ts +6 -2
  43. package/dist/structuredEvents.d.ts.map +1 -1
  44. package/dist/structuredEvents.js +70 -75
  45. package/dist/structuredEvents.js.map +1 -1
  46. package/dist/types.d.ts +231 -227
  47. package/dist/types.d.ts.map +1 -1
  48. package/dist/types.js +15 -12
  49. package/dist/types.js.map +1 -1
  50. package/dist/useAdkMessages.d.ts +32 -25
  51. package/dist/useAdkMessages.d.ts.map +1 -1
  52. package/dist/useAdkMessages.js +155 -182
  53. package/dist/useAdkMessages.js.map +1 -1
  54. package/dist/useAdkRuntime.d.ts +43 -34
  55. package/dist/useAdkRuntime.d.ts.map +1 -1
  56. package/dist/useAdkRuntime.js +219 -273
  57. package/dist/useAdkRuntime.js.map +1 -1
  58. package/package.json +8 -8
  59. package/src/useAdkRuntime.ts +6 -2
  60. package/dist/index.d.ts.map +0 -1
  61. package/dist/index.js.map +0 -1
  62. package/dist/server/index.d.ts.map +0 -1
  63. package/dist/server/index.js.map +0 -1
@@ -1,544 +1,459 @@
1
- import { v4 as uuidv4 } from "uuid";
1
+ import { v4 } from "uuid";
2
+ //#region src/AdkEventAccumulator.ts
2
3
  const ADK_REQUEST_CONFIRMATION = "adk_request_confirmation";
3
4
  const ADK_REQUEST_CREDENTIAL = "adk_request_credential";
4
5
  /**
5
- * Checks if an event is a final response using the same logic as ADK's
6
- * `isFinalResponse()`.
7
- */
8
- export const isFinalResponse = (event) => {
9
- if (event.actions?.skipSummarization ||
10
- (event.longRunningToolIds && event.longRunningToolIds.length > 0)) {
11
- return true;
12
- }
13
- const parts = event.content?.parts;
14
- return (!event.partial &&
15
- (parts?.length ?? 0) > 0 &&
16
- !parts.some((p) => p.functionCall) &&
17
- !parts.some((p) => p.functionResponse) &&
18
- !parts[parts.length - 1]?.codeExecutionResult);
6
+ * Checks if an event is a final response using the same logic as ADK's
7
+ * `isFinalResponse()`.
8
+ */
9
+ const isFinalResponse = (event) => {
10
+ if (event.actions?.skipSummarization || event.longRunningToolIds && event.longRunningToolIds.length > 0) return true;
11
+ const parts = event.content?.parts;
12
+ return !event.partial && (parts?.length ?? 0) > 0 && !parts.some((p) => p.functionCall) && !parts.some((p) => p.functionResponse) && !parts[parts.length - 1]?.codeExecutionResult;
19
13
  };
20
14
  const CONTENT_FILTER_REASONS = new Set([
21
- "SAFETY",
22
- "RECITATION",
23
- "BLOCKLIST",
24
- "PROHIBITED_CONTENT",
25
- "SPII",
26
- "LANGUAGE",
27
- "IMAGE_SAFETY",
28
- "IMAGE_RECITATION",
29
- "IMAGE_OTHER",
30
- "IMAGE_PROHIBITED_CONTENT",
31
- ]);
32
- const ERROR_REASONS = new Set([
33
- "MALFORMED_FUNCTION_CALL",
34
- "UNEXPECTED_TOOL_CALL",
15
+ "SAFETY",
16
+ "RECITATION",
17
+ "BLOCKLIST",
18
+ "PROHIBITED_CONTENT",
19
+ "SPII",
20
+ "LANGUAGE",
21
+ "IMAGE_SAFETY",
22
+ "IMAGE_RECITATION",
23
+ "IMAGE_OTHER",
24
+ "IMAGE_PROHIBITED_CONTENT"
35
25
  ]);
26
+ const ERROR_REASONS = new Set(["MALFORMED_FUNCTION_CALL", "UNEXPECTED_TOOL_CALL"]);
36
27
  const finishReasonToStatus = (finishReason) => {
37
- if (finishReason === "MAX_TOKENS") {
38
- return { type: "incomplete", reason: "length" };
39
- }
40
- if (finishReason && CONTENT_FILTER_REASONS.has(finishReason)) {
41
- return {
42
- type: "incomplete",
43
- reason: "content-filter",
44
- error: `Content filtered: ${finishReason}`,
45
- };
46
- }
47
- if (finishReason && ERROR_REASONS.has(finishReason)) {
48
- return {
49
- type: "incomplete",
50
- reason: "error",
51
- error: `LLM error: ${finishReason}`,
52
- };
53
- }
54
- return { type: "complete", reason: "stop" };
28
+ if (finishReason === "MAX_TOKENS") return {
29
+ type: "incomplete",
30
+ reason: "length"
31
+ };
32
+ if (finishReason && CONTENT_FILTER_REASONS.has(finishReason)) return {
33
+ type: "incomplete",
34
+ reason: "content-filter",
35
+ error: `Content filtered: ${finishReason}`
36
+ };
37
+ if (finishReason && ERROR_REASONS.has(finishReason)) return {
38
+ type: "incomplete",
39
+ reason: "error",
40
+ error: `LLM error: ${finishReason}`
41
+ };
42
+ return {
43
+ type: "complete",
44
+ reason: "stop"
45
+ };
46
+ };
47
+ const inlineDataToPart = (mimeType, data) => mimeType.startsWith("image/") ? {
48
+ type: "image",
49
+ mimeType,
50
+ data
51
+ } : {
52
+ type: "file",
53
+ mimeType,
54
+ data
55
+ };
56
+ const fileDataToPart = (fileUri, mimeType) => mimeType == null || mimeType.startsWith("image/") ? {
57
+ type: "image_url",
58
+ url: fileUri
59
+ } : {
60
+ type: "file_url",
61
+ url: fileUri,
62
+ mimeType
55
63
  };
56
- const inlineDataToPart = (mimeType, data) => mimeType.startsWith("image/")
57
- ? { type: "image", mimeType, data }
58
- : { type: "file", mimeType, data };
59
- const fileDataToPart = (fileUri, mimeType) => mimeType == null || mimeType.startsWith("image/")
60
- ? { type: "image_url", url: fileUri }
61
- : { type: "file_url", url: fileUri, mimeType };
62
- // ── Snake_case normalization ──
63
64
  const normalizeEventPart = (part) => {
64
- const p = part;
65
- const result = { ...p };
66
- if ("function_call" in p && !("functionCall" in p))
67
- result.functionCall = p.function_call;
68
- if ("function_response" in p && !("functionResponse" in p))
69
- result.functionResponse = p.function_response;
70
- if ("inline_data" in p && !("inlineData" in p))
71
- result.inlineData = p.inline_data;
72
- if ("file_data" in p && !("fileData" in p))
73
- result.fileData = p.file_data;
74
- if ("executable_code" in p && !("executableCode" in p))
75
- result.executableCode = p.executable_code;
76
- if ("code_execution_result" in p && !("codeExecutionResult" in p))
77
- result.codeExecutionResult = p.code_execution_result;
78
- return result;
65
+ const p = part;
66
+ const result = { ...p };
67
+ if ("function_call" in p && !("functionCall" in p)) result.functionCall = p.function_call;
68
+ if ("function_response" in p && !("functionResponse" in p)) result.functionResponse = p.function_response;
69
+ if ("inline_data" in p && !("inlineData" in p)) result.inlineData = p.inline_data;
70
+ if ("file_data" in p && !("fileData" in p)) result.fileData = p.file_data;
71
+ if ("executable_code" in p && !("executableCode" in p)) result.executableCode = p.executable_code;
72
+ if ("code_execution_result" in p && !("codeExecutionResult" in p)) result.codeExecutionResult = p.code_execution_result;
73
+ return result;
79
74
  };
80
75
  const normalizeEvent = (event) => {
81
- const e = event;
82
- const result = { ...e };
83
- if ("error_code" in e && !("errorCode" in e))
84
- result.errorCode = e.error_code;
85
- if ("error_message" in e && !("errorMessage" in e))
86
- result.errorMessage = e.error_message;
87
- if ("long_running_tool_ids" in e && !("longRunningToolIds" in e))
88
- result.longRunningToolIds = e.long_running_tool_ids;
89
- if ("turn_complete" in e && !("turnComplete" in e))
90
- result.turnComplete = e.turn_complete;
91
- if ("finish_reason" in e && !("finishReason" in e))
92
- result.finishReason = e.finish_reason;
93
- if ("invocation_id" in e && !("invocationId" in e))
94
- result.invocationId = e.invocation_id;
95
- if ("custom_metadata" in e && !("customMetadata" in e))
96
- result.customMetadata = e.custom_metadata;
97
- if ("grounding_metadata" in e && !("groundingMetadata" in e))
98
- result.groundingMetadata = e.grounding_metadata;
99
- if ("citation_metadata" in e && !("citationMetadata" in e))
100
- result.citationMetadata = e.citation_metadata;
101
- if ("usage_metadata" in e && !("usageMetadata" in e))
102
- result.usageMetadata = e.usage_metadata;
103
- if (result.actions) {
104
- const a = result.actions;
105
- const na = { ...a };
106
- if ("state_delta" in a && !("stateDelta" in a))
107
- na.stateDelta = a.state_delta;
108
- if ("artifact_delta" in a && !("artifactDelta" in a))
109
- na.artifactDelta = a.artifact_delta;
110
- if ("transfer_to_agent" in a && !("transferToAgent" in a))
111
- na.transferToAgent = a.transfer_to_agent;
112
- if ("skip_summarization" in a && !("skipSummarization" in a))
113
- na.skipSummarization = a.skip_summarization;
114
- if ("requested_auth_configs" in a && !("requestedAuthConfigs" in a))
115
- na.requestedAuthConfigs = a.requested_auth_configs;
116
- if ("requested_tool_confirmations" in a &&
117
- !("requestedToolConfirmations" in a))
118
- na.requestedToolConfirmations = a.requested_tool_confirmations;
119
- result.actions = na;
120
- }
121
- if (result.content && result.content.parts) {
122
- const content = result.content;
123
- const parts = content.parts;
124
- result.content = { ...content, parts: parts.map(normalizeEventPart) };
125
- }
126
- return result;
76
+ const e = event;
77
+ const result = { ...e };
78
+ if ("error_code" in e && !("errorCode" in e)) result.errorCode = e.error_code;
79
+ if ("error_message" in e && !("errorMessage" in e)) result.errorMessage = e.error_message;
80
+ if ("long_running_tool_ids" in e && !("longRunningToolIds" in e)) result.longRunningToolIds = e.long_running_tool_ids;
81
+ if ("turn_complete" in e && !("turnComplete" in e)) result.turnComplete = e.turn_complete;
82
+ if ("finish_reason" in e && !("finishReason" in e)) result.finishReason = e.finish_reason;
83
+ if ("invocation_id" in e && !("invocationId" in e)) result.invocationId = e.invocation_id;
84
+ if ("custom_metadata" in e && !("customMetadata" in e)) result.customMetadata = e.custom_metadata;
85
+ if ("grounding_metadata" in e && !("groundingMetadata" in e)) result.groundingMetadata = e.grounding_metadata;
86
+ if ("citation_metadata" in e && !("citationMetadata" in e)) result.citationMetadata = e.citation_metadata;
87
+ if ("usage_metadata" in e && !("usageMetadata" in e)) result.usageMetadata = e.usage_metadata;
88
+ if (result.actions) {
89
+ const a = result.actions;
90
+ const na = { ...a };
91
+ if ("state_delta" in a && !("stateDelta" in a)) na.stateDelta = a.state_delta;
92
+ if ("artifact_delta" in a && !("artifactDelta" in a)) na.artifactDelta = a.artifact_delta;
93
+ if ("transfer_to_agent" in a && !("transferToAgent" in a)) na.transferToAgent = a.transfer_to_agent;
94
+ if ("skip_summarization" in a && !("skipSummarization" in a)) na.skipSummarization = a.skip_summarization;
95
+ if ("requested_auth_configs" in a && !("requestedAuthConfigs" in a)) na.requestedAuthConfigs = a.requested_auth_configs;
96
+ if ("requested_tool_confirmations" in a && !("requestedToolConfirmations" in a)) na.requestedToolConfirmations = a.requested_tool_confirmations;
97
+ result.actions = na;
98
+ }
99
+ if (result.content && result.content.parts) {
100
+ const content = result.content;
101
+ const parts = content.parts;
102
+ result.content = {
103
+ ...content,
104
+ parts: parts.map(normalizeEventPart)
105
+ };
106
+ }
107
+ return result;
108
+ };
109
+ var AdkEventAccumulator = class {
110
+ messagesMap = /* @__PURE__ */ new Map();
111
+ currentMessageId = null;
112
+ partialTextBuffer = "";
113
+ partialReasoningBuffer = "";
114
+ accumulatedStateDelta = {};
115
+ accumulatedArtifactDelta = {};
116
+ lastAgentInfo = {};
117
+ lastTransferToAgent;
118
+ pendingLongRunningToolIds = /* @__PURE__ */ new Set();
119
+ toolConfirmations = [];
120
+ authRequests = [];
121
+ escalated = false;
122
+ messageMetadataMap = /* @__PURE__ */ new Map();
123
+ constructor(initialMessages) {
124
+ if (initialMessages) for (const msg of initialMessages) this.messagesMap.set(msg.id, msg);
125
+ }
126
+ processEvent(rawEvent) {
127
+ const event = normalizeEvent(rawEvent);
128
+ if (event.actions?.stateDelta) Object.assign(this.accumulatedStateDelta, event.actions.stateDelta);
129
+ if (event.actions?.artifactDelta) Object.assign(this.accumulatedArtifactDelta, event.actions.artifactDelta);
130
+ if (event.actions?.escalate) this.escalated = true;
131
+ if (event.actions?.transferToAgent) this.lastTransferToAgent = event.actions.transferToAgent;
132
+ if (event.longRunningToolIds?.length) for (const id of event.longRunningToolIds) this.pendingLongRunningToolIds.add(id);
133
+ if (event.actions?.requestedToolConfirmations) for (const [tcId, conf] of Object.entries(event.actions.requestedToolConfirmations)) {
134
+ const c = conf;
135
+ this.toolConfirmations.push({
136
+ toolCallId: tcId,
137
+ toolName: "",
138
+ args: {},
139
+ hint: c.hint ?? "",
140
+ confirmed: false,
141
+ payload: c.payload
142
+ });
143
+ }
144
+ if (event.actions?.requestedAuthConfigs) for (const [tcId, authConf] of Object.entries(event.actions.requestedAuthConfigs)) this.authRequests.push({
145
+ toolCallId: tcId,
146
+ authConfig: authConf
147
+ });
148
+ if (event.author && event.author !== "user") this.lastAgentInfo = {
149
+ name: event.author ?? void 0,
150
+ branch: event.branch ?? void 0
151
+ };
152
+ if (event.interrupted) {
153
+ if (this.currentMessageId) {
154
+ const msg = this.messagesMap.get(this.currentMessageId);
155
+ if (msg && msg.type === "ai" && !msg.status) {
156
+ const updated = {
157
+ ...msg,
158
+ content: [...this.getContentArray(msg)],
159
+ status: {
160
+ type: "incomplete",
161
+ reason: "cancelled"
162
+ }
163
+ };
164
+ this.messagesMap.set(updated.id, updated);
165
+ }
166
+ }
167
+ this.finalizeCurrentMessage();
168
+ return this.getMessages();
169
+ }
170
+ if (event.errorCode || event.errorMessage) {
171
+ this.finalizeCurrentMessage();
172
+ const errorMsg = this.getOrCreateAiMessage(event);
173
+ const errorText = event.errorMessage ?? event.errorCode ?? "Unknown error";
174
+ const updated = {
175
+ ...errorMsg,
176
+ content: [...this.getContentArray(errorMsg), {
177
+ type: "text",
178
+ text: errorText
179
+ }],
180
+ status: {
181
+ type: "incomplete",
182
+ reason: "error",
183
+ error: errorText
184
+ }
185
+ };
186
+ this.messagesMap.set(updated.id, updated);
187
+ this.currentMessageId = null;
188
+ return this.getMessages();
189
+ }
190
+ const parts = event.content?.parts;
191
+ if (!parts?.length) {
192
+ this.trackMessageMetadata(event);
193
+ return this.getMessages();
194
+ }
195
+ if (event.author === "user") {
196
+ this.finalizeCurrentMessage();
197
+ const humanParts = [];
198
+ for (const part of parts) if (part.text != null && !part.thought) humanParts.push({
199
+ type: "text",
200
+ text: part.text
201
+ });
202
+ else if (part.inlineData) humanParts.push(inlineDataToPart(part.inlineData.mimeType, part.inlineData.data));
203
+ else if (part.fileData) humanParts.push(fileDataToPart(part.fileData.fileUri, part.fileData.mimeType));
204
+ if (humanParts.length > 0) {
205
+ const id = event.id ?? v4();
206
+ const first = humanParts[0];
207
+ const content = humanParts.length === 1 && first?.type === "text" ? first.text : humanParts;
208
+ this.messagesMap.set(id, {
209
+ id,
210
+ type: "human",
211
+ content
212
+ });
213
+ }
214
+ return this.getMessages();
215
+ }
216
+ if (this.currentMessageId && event.author && event.author !== "user") {
217
+ const current = this.messagesMap.get(this.currentMessageId);
218
+ if (current && current.type === "ai" && current.author !== event.author) this.finalizeCurrentMessage();
219
+ }
220
+ for (const part of parts) this.processPart(part, event);
221
+ this.trackMessageMetadata(event);
222
+ if (isFinalResponse(event) && this.currentMessageId) {
223
+ const msg = this.messagesMap.get(this.currentMessageId);
224
+ const isHitlOnly = event.longRunningToolIds && event.longRunningToolIds.length > 0 && !event.actions?.skipSummarization;
225
+ if (msg && msg.type === "ai" && !msg.status && !isHitlOnly) {
226
+ const status = finishReasonToStatus(event.finishReason);
227
+ const updated = {
228
+ ...msg,
229
+ content: [...this.getContentArray(msg)],
230
+ status
231
+ };
232
+ this.messagesMap.set(updated.id, updated);
233
+ }
234
+ }
235
+ if (!event.partial || isFinalResponse(event)) this.finalizeCurrentMessage();
236
+ return this.getMessages();
237
+ }
238
+ processPart(part, event) {
239
+ if (part.functionCall && !event.partial) {
240
+ const name = part.functionCall.name;
241
+ if (name === ADK_REQUEST_CONFIRMATION) {
242
+ const callArgs = part.functionCall.args;
243
+ const original = callArgs.originalFunctionCall ?? callArgs.original_function_call;
244
+ const conf = callArgs.toolConfirmation ?? callArgs.tool_confirmation;
245
+ this.toolConfirmations.push({
246
+ toolCallId: part.functionCall.id ?? "",
247
+ toolName: original?.name ?? "",
248
+ args: original?.args ?? {},
249
+ hint: conf?.hint ?? "",
250
+ confirmed: false,
251
+ payload: conf?.payload
252
+ });
253
+ }
254
+ if (name === ADK_REQUEST_CREDENTIAL) {
255
+ const credArgs = part.functionCall.args;
256
+ const originalToolCallId = credArgs.function_call_id ?? part.functionCall.id ?? "";
257
+ const authConfig = credArgs.auth_config ?? credArgs;
258
+ this.authRequests.push({
259
+ toolCallId: originalToolCallId,
260
+ authConfig
261
+ });
262
+ }
263
+ }
264
+ if (part.text != null && part.thought) {
265
+ const msg = this.getOrCreateAiMessage(event);
266
+ if (event.partial) {
267
+ this.partialReasoningBuffer += part.text;
268
+ this.replaceLastReasoningContent(msg, this.partialReasoningBuffer);
269
+ } else {
270
+ this.partialReasoningBuffer = "";
271
+ this.replaceLastReasoningContent(msg, part.text);
272
+ }
273
+ return;
274
+ }
275
+ if (part.text != null) {
276
+ const msg = this.getOrCreateAiMessage(event);
277
+ if (event.partial) {
278
+ this.partialTextBuffer += part.text;
279
+ this.replaceLastTextContent(msg, this.partialTextBuffer);
280
+ } else {
281
+ this.partialTextBuffer = "";
282
+ this.replaceLastTextContent(msg, part.text);
283
+ }
284
+ return;
285
+ }
286
+ if (part.functionCall) {
287
+ if (event.partial) return;
288
+ const msg = this.getOrCreateAiMessage(event);
289
+ const toolCall = {
290
+ id: part.functionCall.id ?? v4(),
291
+ name: part.functionCall.name,
292
+ args: part.functionCall.args,
293
+ argsText: JSON.stringify(part.functionCall.args)
294
+ };
295
+ const existing = [...msg.tool_calls ?? []];
296
+ const idx = existing.findIndex((tc) => tc.id === toolCall.id);
297
+ if (idx >= 0) existing[idx] = toolCall;
298
+ else existing.push(toolCall);
299
+ const updated = {
300
+ ...msg,
301
+ content: [...this.getContentArray(msg)],
302
+ tool_calls: existing
303
+ };
304
+ this.messagesMap.set(updated.id, updated);
305
+ return;
306
+ }
307
+ if (part.functionResponse) {
308
+ this.finalizeCurrentMessage();
309
+ const toolMsg = {
310
+ id: v4(),
311
+ type: "tool",
312
+ tool_call_id: part.functionResponse.id ?? "",
313
+ name: part.functionResponse.name,
314
+ content: JSON.stringify(part.functionResponse.response),
315
+ status: "success"
316
+ };
317
+ this.messagesMap.set(toolMsg.id, toolMsg);
318
+ return;
319
+ }
320
+ if (part.executableCode) {
321
+ const msg = this.getOrCreateAiMessage(event);
322
+ this.appendContent(msg, {
323
+ type: "code",
324
+ code: part.executableCode.code,
325
+ language: part.executableCode.language ?? "python"
326
+ });
327
+ return;
328
+ }
329
+ if (part.codeExecutionResult) {
330
+ const msg = this.getOrCreateAiMessage(event);
331
+ this.appendContent(msg, {
332
+ type: "code_result",
333
+ output: part.codeExecutionResult.output,
334
+ outcome: part.codeExecutionResult.outcome ?? "OUTCOME_OK"
335
+ });
336
+ return;
337
+ }
338
+ if (part.inlineData) {
339
+ const msg = this.getOrCreateAiMessage(event);
340
+ this.appendContent(msg, inlineDataToPart(part.inlineData.mimeType, part.inlineData.data));
341
+ return;
342
+ }
343
+ if (part.fileData) {
344
+ const msg = this.getOrCreateAiMessage(event);
345
+ this.appendContent(msg, fileDataToPart(part.fileData.fileUri, part.fileData.mimeType));
346
+ }
347
+ }
348
+ trackMessageMetadata(event) {
349
+ if (!this.currentMessageId || !event.groundingMetadata && !event.citationMetadata && !event.usageMetadata) return;
350
+ const updated = { ...this.messageMetadataMap.get(this.currentMessageId) ?? {} };
351
+ if (event.groundingMetadata) updated.groundingMetadata = event.groundingMetadata;
352
+ if (event.citationMetadata) updated.citationMetadata = event.citationMetadata;
353
+ if (event.usageMetadata) updated.usageMetadata = event.usageMetadata;
354
+ this.messageMetadataMap.set(this.currentMessageId, updated);
355
+ }
356
+ getContentArray(msg) {
357
+ return Array.isArray(msg.content) ? msg.content : [];
358
+ }
359
+ getOrCreateAiMessage(event) {
360
+ if (this.currentMessageId) {
361
+ const existing = this.messagesMap.get(this.currentMessageId);
362
+ if (existing && existing.type === "ai") return existing;
363
+ }
364
+ const id = v4();
365
+ const msg = {
366
+ id,
367
+ type: "ai",
368
+ content: [],
369
+ ...event.author != null && { author: event.author },
370
+ ...event.branch != null && { branch: event.branch }
371
+ };
372
+ this.messagesMap.set(id, msg);
373
+ this.currentMessageId = id;
374
+ this.partialTextBuffer = "";
375
+ this.partialReasoningBuffer = "";
376
+ return msg;
377
+ }
378
+ appendContent(msg, part) {
379
+ const content = [...this.getContentArray(msg), part];
380
+ const updated = {
381
+ ...msg,
382
+ content
383
+ };
384
+ this.messagesMap.set(updated.id, updated);
385
+ }
386
+ replaceLastTextContent(msg, text) {
387
+ const content = [...this.getContentArray(msg)];
388
+ const lastTextIdx = content.findLastIndex((p) => p.type === "text");
389
+ if (lastTextIdx >= 0) content[lastTextIdx] = {
390
+ type: "text",
391
+ text
392
+ };
393
+ else content.push({
394
+ type: "text",
395
+ text
396
+ });
397
+ const updated = {
398
+ ...msg,
399
+ content
400
+ };
401
+ this.messagesMap.set(updated.id, updated);
402
+ }
403
+ replaceLastReasoningContent(msg, text) {
404
+ const content = [...this.getContentArray(msg)];
405
+ const lastIdx = content.findLastIndex((p) => p.type === "reasoning");
406
+ if (lastIdx >= 0) content[lastIdx] = {
407
+ type: "reasoning",
408
+ text
409
+ };
410
+ else content.push({
411
+ type: "reasoning",
412
+ text
413
+ });
414
+ const updated = {
415
+ ...msg,
416
+ content
417
+ };
418
+ this.messagesMap.set(updated.id, updated);
419
+ }
420
+ finalizeCurrentMessage() {
421
+ this.partialTextBuffer = "";
422
+ this.partialReasoningBuffer = "";
423
+ this.currentMessageId = null;
424
+ }
425
+ getMessages() {
426
+ return [...this.messagesMap.values()];
427
+ }
428
+ getStateDelta() {
429
+ return { ...this.accumulatedStateDelta };
430
+ }
431
+ getArtifactDelta() {
432
+ return { ...this.accumulatedArtifactDelta };
433
+ }
434
+ getAgentInfo() {
435
+ return { ...this.lastAgentInfo };
436
+ }
437
+ getLastTransferToAgent() {
438
+ return this.lastTransferToAgent;
439
+ }
440
+ getLongRunningToolIds() {
441
+ return [...this.pendingLongRunningToolIds];
442
+ }
443
+ getToolConfirmations() {
444
+ return [...this.toolConfirmations];
445
+ }
446
+ getAuthRequests() {
447
+ return [...this.authRequests];
448
+ }
449
+ isEscalated() {
450
+ return this.escalated;
451
+ }
452
+ getMessageMetadata() {
453
+ return new Map(this.messageMetadataMap);
454
+ }
127
455
  };
128
- // ── Accumulator ──
129
- export class AdkEventAccumulator {
130
- messagesMap = new Map();
131
- currentMessageId = null;
132
- partialTextBuffer = "";
133
- partialReasoningBuffer = "";
134
- accumulatedStateDelta = {};
135
- accumulatedArtifactDelta = {};
136
- lastAgentInfo = {};
137
- lastTransferToAgent;
138
- pendingLongRunningToolIds = new Set();
139
- toolConfirmations = [];
140
- authRequests = [];
141
- escalated = false;
142
- messageMetadataMap = new Map();
143
- constructor(initialMessages) {
144
- if (initialMessages) {
145
- for (const msg of initialMessages) {
146
- this.messagesMap.set(msg.id, msg);
147
- }
148
- }
149
- }
150
- processEvent(rawEvent) {
151
- const event = normalizeEvent(rawEvent);
152
- // Accumulate state delta
153
- if (event.actions?.stateDelta) {
154
- Object.assign(this.accumulatedStateDelta, event.actions.stateDelta);
155
- }
156
- // Accumulate artifact delta
157
- if (event.actions?.artifactDelta) {
158
- Object.assign(this.accumulatedArtifactDelta, event.actions.artifactDelta);
159
- }
160
- // Track escalation
161
- if (event.actions?.escalate) {
162
- this.escalated = true;
163
- }
164
- // Track agent transfer
165
- if (event.actions?.transferToAgent) {
166
- this.lastTransferToAgent = event.actions.transferToAgent;
167
- }
168
- // Track long-running tool IDs. Accumulate across events so that multiple
169
- // HITL interrupts emitted in the same turn are all tracked — a
170
- // single-event replacement would drop earlier ids.
171
- if (event.longRunningToolIds?.length) {
172
- for (const id of event.longRunningToolIds) {
173
- this.pendingLongRunningToolIds.add(id);
174
- }
175
- }
176
- // Track tool confirmations from actions
177
- if (event.actions?.requestedToolConfirmations) {
178
- for (const [tcId, conf] of Object.entries(event.actions.requestedToolConfirmations)) {
179
- const c = conf;
180
- this.toolConfirmations.push({
181
- toolCallId: tcId,
182
- toolName: "",
183
- args: {},
184
- hint: c.hint ?? "",
185
- confirmed: false,
186
- payload: c.payload,
187
- });
188
- }
189
- }
190
- // Track auth requests from actions
191
- if (event.actions?.requestedAuthConfigs) {
192
- for (const [tcId, authConf] of Object.entries(event.actions.requestedAuthConfigs)) {
193
- this.authRequests.push({ toolCallId: tcId, authConfig: authConf });
194
- }
195
- }
196
- // Track agent info
197
- if (event.author && event.author !== "user") {
198
- this.lastAgentInfo = {
199
- name: event.author ?? undefined,
200
- branch: event.branch ?? undefined,
201
- };
202
- }
203
- // Handle interrupted events
204
- if (event.interrupted) {
205
- if (this.currentMessageId) {
206
- const msg = this.messagesMap.get(this.currentMessageId);
207
- if (msg && msg.type === "ai" && !msg.status) {
208
- const updated = {
209
- ...msg,
210
- content: [...this.getContentArray(msg)],
211
- status: { type: "incomplete", reason: "cancelled" },
212
- };
213
- this.messagesMap.set(updated.id, updated);
214
- }
215
- }
216
- this.finalizeCurrentMessage();
217
- return this.getMessages();
218
- }
219
- // Handle error events
220
- if (event.errorCode || event.errorMessage) {
221
- this.finalizeCurrentMessage();
222
- const errorMsg = this.getOrCreateAiMessage(event);
223
- const errorText = event.errorMessage ?? event.errorCode ?? "Unknown error";
224
- const updated = {
225
- ...errorMsg,
226
- content: [
227
- ...this.getContentArray(errorMsg),
228
- { type: "text", text: errorText },
229
- ],
230
- status: { type: "incomplete", reason: "error", error: errorText },
231
- };
232
- this.messagesMap.set(updated.id, updated);
233
- this.currentMessageId = null;
234
- return this.getMessages();
235
- }
236
- const parts = event.content?.parts;
237
- if (!parts?.length) {
238
- // Track metadata even for content-less events (e.g. turnComplete)
239
- this.trackMessageMetadata(event);
240
- return this.getMessages();
241
- }
242
- // User-authored events → create human message, not AI.
243
- // Without this, user events fall through to processPart →
244
- // getOrCreateAiMessage, producing type:"ai" messages that
245
- // convertAdkMessage maps to role:"assistant".
246
- if (event.author === "user") {
247
- this.finalizeCurrentMessage();
248
- const humanParts = [];
249
- for (const part of parts) {
250
- if (part.text != null && !part.thought) {
251
- humanParts.push({ type: "text", text: part.text });
252
- }
253
- else if (part.inlineData) {
254
- humanParts.push(inlineDataToPart(part.inlineData.mimeType, part.inlineData.data));
255
- }
256
- else if (part.fileData) {
257
- humanParts.push(fileDataToPart(part.fileData.fileUri, part.fileData.mimeType));
258
- }
259
- }
260
- if (humanParts.length > 0) {
261
- const id = event.id ?? uuidv4();
262
- const first = humanParts[0];
263
- const content = humanParts.length === 1 && first?.type === "text"
264
- ? first.text
265
- : humanParts;
266
- this.messagesMap.set(id, { id, type: "human", content });
267
- }
268
- return this.getMessages();
269
- }
270
- // If author changed, finalize previous message
271
- if (this.currentMessageId && event.author && event.author !== "user") {
272
- const current = this.messagesMap.get(this.currentMessageId);
273
- if (current && current.type === "ai" && current.author !== event.author) {
274
- this.finalizeCurrentMessage();
275
- }
276
- }
277
- for (const part of parts) {
278
- this.processPart(part, event);
279
- }
280
- // Track per-message metadata (grounding, citation, usage)
281
- this.trackMessageMetadata(event);
282
- // Check isFinalResponse (can be true even for partial events via skipSummarization/longRunningToolIds)
283
- if (isFinalResponse(event) && this.currentMessageId) {
284
- const msg = this.messagesMap.get(this.currentMessageId);
285
- // Skip manual "complete" when longRunningToolIds is the sole reason for
286
- // isFinalResponse — let auto-status apply requires-action for pending tool calls.
287
- const isHitlOnly = event.longRunningToolIds &&
288
- event.longRunningToolIds.length > 0 &&
289
- !event.actions?.skipSummarization;
290
- if (msg && msg.type === "ai" && !msg.status && !isHitlOnly) {
291
- const status = finishReasonToStatus(event.finishReason);
292
- const updated = {
293
- ...msg,
294
- content: [...this.getContentArray(msg)],
295
- status,
296
- };
297
- this.messagesMap.set(updated.id, updated);
298
- }
299
- }
300
- // Non-partial event finalizes the current message
301
- if (!event.partial || isFinalResponse(event)) {
302
- this.finalizeCurrentMessage();
303
- }
304
- return this.getMessages();
305
- }
306
- processPart(part, event) {
307
- // Detect special ADK function calls
308
- if (part.functionCall && !event.partial) {
309
- const name = part.functionCall.name;
310
- // Tool confirmation request
311
- if (name === ADK_REQUEST_CONFIRMATION) {
312
- const callArgs = part.functionCall.args;
313
- // ADK JS: args keys are "originalFunctionCall" and "toolConfirmation"
314
- // ADK Python: args keys are "original_function_call" and "tool_confirmation"
315
- const original = callArgs.originalFunctionCall ??
316
- callArgs.original_function_call;
317
- const conf = callArgs.toolConfirmation ??
318
- callArgs.tool_confirmation;
319
- this.toolConfirmations.push({
320
- toolCallId: part.functionCall.id ?? "",
321
- toolName: original?.name ?? "",
322
- args: original?.args ?? {},
323
- hint: conf?.hint ?? "",
324
- confirmed: false,
325
- payload: conf?.payload,
326
- });
327
- }
328
- // Auth credential request
329
- if (name === ADK_REQUEST_CREDENTIAL) {
330
- const credArgs = part.functionCall.args;
331
- // ADK JS: args keys are "function_call_id" and "auth_config"
332
- const originalToolCallId = credArgs.function_call_id ?? part.functionCall.id ?? "";
333
- const authConfig = credArgs.auth_config ?? credArgs;
334
- this.authRequests.push({
335
- toolCallId: originalToolCallId,
336
- authConfig,
337
- });
338
- }
339
- }
340
- // Text with thought=true → reasoning (accumulated)
341
- if (part.text != null && part.thought) {
342
- const msg = this.getOrCreateAiMessage(event);
343
- if (event.partial) {
344
- this.partialReasoningBuffer += part.text;
345
- this.replaceLastReasoningContent(msg, this.partialReasoningBuffer);
346
- }
347
- else {
348
- this.partialReasoningBuffer = "";
349
- this.replaceLastReasoningContent(msg, part.text);
350
- }
351
- return;
352
- }
353
- // Regular text
354
- if (part.text != null) {
355
- const msg = this.getOrCreateAiMessage(event);
356
- if (event.partial) {
357
- this.partialTextBuffer += part.text;
358
- this.replaceLastTextContent(msg, this.partialTextBuffer);
359
- }
360
- else {
361
- this.partialTextBuffer = "";
362
- this.replaceLastTextContent(msg, part.text);
363
- }
364
- return;
365
- }
366
- // Function call — skip partial events (args may be incomplete)
367
- if (part.functionCall) {
368
- if (event.partial)
369
- return;
370
- const msg = this.getOrCreateAiMessage(event);
371
- const toolCall = {
372
- id: part.functionCall.id ?? uuidv4(),
373
- name: part.functionCall.name,
374
- args: part.functionCall.args,
375
- argsText: JSON.stringify(part.functionCall.args),
376
- };
377
- const existing = [...(msg.tool_calls ?? [])];
378
- const idx = existing.findIndex((tc) => tc.id === toolCall.id);
379
- if (idx >= 0) {
380
- existing[idx] = toolCall;
381
- }
382
- else {
383
- existing.push(toolCall);
384
- }
385
- const updated = {
386
- ...msg,
387
- content: [...this.getContentArray(msg)],
388
- tool_calls: existing,
389
- };
390
- this.messagesMap.set(updated.id, updated);
391
- return;
392
- }
393
- // Function response → tool message
394
- if (part.functionResponse) {
395
- this.finalizeCurrentMessage();
396
- const toolMsg = {
397
- id: uuidv4(),
398
- type: "tool",
399
- tool_call_id: part.functionResponse.id ?? "",
400
- name: part.functionResponse.name,
401
- content: JSON.stringify(part.functionResponse.response),
402
- status: "success",
403
- };
404
- this.messagesMap.set(toolMsg.id, toolMsg);
405
- return;
406
- }
407
- // Executable code
408
- if (part.executableCode) {
409
- const msg = this.getOrCreateAiMessage(event);
410
- this.appendContent(msg, {
411
- type: "code",
412
- code: part.executableCode.code,
413
- language: part.executableCode.language ?? "python",
414
- });
415
- return;
416
- }
417
- // Code execution result
418
- if (part.codeExecutionResult) {
419
- const msg = this.getOrCreateAiMessage(event);
420
- this.appendContent(msg, {
421
- type: "code_result",
422
- output: part.codeExecutionResult.output,
423
- outcome: part.codeExecutionResult.outcome ?? "OUTCOME_OK",
424
- });
425
- return;
426
- }
427
- if (part.inlineData) {
428
- const msg = this.getOrCreateAiMessage(event);
429
- this.appendContent(msg, inlineDataToPart(part.inlineData.mimeType, part.inlineData.data));
430
- return;
431
- }
432
- if (part.fileData) {
433
- const msg = this.getOrCreateAiMessage(event);
434
- this.appendContent(msg, fileDataToPart(part.fileData.fileUri, part.fileData.mimeType));
435
- }
436
- }
437
- trackMessageMetadata(event) {
438
- if (!this.currentMessageId ||
439
- (!event.groundingMetadata &&
440
- !event.citationMetadata &&
441
- !event.usageMetadata))
442
- return;
443
- const existing = this.messageMetadataMap.get(this.currentMessageId) ?? {};
444
- const updated = { ...existing };
445
- if (event.groundingMetadata)
446
- updated.groundingMetadata = event.groundingMetadata;
447
- if (event.citationMetadata)
448
- updated.citationMetadata = event.citationMetadata;
449
- if (event.usageMetadata)
450
- updated.usageMetadata = event.usageMetadata;
451
- this.messageMetadataMap.set(this.currentMessageId, updated);
452
- }
453
- getContentArray(msg) {
454
- return Array.isArray(msg.content)
455
- ? msg.content
456
- : [];
457
- }
458
- getOrCreateAiMessage(event) {
459
- if (this.currentMessageId) {
460
- const existing = this.messagesMap.get(this.currentMessageId);
461
- if (existing && existing.type === "ai") {
462
- return existing;
463
- }
464
- }
465
- const id = uuidv4();
466
- const msg = {
467
- id,
468
- type: "ai",
469
- content: [],
470
- ...(event.author != null && { author: event.author }),
471
- ...(event.branch != null && { branch: event.branch }),
472
- };
473
- this.messagesMap.set(id, msg);
474
- this.currentMessageId = id;
475
- this.partialTextBuffer = "";
476
- this.partialReasoningBuffer = "";
477
- return msg;
478
- }
479
- appendContent(msg, part) {
480
- const content = [...this.getContentArray(msg), part];
481
- const updated = { ...msg, content };
482
- this.messagesMap.set(updated.id, updated);
483
- }
484
- replaceLastTextContent(msg, text) {
485
- const content = [...this.getContentArray(msg)];
486
- const lastTextIdx = content.findLastIndex((p) => p.type === "text");
487
- if (lastTextIdx >= 0) {
488
- content[lastTextIdx] = { type: "text", text };
489
- }
490
- else {
491
- content.push({ type: "text", text });
492
- }
493
- const updated = { ...msg, content };
494
- this.messagesMap.set(updated.id, updated);
495
- }
496
- replaceLastReasoningContent(msg, text) {
497
- const content = [...this.getContentArray(msg)];
498
- const lastIdx = content.findLastIndex((p) => p.type === "reasoning");
499
- if (lastIdx >= 0) {
500
- content[lastIdx] = { type: "reasoning", text };
501
- }
502
- else {
503
- content.push({ type: "reasoning", text });
504
- }
505
- const updated = { ...msg, content };
506
- this.messagesMap.set(updated.id, updated);
507
- }
508
- finalizeCurrentMessage() {
509
- this.partialTextBuffer = "";
510
- this.partialReasoningBuffer = "";
511
- this.currentMessageId = null;
512
- }
513
- getMessages() {
514
- return [...this.messagesMap.values()];
515
- }
516
- getStateDelta() {
517
- return { ...this.accumulatedStateDelta };
518
- }
519
- getArtifactDelta() {
520
- return { ...this.accumulatedArtifactDelta };
521
- }
522
- getAgentInfo() {
523
- return { ...this.lastAgentInfo };
524
- }
525
- getLastTransferToAgent() {
526
- return this.lastTransferToAgent;
527
- }
528
- getLongRunningToolIds() {
529
- return [...this.pendingLongRunningToolIds];
530
- }
531
- getToolConfirmations() {
532
- return [...this.toolConfirmations];
533
- }
534
- getAuthRequests() {
535
- return [...this.authRequests];
536
- }
537
- isEscalated() {
538
- return this.escalated;
539
- }
540
- getMessageMetadata() {
541
- return new Map(this.messageMetadataMap);
542
- }
543
- }
456
+ //#endregion
457
+ export { AdkEventAccumulator, isFinalResponse };
458
+
544
459
  //# sourceMappingURL=AdkEventAccumulator.js.map