@assistant-ui/react-google-adk 0.0.28 → 0.0.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AdkEventAccumulator.d.ts.map +1 -1
- package/dist/AdkEventAccumulator.js +2 -2
- package/dist/AdkEventAccumulator.js.map +1 -1
- package/dist/convertToAdkMessages.js +1 -1
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +6 -8
- package/dist/hooks.js.map +1 -1
- package/dist/parseAdkEvent.d.ts.map +1 -1
- package/dist/parseAdkEvent.js +15 -2
- package/dist/parseAdkEvent.js.map +1 -1
- package/dist/useAdkMessages.d.ts.map +1 -1
- package/dist/useAdkMessages.js +8 -5
- package/dist/useAdkMessages.js.map +1 -1
- package/dist/useAdkRuntime.d.ts.map +1 -1
- package/dist/useAdkRuntime.js +4 -2
- package/dist/useAdkRuntime.js.map +1 -1
- package/package.json +5 -5
- package/src/AdkClient.test.ts +53 -0
- package/src/AdkEventAccumulator.test.ts +21 -0
- package/src/AdkEventAccumulator.ts +3 -2
- package/src/hooks.render.test.tsx +74 -0
- package/src/hooks.test.tsx +33 -0
- package/src/hooks.ts +17 -22
- package/src/parseAdkEvent.ts +36 -7
- package/src/useAdkMessages.test.ts +99 -0
- package/src/useAdkMessages.ts +29 -9
- package/src/useAdkRuntime.replacement.test.tsx +138 -0
- package/src/useAdkRuntime.ts +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdkEventAccumulator.d.ts","names":[],"sources":["../src/AdkEventAccumulator.ts"],"mappings":";;;;;;cAwCa,kBAAmB,OAAO;cAqJ1B;UACH;UACA;UACA;UACA;UACA;UACA;UACA;UACA;
|
|
1
|
+
{"version":3,"file":"AdkEventAccumulator.d.ts","names":[],"sources":["../src/AdkEventAccumulator.ts"],"mappings":";;;;;;cAwCa,kBAAmB,OAAO;cAqJ1B;UACH;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UAEA;UAIA;UACA;UACA;UACA;UACA;UACA;UAGA;EACI,YAAA,kBAAkB;EAQ9B,aAAa,UAAU,WAAW;UAoN1B;UA6JA;UAmBA;UAMA;UAyBA;UASA;UAYA;UAeA;EAMR,eAAe;EAIf,iBAAiB;EAIjB,oBAAoB;EAIpB;IAAkB;IAA2B;;EAI7C;EAIA;EAIA,wBAAwB;EAIxB,mBAAmB;EAInB;EAIA,sBAAsB,YAAY"}
|
|
@@ -126,8 +126,8 @@ var AdkEventAccumulator = class {
|
|
|
126
126
|
finalTextReplacedThisEvent = false;
|
|
127
127
|
finalReasoningReplacedThisEvent = false;
|
|
128
128
|
partialReasoningBuffer = "";
|
|
129
|
-
accumulatedStateDelta =
|
|
130
|
-
accumulatedArtifactDelta =
|
|
129
|
+
accumulatedStateDelta = Object.create(null);
|
|
130
|
+
accumulatedArtifactDelta = Object.create(null);
|
|
131
131
|
lastAgentInfo = {};
|
|
132
132
|
lastTransferToAgent;
|
|
133
133
|
pendingLongRunningToolIds = /* @__PURE__ */ new Set();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdkEventAccumulator.js","names":[],"sources":["../src/AdkEventAccumulator.ts"],"sourcesContent":["import { generateId } from \"@assistant-ui/core\";\nimport type { MessageStatus } from \"@assistant-ui/core\";\nimport type {\n AdkEvent,\n AdkEventPart,\n AdkMessage,\n AdkMessageContentPart,\n AdkToolCall,\n AdkToolConfirmation,\n AdkAuthRequest,\n AdkMessageMetadata,\n} from \"./types\";\nimport type { ReadonlyJSONObject } from \"assistant-stream/utils\";\n\ntype InProgressMessage = AdkMessage & { type: \"ai\" };\n\n/**\n * A session load replays the stored events through a fresh accumulator, so a\n * message needs an id derived from the event that carries it rather than one\n * minted per replay. An event with no id of its own has never been through the\n * session and has nothing stable to derive from, so it keeps a generated one.\n *\n * A human message keeps the bare event id it has always had. The other kinds\n * take a suffixed namespace, since one event can carry several of them: a tool\n * message by the index of its part, an assistant message by how many this\n * event has already opened.\n */\nconst toolMessageId = (event: AdkEvent, partIndex: number): string =>\n event.id ? `${event.id}:${partIndex}` : generateId();\n\nconst aiMessageId = (event: AdkEvent, ordinal: number): string =>\n event.id ? `${event.id}:ai${ordinal === 0 ? \"\" : ordinal}` : generateId();\n\nconst ADK_REQUEST_CONFIRMATION = \"adk_request_confirmation\";\nconst ADK_REQUEST_CREDENTIAL = \"adk_request_credential\";\n\n/**\n * Checks if an event is a final response using the same logic as ADK's\n * `isFinalResponse()`.\n */\nexport const isFinalResponse = (event: AdkEvent): boolean => {\n if (\n event.actions?.skipSummarization ||\n (event.longRunningToolIds && event.longRunningToolIds.length > 0)\n ) {\n return true;\n }\n\n const parts = event.content?.parts;\n return (\n !event.partial &&\n (parts?.length ?? 0) > 0 &&\n !parts!.some((p) => p.functionCall) &&\n !parts!.some((p) => p.functionResponse) &&\n !parts![parts!.length - 1]?.codeExecutionResult\n );\n};\n\nconst CONTENT_FILTER_REASONS = new Set([\n \"SAFETY\",\n \"RECITATION\",\n \"BLOCKLIST\",\n \"PROHIBITED_CONTENT\",\n \"SPII\",\n \"LANGUAGE\",\n \"IMAGE_SAFETY\",\n \"IMAGE_RECITATION\",\n \"IMAGE_OTHER\",\n \"IMAGE_PROHIBITED_CONTENT\",\n]);\n\nconst ERROR_REASONS = new Set([\n \"MALFORMED_FUNCTION_CALL\",\n \"UNEXPECTED_TOOL_CALL\",\n]);\n\nconst finishReasonToStatus = (\n finishReason: string | undefined,\n): MessageStatus => {\n if (finishReason === \"MAX_TOKENS\") {\n return { type: \"incomplete\", reason: \"length\" };\n }\n if (finishReason && CONTENT_FILTER_REASONS.has(finishReason)) {\n return {\n type: \"incomplete\",\n reason: \"content-filter\",\n error: `Content filtered: ${finishReason}`,\n };\n }\n if (finishReason && ERROR_REASONS.has(finishReason)) {\n return {\n type: \"incomplete\",\n reason: \"error\",\n error: `LLM error: ${finishReason}`,\n };\n }\n return { type: \"complete\", reason: \"stop\" };\n};\n\nconst inlineDataToPart = (\n mimeType: string,\n data: string,\n): AdkMessageContentPart =>\n mimeType.startsWith(\"image/\")\n ? { type: \"image\", mimeType, data }\n : { type: \"file\", mimeType, data };\n\nconst fileDataToPart = (\n fileUri: string,\n mimeType: string | undefined,\n): AdkMessageContentPart =>\n mimeType == null || mimeType.startsWith(\"image/\")\n ? { type: \"image_url\", url: fileUri }\n : { type: \"file_url\", url: fileUri, mimeType };\n\n// ── Snake_case normalization ──\n\nconst normalizeEventPart = (part: AdkEventPart): AdkEventPart => {\n const p = part as Record<string, unknown>;\n const result: Record<string, unknown> = { ...p };\n if (\"function_call\" in p && !(\"functionCall\" in p))\n result.functionCall = p.function_call;\n if (\"function_response\" in p && !(\"functionResponse\" in p))\n result.functionResponse = p.function_response;\n if (\"inline_data\" in p && !(\"inlineData\" in p))\n result.inlineData = p.inline_data;\n if (\"file_data\" in p && !(\"fileData\" in p)) result.fileData = p.file_data;\n if (\"executable_code\" in p && !(\"executableCode\" in p))\n result.executableCode = p.executable_code;\n if (\"code_execution_result\" in p && !(\"codeExecutionResult\" in p))\n result.codeExecutionResult = p.code_execution_result;\n return result as AdkEventPart;\n};\n\nconst normalizeEvent = (event: AdkEvent): AdkEvent => {\n const e = event as Record<string, unknown>;\n const result: Record<string, unknown> = { ...e };\n if (\"error_code\" in e && !(\"errorCode\" in e)) result.errorCode = e.error_code;\n if (\"error_message\" in e && !(\"errorMessage\" in e))\n result.errorMessage = e.error_message;\n if (\"long_running_tool_ids\" in e && !(\"longRunningToolIds\" in e))\n result.longRunningToolIds = e.long_running_tool_ids;\n if (\"turn_complete\" in e && !(\"turnComplete\" in e))\n result.turnComplete = e.turn_complete;\n if (\"finish_reason\" in e && !(\"finishReason\" in e))\n result.finishReason = e.finish_reason;\n if (\"invocation_id\" in e && !(\"invocationId\" in e))\n result.invocationId = e.invocation_id;\n if (\"custom_metadata\" in e && !(\"customMetadata\" in e))\n result.customMetadata = e.custom_metadata;\n if (\"grounding_metadata\" in e && !(\"groundingMetadata\" in e))\n result.groundingMetadata = e.grounding_metadata;\n if (\"citation_metadata\" in e && !(\"citationMetadata\" in e))\n result.citationMetadata = e.citation_metadata;\n if (\"usage_metadata\" in e && !(\"usageMetadata\" in e))\n result.usageMetadata = e.usage_metadata;\n\n if (result.actions) {\n const a = result.actions as Record<string, unknown>;\n const na: Record<string, unknown> = { ...a };\n if (\"state_delta\" in a && !(\"stateDelta\" in a))\n na.stateDelta = a.state_delta;\n if (\"artifact_delta\" in a && !(\"artifactDelta\" in a))\n na.artifactDelta = a.artifact_delta;\n if (\"transfer_to_agent\" in a && !(\"transferToAgent\" in a))\n na.transferToAgent = a.transfer_to_agent;\n if (\"skip_summarization\" in a && !(\"skipSummarization\" in a))\n na.skipSummarization = a.skip_summarization;\n if (\"requested_auth_configs\" in a && !(\"requestedAuthConfigs\" in a))\n na.requestedAuthConfigs = a.requested_auth_configs;\n if (\n \"requested_tool_confirmations\" in a &&\n !(\"requestedToolConfirmations\" in a)\n )\n na.requestedToolConfirmations = a.requested_tool_confirmations;\n result.actions = na;\n }\n\n if (result.content && (result.content as Record<string, unknown>).parts) {\n const content = result.content as Record<string, unknown>;\n const parts = content.parts as AdkEventPart[];\n result.content = { ...content, parts: parts.map(normalizeEventPart) };\n }\n\n return result as AdkEvent;\n};\n\n// ── Accumulator ──\n\nexport class AdkEventAccumulator {\n private messagesMap = new Map<string, AdkMessage>();\n private currentMessageId: string | null = null;\n private partialTextBuffer = \"\";\n private finalTextReplacedThisEvent = false;\n private finalReasoningReplacedThisEvent = false;\n private partialReasoningBuffer = \"\";\n private accumulatedStateDelta: Record<string, unknown> = {};\n private accumulatedArtifactDelta: Record<string, number> = {};\n private lastAgentInfo: {\n name?: string | undefined;\n branch?: string | undefined;\n } = {};\n private lastTransferToAgent: string | undefined;\n private pendingLongRunningToolIds = new Set<string>();\n private toolConfirmations: AdkToolConfirmation[] = [];\n private authRequests: AdkAuthRequest[] = [];\n private escalated = false;\n private messageMetadataMap = new Map<string, AdkMessageMetadata>();\n // How many assistant messages each event has opened, so a replay of that\n // event opens them with the same ids.\n private aiMessageOrdinals = new Map<string, number>();\n constructor(initialMessages?: AdkMessage[]) {\n if (initialMessages) {\n for (const msg of initialMessages) {\n this.messagesMap.set(msg.id, msg);\n }\n }\n }\n\n processEvent(rawEvent: AdkEvent): AdkMessage[] {\n const event = normalizeEvent(rawEvent);\n\n // Accumulate state delta\n if (event.actions?.stateDelta) {\n Object.assign(this.accumulatedStateDelta, event.actions.stateDelta);\n }\n\n // Accumulate artifact delta\n if (event.actions?.artifactDelta) {\n Object.assign(this.accumulatedArtifactDelta, event.actions.artifactDelta);\n }\n\n // Track escalation\n if (event.actions?.escalate) {\n this.escalated = true;\n }\n\n // Track agent transfer\n if (event.actions?.transferToAgent) {\n this.lastTransferToAgent = event.actions.transferToAgent;\n }\n\n // Track long-running tool IDs. Accumulate across events so that multiple\n // HITL interrupts emitted in the same turn are all tracked — a\n // single-event replacement would drop earlier ids.\n if (event.longRunningToolIds?.length) {\n for (const id of event.longRunningToolIds) {\n this.pendingLongRunningToolIds.add(id);\n }\n }\n\n // Track tool confirmations from actions\n if (event.actions?.requestedToolConfirmations) {\n for (const [tcId, conf] of Object.entries(\n event.actions.requestedToolConfirmations,\n )) {\n const c = conf as Record<string, unknown>;\n this.toolConfirmations.push({\n toolCallId: tcId,\n toolName: \"\",\n args: {},\n hint: (c.hint as string) ?? \"\",\n confirmed: false,\n payload: c.payload,\n });\n }\n }\n\n // Track auth requests from actions\n if (event.actions?.requestedAuthConfigs) {\n for (const [tcId, authConf] of Object.entries(\n event.actions.requestedAuthConfigs,\n )) {\n this.authRequests.push({ toolCallId: tcId, authConfig: authConf });\n }\n }\n\n // Track agent info\n if (event.author && event.author !== \"user\") {\n this.lastAgentInfo = {\n name: event.author ?? undefined,\n branch: event.branch ?? undefined,\n };\n }\n\n // Handle interrupted events\n if (event.interrupted) {\n if (this.currentMessageId) {\n const msg = this.messagesMap.get(this.currentMessageId);\n if (msg && msg.type === \"ai\" && !msg.status) {\n const updated: InProgressMessage = {\n ...msg,\n content: [...this.getContentArray(msg)],\n status: { type: \"incomplete\", reason: \"cancelled\" },\n };\n this.messagesMap.set(updated.id, updated);\n }\n }\n this.finalizeCurrentMessage();\n return this.getMessages();\n }\n\n // Handle error events\n if (event.errorCode || event.errorMessage) {\n this.finalizeCurrentMessage();\n const errorMsg = this.getOrCreateAiMessage(event);\n const errorText =\n event.errorMessage ?? event.errorCode ?? \"Unknown error\";\n const updated: InProgressMessage = {\n ...errorMsg,\n content: [\n ...this.getContentArray(errorMsg),\n { type: \"text\", text: errorText },\n ],\n status: { type: \"incomplete\", reason: \"error\", error: errorText },\n };\n this.messagesMap.set(updated.id, updated);\n this.currentMessageId = null;\n return this.getMessages();\n }\n\n const parts = event.content?.parts;\n if (!parts?.length) {\n // Track metadata even for content-less events (e.g. turnComplete)\n this.trackMessageMetadata(event);\n return this.getMessages();\n }\n\n // User-authored events → create human message, not AI.\n // Without this, user events fall through to processPart →\n // getOrCreateAiMessage, producing type:\"ai\" messages that\n // convertAdkMessage maps to role:\"assistant\".\n if (event.author === \"user\") {\n this.finalizeCurrentMessage();\n const humanParts: AdkMessageContentPart[] = [];\n const toolMessages: AdkMessage[] = [];\n for (const [index, part] of parts.entries()) {\n if (part.text != null && !part.thought) {\n humanParts.push({ type: \"text\", text: part.text });\n } else if (part.inlineData) {\n humanParts.push(\n inlineDataToPart(part.inlineData.mimeType, part.inlineData.data),\n );\n } else if (part.fileData) {\n humanParts.push(\n fileDataToPart(part.fileData.fileUri, part.fileData.mimeType),\n );\n } else if (part.functionResponse?.id) {\n // ADK records tool confirmation and other client-supplied tool\n // results as user-authored function responses, and its request\n // confirmation processors search user events for them. Dropping\n // them here would replay a settled gate as pending. A response\n // carrying no id answers no call: core drops it as an orphan, and\n // keeping it would let it settle the batch it was grouped into.\n toolMessages.push({\n id: toolMessageId(event, index),\n type: \"tool\",\n tool_call_id: part.functionResponse.id,\n name: part.functionResponse.name,\n content: JSON.stringify(part.functionResponse.response),\n status: \"success\",\n });\n }\n }\n // The replies answer the preceding assistant turn, so they are emitted\n // before any user content in the same event. A human message between the\n // tool call and its reply splits them into separate converted messages,\n // orphaning the reply and leaving its gate unsettled.\n for (const toolMsg of toolMessages) {\n this.messagesMap.set(toolMsg.id, toolMsg);\n }\n if (humanParts.length > 0) {\n const id = event.id ?? generateId();\n const first = humanParts[0];\n const content: string | AdkMessageContentPart[] =\n humanParts.length === 1 && first?.type === \"text\"\n ? first.text\n : humanParts;\n this.messagesMap.set(id, { id, type: \"human\", content });\n }\n return this.getMessages();\n }\n\n // If author changed, finalize previous message\n if (this.currentMessageId && event.author && event.author !== \"user\") {\n const current = this.messagesMap.get(this.currentMessageId);\n if (current && current.type === \"ai\" && current.author !== event.author) {\n this.finalizeCurrentMessage();\n }\n }\n\n // Replace-semantics close out the streamed partial buffer, which only\n // the first final text/reasoning part of an event may do; later parts\n // of the same event are distinct content and append.\n this.finalTextReplacedThisEvent = false;\n this.finalReasoningReplacedThisEvent = false;\n for (const [index, part] of parts.entries()) {\n this.processPart(part, event, index);\n }\n\n // Track per-message metadata (grounding, citation, usage)\n this.trackMessageMetadata(event);\n\n // Check isFinalResponse (can be true even for partial events via skipSummarization/longRunningToolIds)\n if (isFinalResponse(event) && this.currentMessageId) {\n const msg = this.messagesMap.get(this.currentMessageId);\n // Skip manual \"complete\" when longRunningToolIds is the sole reason for\n // isFinalResponse — let auto-status apply requires-action for pending tool calls.\n const isHitlOnly =\n event.longRunningToolIds &&\n event.longRunningToolIds.length > 0 &&\n !event.actions?.skipSummarization;\n if (msg && msg.type === \"ai\" && !msg.status && !isHitlOnly) {\n const status = finishReasonToStatus(event.finishReason);\n const updated: InProgressMessage = {\n ...msg,\n content: [...this.getContentArray(msg)],\n status,\n };\n this.messagesMap.set(updated.id, updated);\n }\n }\n\n // Non-partial event finalizes the current message\n if (!event.partial || isFinalResponse(event)) {\n this.finalizeCurrentMessage();\n }\n\n return this.getMessages();\n }\n\n private processPart(\n part: AdkEventPart,\n event: AdkEvent,\n partIndex: number,\n ): void {\n // Detect special ADK function calls\n if (part.functionCall && !event.partial) {\n const name = part.functionCall.name;\n\n // Tool confirmation request\n if (name === ADK_REQUEST_CONFIRMATION) {\n const callArgs = part.functionCall.args;\n // ADK JS: args keys are \"originalFunctionCall\" and \"toolConfirmation\"\n // ADK Python: args keys are \"original_function_call\" and \"tool_confirmation\"\n const original =\n (callArgs.originalFunctionCall as Record<string, unknown>) ??\n (callArgs.original_function_call as Record<string, unknown>);\n const conf =\n (callArgs.toolConfirmation as Record<string, unknown>) ??\n (callArgs.tool_confirmation as Record<string, unknown>);\n this.toolConfirmations.push({\n toolCallId: part.functionCall.id ?? \"\",\n toolName: (original?.name as string) ?? \"\",\n args: (original?.args as Record<string, unknown>) ?? {},\n hint: (conf?.hint as string) ?? \"\",\n confirmed: false,\n payload: conf?.payload,\n });\n }\n\n // Auth credential request\n if (name === ADK_REQUEST_CREDENTIAL) {\n const credArgs = part.functionCall.args;\n // ADK JS: args keys are \"function_call_id\" and \"auth_config\"\n const originalToolCallId =\n (credArgs.function_call_id as string) ?? part.functionCall.id ?? \"\";\n const authConfig = credArgs.auth_config ?? credArgs;\n this.authRequests.push({\n toolCallId: originalToolCallId,\n authConfig,\n });\n }\n }\n\n // Text with thought=true → reasoning (accumulated)\n if (part.text != null && part.thought) {\n const msg = this.getOrCreateAiMessage(event);\n if (event.partial) {\n this.partialReasoningBuffer += part.text;\n this.replaceLastReasoningContent(msg, this.partialReasoningBuffer);\n } else if (!this.finalReasoningReplacedThisEvent) {\n this.finalReasoningReplacedThisEvent = true;\n this.partialReasoningBuffer = \"\";\n this.replaceLastReasoningContent(msg, part.text);\n } else {\n this.appendContent(msg, { type: \"reasoning\", text: part.text });\n }\n return;\n }\n\n // Regular text\n if (part.text != null) {\n const msg = this.getOrCreateAiMessage(event);\n if (event.partial) {\n this.partialTextBuffer += part.text;\n this.replaceLastTextContent(msg, this.partialTextBuffer);\n } else if (!this.finalTextReplacedThisEvent) {\n this.finalTextReplacedThisEvent = true;\n this.partialTextBuffer = \"\";\n this.replaceLastTextContent(msg, part.text);\n } else {\n this.appendContent(msg, { type: \"text\", text: part.text });\n }\n return;\n }\n\n // Function call — skip partial events (args may be incomplete)\n if (part.functionCall) {\n if (event.partial) return;\n const msg = this.getOrCreateAiMessage(event);\n const toolCall: AdkToolCall = {\n id: part.functionCall.id ?? generateId(),\n name: part.functionCall.name,\n args: part.functionCall.args as ReadonlyJSONObject,\n argsText: JSON.stringify(part.functionCall.args),\n };\n const existing = [...(msg.tool_calls ?? [])];\n const idx = existing.findIndex((tc) => tc.id === toolCall.id);\n if (idx >= 0) {\n existing[idx] = toolCall;\n } else {\n existing.push(toolCall);\n }\n const updated: InProgressMessage = {\n ...msg,\n content: [...this.getContentArray(msg)],\n tool_calls: existing,\n };\n this.messagesMap.set(updated.id, updated);\n return;\n }\n\n // Function response → tool message\n if (part.functionResponse) {\n this.finalizeCurrentMessage();\n const toolMsg: AdkMessage = {\n id: toolMessageId(event, partIndex),\n type: \"tool\",\n tool_call_id: part.functionResponse.id ?? \"\",\n name: part.functionResponse.name,\n content: JSON.stringify(part.functionResponse.response),\n status: \"success\",\n };\n this.messagesMap.set(toolMsg.id, toolMsg);\n return;\n }\n\n // Executable code\n if (part.executableCode) {\n const msg = this.getOrCreateAiMessage(event);\n this.appendContent(msg, {\n type: \"code\",\n code: part.executableCode.code,\n language: part.executableCode.language ?? \"python\",\n });\n return;\n }\n\n // Code execution result\n if (part.codeExecutionResult) {\n const msg = this.getOrCreateAiMessage(event);\n this.appendContent(msg, {\n type: \"code_result\",\n output: part.codeExecutionResult.output,\n outcome: part.codeExecutionResult.outcome ?? \"OUTCOME_OK\",\n });\n return;\n }\n\n if (part.inlineData) {\n const msg = this.getOrCreateAiMessage(event);\n this.appendContent(\n msg,\n inlineDataToPart(part.inlineData.mimeType, part.inlineData.data),\n );\n return;\n }\n\n if (part.fileData) {\n const msg = this.getOrCreateAiMessage(event);\n this.appendContent(\n msg,\n fileDataToPart(part.fileData.fileUri, part.fileData.mimeType),\n );\n }\n }\n\n private trackMessageMetadata(event: AdkEvent): void {\n if (\n !this.currentMessageId ||\n (!event.groundingMetadata &&\n !event.citationMetadata &&\n !event.usageMetadata)\n )\n return;\n\n const existing = this.messageMetadataMap.get(this.currentMessageId) ?? {};\n const updated: AdkMessageMetadata = { ...existing };\n if (event.groundingMetadata)\n updated.groundingMetadata = event.groundingMetadata;\n if (event.citationMetadata)\n updated.citationMetadata = event.citationMetadata;\n if (event.usageMetadata) updated.usageMetadata = event.usageMetadata;\n this.messageMetadataMap.set(this.currentMessageId, updated);\n }\n\n private getContentArray(msg: AdkMessage): AdkMessageContentPart[] {\n return Array.isArray(msg.content)\n ? (msg.content as AdkMessageContentPart[])\n : [];\n }\n\n private getOrCreateAiMessage(event: AdkEvent): InProgressMessage {\n if (this.currentMessageId) {\n const existing = this.messagesMap.get(this.currentMessageId);\n if (existing && existing.type === \"ai\") {\n return existing;\n }\n }\n\n const ordinal = this.aiMessageOrdinals.get(event.id ?? \"\") ?? 0;\n this.aiMessageOrdinals.set(event.id ?? \"\", ordinal + 1);\n const id = aiMessageId(event, ordinal);\n const msg: InProgressMessage = {\n id,\n type: \"ai\",\n content: [] as AdkMessageContentPart[],\n ...(event.author != null && { author: event.author }),\n ...(event.branch != null && { branch: event.branch }),\n };\n this.messagesMap.set(id, msg);\n this.currentMessageId = id;\n this.partialTextBuffer = \"\";\n this.partialReasoningBuffer = \"\";\n return msg;\n }\n\n private appendContent(\n msg: InProgressMessage,\n part: AdkMessageContentPart,\n ): void {\n const content = [...this.getContentArray(msg), part];\n const updated: InProgressMessage = { ...msg, content };\n this.messagesMap.set(updated.id, updated);\n }\n\n private replaceLastTextContent(msg: InProgressMessage, text: string): void {\n const content = [...this.getContentArray(msg)];\n const lastTextIdx = content.findLastIndex((p) => p.type === \"text\");\n if (lastTextIdx >= 0) {\n content[lastTextIdx] = { type: \"text\", text };\n } else {\n content.push({ type: \"text\", text });\n }\n const updated: InProgressMessage = { ...msg, content };\n this.messagesMap.set(updated.id, updated);\n }\n\n private replaceLastReasoningContent(\n msg: InProgressMessage,\n text: string,\n ): void {\n const content = [...this.getContentArray(msg)];\n const lastIdx = content.findLastIndex((p) => p.type === \"reasoning\");\n if (lastIdx >= 0) {\n content[lastIdx] = { type: \"reasoning\", text };\n } else {\n content.push({ type: \"reasoning\", text });\n }\n const updated: InProgressMessage = { ...msg, content };\n this.messagesMap.set(updated.id, updated);\n }\n\n private finalizeCurrentMessage(): void {\n this.partialTextBuffer = \"\";\n this.partialReasoningBuffer = \"\";\n this.currentMessageId = null;\n }\n\n getMessages(): AdkMessage[] {\n return [...this.messagesMap.values()];\n }\n\n getStateDelta(): Record<string, unknown> {\n return { ...this.accumulatedStateDelta };\n }\n\n getArtifactDelta(): Record<string, number> {\n return { ...this.accumulatedArtifactDelta };\n }\n\n getAgentInfo(): { name?: string | undefined; branch?: string | undefined } {\n return { ...this.lastAgentInfo };\n }\n\n getLastTransferToAgent(): string | undefined {\n return this.lastTransferToAgent;\n }\n\n getLongRunningToolIds(): string[] {\n return [...this.pendingLongRunningToolIds];\n }\n\n getToolConfirmations(): AdkToolConfirmation[] {\n return [...this.toolConfirmations];\n }\n\n getAuthRequests(): AdkAuthRequest[] {\n return [...this.authRequests];\n }\n\n isEscalated(): boolean {\n return this.escalated;\n }\n\n getMessageMetadata(): Map<string, AdkMessageMetadata> {\n return new Map(this.messageMetadataMap);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AdkEventAccumulator.js","names":[],"sources":["../src/AdkEventAccumulator.ts"],"sourcesContent":["import { generateId } from \"@assistant-ui/core\";\nimport type { MessageStatus } from \"@assistant-ui/core\";\nimport type {\n AdkEvent,\n AdkEventPart,\n AdkMessage,\n AdkMessageContentPart,\n AdkToolCall,\n AdkToolConfirmation,\n AdkAuthRequest,\n AdkMessageMetadata,\n} from \"./types\";\nimport type { ReadonlyJSONObject } from \"assistant-stream/utils\";\n\ntype InProgressMessage = AdkMessage & { type: \"ai\" };\n\n/**\n * A session load replays the stored events through a fresh accumulator, so a\n * message needs an id derived from the event that carries it rather than one\n * minted per replay. An event with no id of its own has never been through the\n * session and has nothing stable to derive from, so it keeps a generated one.\n *\n * A human message keeps the bare event id it has always had. The other kinds\n * take a suffixed namespace, since one event can carry several of them: a tool\n * message by the index of its part, an assistant message by how many this\n * event has already opened.\n */\nconst toolMessageId = (event: AdkEvent, partIndex: number): string =>\n event.id ? `${event.id}:${partIndex}` : generateId();\n\nconst aiMessageId = (event: AdkEvent, ordinal: number): string =>\n event.id ? `${event.id}:ai${ordinal === 0 ? \"\" : ordinal}` : generateId();\n\nconst ADK_REQUEST_CONFIRMATION = \"adk_request_confirmation\";\nconst ADK_REQUEST_CREDENTIAL = \"adk_request_credential\";\n\n/**\n * Checks if an event is a final response using the same logic as ADK's\n * `isFinalResponse()`.\n */\nexport const isFinalResponse = (event: AdkEvent): boolean => {\n if (\n event.actions?.skipSummarization ||\n (event.longRunningToolIds && event.longRunningToolIds.length > 0)\n ) {\n return true;\n }\n\n const parts = event.content?.parts;\n return (\n !event.partial &&\n (parts?.length ?? 0) > 0 &&\n !parts!.some((p) => p.functionCall) &&\n !parts!.some((p) => p.functionResponse) &&\n !parts![parts!.length - 1]?.codeExecutionResult\n );\n};\n\nconst CONTENT_FILTER_REASONS = new Set([\n \"SAFETY\",\n \"RECITATION\",\n \"BLOCKLIST\",\n \"PROHIBITED_CONTENT\",\n \"SPII\",\n \"LANGUAGE\",\n \"IMAGE_SAFETY\",\n \"IMAGE_RECITATION\",\n \"IMAGE_OTHER\",\n \"IMAGE_PROHIBITED_CONTENT\",\n]);\n\nconst ERROR_REASONS = new Set([\n \"MALFORMED_FUNCTION_CALL\",\n \"UNEXPECTED_TOOL_CALL\",\n]);\n\nconst finishReasonToStatus = (\n finishReason: string | undefined,\n): MessageStatus => {\n if (finishReason === \"MAX_TOKENS\") {\n return { type: \"incomplete\", reason: \"length\" };\n }\n if (finishReason && CONTENT_FILTER_REASONS.has(finishReason)) {\n return {\n type: \"incomplete\",\n reason: \"content-filter\",\n error: `Content filtered: ${finishReason}`,\n };\n }\n if (finishReason && ERROR_REASONS.has(finishReason)) {\n return {\n type: \"incomplete\",\n reason: \"error\",\n error: `LLM error: ${finishReason}`,\n };\n }\n return { type: \"complete\", reason: \"stop\" };\n};\n\nconst inlineDataToPart = (\n mimeType: string,\n data: string,\n): AdkMessageContentPart =>\n mimeType.startsWith(\"image/\")\n ? { type: \"image\", mimeType, data }\n : { type: \"file\", mimeType, data };\n\nconst fileDataToPart = (\n fileUri: string,\n mimeType: string | undefined,\n): AdkMessageContentPart =>\n mimeType == null || mimeType.startsWith(\"image/\")\n ? { type: \"image_url\", url: fileUri }\n : { type: \"file_url\", url: fileUri, mimeType };\n\n// ── Snake_case normalization ──\n\nconst normalizeEventPart = (part: AdkEventPart): AdkEventPart => {\n const p = part as Record<string, unknown>;\n const result: Record<string, unknown> = { ...p };\n if (\"function_call\" in p && !(\"functionCall\" in p))\n result.functionCall = p.function_call;\n if (\"function_response\" in p && !(\"functionResponse\" in p))\n result.functionResponse = p.function_response;\n if (\"inline_data\" in p && !(\"inlineData\" in p))\n result.inlineData = p.inline_data;\n if (\"file_data\" in p && !(\"fileData\" in p)) result.fileData = p.file_data;\n if (\"executable_code\" in p && !(\"executableCode\" in p))\n result.executableCode = p.executable_code;\n if (\"code_execution_result\" in p && !(\"codeExecutionResult\" in p))\n result.codeExecutionResult = p.code_execution_result;\n return result as AdkEventPart;\n};\n\nconst normalizeEvent = (event: AdkEvent): AdkEvent => {\n const e = event as Record<string, unknown>;\n const result: Record<string, unknown> = { ...e };\n if (\"error_code\" in e && !(\"errorCode\" in e)) result.errorCode = e.error_code;\n if (\"error_message\" in e && !(\"errorMessage\" in e))\n result.errorMessage = e.error_message;\n if (\"long_running_tool_ids\" in e && !(\"longRunningToolIds\" in e))\n result.longRunningToolIds = e.long_running_tool_ids;\n if (\"turn_complete\" in e && !(\"turnComplete\" in e))\n result.turnComplete = e.turn_complete;\n if (\"finish_reason\" in e && !(\"finishReason\" in e))\n result.finishReason = e.finish_reason;\n if (\"invocation_id\" in e && !(\"invocationId\" in e))\n result.invocationId = e.invocation_id;\n if (\"custom_metadata\" in e && !(\"customMetadata\" in e))\n result.customMetadata = e.custom_metadata;\n if (\"grounding_metadata\" in e && !(\"groundingMetadata\" in e))\n result.groundingMetadata = e.grounding_metadata;\n if (\"citation_metadata\" in e && !(\"citationMetadata\" in e))\n result.citationMetadata = e.citation_metadata;\n if (\"usage_metadata\" in e && !(\"usageMetadata\" in e))\n result.usageMetadata = e.usage_metadata;\n\n if (result.actions) {\n const a = result.actions as Record<string, unknown>;\n const na: Record<string, unknown> = { ...a };\n if (\"state_delta\" in a && !(\"stateDelta\" in a))\n na.stateDelta = a.state_delta;\n if (\"artifact_delta\" in a && !(\"artifactDelta\" in a))\n na.artifactDelta = a.artifact_delta;\n if (\"transfer_to_agent\" in a && !(\"transferToAgent\" in a))\n na.transferToAgent = a.transfer_to_agent;\n if (\"skip_summarization\" in a && !(\"skipSummarization\" in a))\n na.skipSummarization = a.skip_summarization;\n if (\"requested_auth_configs\" in a && !(\"requestedAuthConfigs\" in a))\n na.requestedAuthConfigs = a.requested_auth_configs;\n if (\n \"requested_tool_confirmations\" in a &&\n !(\"requestedToolConfirmations\" in a)\n )\n na.requestedToolConfirmations = a.requested_tool_confirmations;\n result.actions = na;\n }\n\n if (result.content && (result.content as Record<string, unknown>).parts) {\n const content = result.content as Record<string, unknown>;\n const parts = content.parts as AdkEventPart[];\n result.content = { ...content, parts: parts.map(normalizeEventPart) };\n }\n\n return result as AdkEvent;\n};\n\n// ── Accumulator ──\n\nexport class AdkEventAccumulator {\n private messagesMap = new Map<string, AdkMessage>();\n private currentMessageId: string | null = null;\n private partialTextBuffer = \"\";\n private finalTextReplacedThisEvent = false;\n private finalReasoningReplacedThisEvent = false;\n private partialReasoningBuffer = \"\";\n private accumulatedStateDelta: Record<string, unknown> = Object.create(null);\n private accumulatedArtifactDelta: Record<string, number> =\n Object.create(null);\n private lastAgentInfo: {\n name?: string | undefined;\n branch?: string | undefined;\n } = {};\n private lastTransferToAgent: string | undefined;\n private pendingLongRunningToolIds = new Set<string>();\n private toolConfirmations: AdkToolConfirmation[] = [];\n private authRequests: AdkAuthRequest[] = [];\n private escalated = false;\n private messageMetadataMap = new Map<string, AdkMessageMetadata>();\n // How many assistant messages each event has opened, so a replay of that\n // event opens them with the same ids.\n private aiMessageOrdinals = new Map<string, number>();\n constructor(initialMessages?: AdkMessage[]) {\n if (initialMessages) {\n for (const msg of initialMessages) {\n this.messagesMap.set(msg.id, msg);\n }\n }\n }\n\n processEvent(rawEvent: AdkEvent): AdkMessage[] {\n const event = normalizeEvent(rawEvent);\n\n // Accumulate state delta\n if (event.actions?.stateDelta) {\n Object.assign(this.accumulatedStateDelta, event.actions.stateDelta);\n }\n\n // Accumulate artifact delta\n if (event.actions?.artifactDelta) {\n Object.assign(this.accumulatedArtifactDelta, event.actions.artifactDelta);\n }\n\n // Track escalation\n if (event.actions?.escalate) {\n this.escalated = true;\n }\n\n // Track agent transfer\n if (event.actions?.transferToAgent) {\n this.lastTransferToAgent = event.actions.transferToAgent;\n }\n\n // Track long-running tool IDs. Accumulate across events so that multiple\n // HITL interrupts emitted in the same turn are all tracked — a\n // single-event replacement would drop earlier ids.\n if (event.longRunningToolIds?.length) {\n for (const id of event.longRunningToolIds) {\n this.pendingLongRunningToolIds.add(id);\n }\n }\n\n // Track tool confirmations from actions\n if (event.actions?.requestedToolConfirmations) {\n for (const [tcId, conf] of Object.entries(\n event.actions.requestedToolConfirmations,\n )) {\n const c = conf as Record<string, unknown>;\n this.toolConfirmations.push({\n toolCallId: tcId,\n toolName: \"\",\n args: {},\n hint: (c.hint as string) ?? \"\",\n confirmed: false,\n payload: c.payload,\n });\n }\n }\n\n // Track auth requests from actions\n if (event.actions?.requestedAuthConfigs) {\n for (const [tcId, authConf] of Object.entries(\n event.actions.requestedAuthConfigs,\n )) {\n this.authRequests.push({ toolCallId: tcId, authConfig: authConf });\n }\n }\n\n // Track agent info\n if (event.author && event.author !== \"user\") {\n this.lastAgentInfo = {\n name: event.author ?? undefined,\n branch: event.branch ?? undefined,\n };\n }\n\n // Handle interrupted events\n if (event.interrupted) {\n if (this.currentMessageId) {\n const msg = this.messagesMap.get(this.currentMessageId);\n if (msg && msg.type === \"ai\" && !msg.status) {\n const updated: InProgressMessage = {\n ...msg,\n content: [...this.getContentArray(msg)],\n status: { type: \"incomplete\", reason: \"cancelled\" },\n };\n this.messagesMap.set(updated.id, updated);\n }\n }\n this.finalizeCurrentMessage();\n return this.getMessages();\n }\n\n // Handle error events\n if (event.errorCode || event.errorMessage) {\n this.finalizeCurrentMessage();\n const errorMsg = this.getOrCreateAiMessage(event);\n const errorText =\n event.errorMessage ?? event.errorCode ?? \"Unknown error\";\n const updated: InProgressMessage = {\n ...errorMsg,\n content: [\n ...this.getContentArray(errorMsg),\n { type: \"text\", text: errorText },\n ],\n status: { type: \"incomplete\", reason: \"error\", error: errorText },\n };\n this.messagesMap.set(updated.id, updated);\n this.currentMessageId = null;\n return this.getMessages();\n }\n\n const parts = event.content?.parts;\n if (!parts?.length) {\n // Track metadata even for content-less events (e.g. turnComplete)\n this.trackMessageMetadata(event);\n return this.getMessages();\n }\n\n // User-authored events → create human message, not AI.\n // Without this, user events fall through to processPart →\n // getOrCreateAiMessage, producing type:\"ai\" messages that\n // convertAdkMessage maps to role:\"assistant\".\n if (event.author === \"user\") {\n this.finalizeCurrentMessage();\n const humanParts: AdkMessageContentPart[] = [];\n const toolMessages: AdkMessage[] = [];\n for (const [index, part] of parts.entries()) {\n if (part.text != null && !part.thought) {\n humanParts.push({ type: \"text\", text: part.text });\n } else if (part.inlineData) {\n humanParts.push(\n inlineDataToPart(part.inlineData.mimeType, part.inlineData.data),\n );\n } else if (part.fileData) {\n humanParts.push(\n fileDataToPart(part.fileData.fileUri, part.fileData.mimeType),\n );\n } else if (part.functionResponse?.id) {\n // ADK records tool confirmation and other client-supplied tool\n // results as user-authored function responses, and its request\n // confirmation processors search user events for them. Dropping\n // them here would replay a settled gate as pending. A response\n // carrying no id answers no call: core drops it as an orphan, and\n // keeping it would let it settle the batch it was grouped into.\n toolMessages.push({\n id: toolMessageId(event, index),\n type: \"tool\",\n tool_call_id: part.functionResponse.id,\n name: part.functionResponse.name,\n content: JSON.stringify(part.functionResponse.response),\n status: \"success\",\n });\n }\n }\n // The replies answer the preceding assistant turn, so they are emitted\n // before any user content in the same event. A human message between the\n // tool call and its reply splits them into separate converted messages,\n // orphaning the reply and leaving its gate unsettled.\n for (const toolMsg of toolMessages) {\n this.messagesMap.set(toolMsg.id, toolMsg);\n }\n if (humanParts.length > 0) {\n const id = event.id ?? generateId();\n const first = humanParts[0];\n const content: string | AdkMessageContentPart[] =\n humanParts.length === 1 && first?.type === \"text\"\n ? first.text\n : humanParts;\n this.messagesMap.set(id, { id, type: \"human\", content });\n }\n return this.getMessages();\n }\n\n // If author changed, finalize previous message\n if (this.currentMessageId && event.author && event.author !== \"user\") {\n const current = this.messagesMap.get(this.currentMessageId);\n if (current && current.type === \"ai\" && current.author !== event.author) {\n this.finalizeCurrentMessage();\n }\n }\n\n // Replace-semantics close out the streamed partial buffer, which only\n // the first final text/reasoning part of an event may do; later parts\n // of the same event are distinct content and append.\n this.finalTextReplacedThisEvent = false;\n this.finalReasoningReplacedThisEvent = false;\n for (const [index, part] of parts.entries()) {\n this.processPart(part, event, index);\n }\n\n // Track per-message metadata (grounding, citation, usage)\n this.trackMessageMetadata(event);\n\n // Check isFinalResponse (can be true even for partial events via skipSummarization/longRunningToolIds)\n if (isFinalResponse(event) && this.currentMessageId) {\n const msg = this.messagesMap.get(this.currentMessageId);\n // Skip manual \"complete\" when longRunningToolIds is the sole reason for\n // isFinalResponse — let auto-status apply requires-action for pending tool calls.\n const isHitlOnly =\n event.longRunningToolIds &&\n event.longRunningToolIds.length > 0 &&\n !event.actions?.skipSummarization;\n if (msg && msg.type === \"ai\" && !msg.status && !isHitlOnly) {\n const status = finishReasonToStatus(event.finishReason);\n const updated: InProgressMessage = {\n ...msg,\n content: [...this.getContentArray(msg)],\n status,\n };\n this.messagesMap.set(updated.id, updated);\n }\n }\n\n // Non-partial event finalizes the current message\n if (!event.partial || isFinalResponse(event)) {\n this.finalizeCurrentMessage();\n }\n\n return this.getMessages();\n }\n\n private processPart(\n part: AdkEventPart,\n event: AdkEvent,\n partIndex: number,\n ): void {\n // Detect special ADK function calls\n if (part.functionCall && !event.partial) {\n const name = part.functionCall.name;\n\n // Tool confirmation request\n if (name === ADK_REQUEST_CONFIRMATION) {\n const callArgs = part.functionCall.args;\n // ADK JS: args keys are \"originalFunctionCall\" and \"toolConfirmation\"\n // ADK Python: args keys are \"original_function_call\" and \"tool_confirmation\"\n const original =\n (callArgs.originalFunctionCall as Record<string, unknown>) ??\n (callArgs.original_function_call as Record<string, unknown>);\n const conf =\n (callArgs.toolConfirmation as Record<string, unknown>) ??\n (callArgs.tool_confirmation as Record<string, unknown>);\n this.toolConfirmations.push({\n toolCallId: part.functionCall.id ?? \"\",\n toolName: (original?.name as string) ?? \"\",\n args: (original?.args as Record<string, unknown>) ?? {},\n hint: (conf?.hint as string) ?? \"\",\n confirmed: false,\n payload: conf?.payload,\n });\n }\n\n // Auth credential request\n if (name === ADK_REQUEST_CREDENTIAL) {\n const credArgs = part.functionCall.args;\n // ADK JS: args keys are \"function_call_id\" and \"auth_config\"\n const originalToolCallId =\n (credArgs.function_call_id as string) ?? part.functionCall.id ?? \"\";\n const authConfig = credArgs.auth_config ?? credArgs;\n this.authRequests.push({\n toolCallId: originalToolCallId,\n authConfig,\n });\n }\n }\n\n // Text with thought=true → reasoning (accumulated)\n if (part.text != null && part.thought) {\n const msg = this.getOrCreateAiMessage(event);\n if (event.partial) {\n this.partialReasoningBuffer += part.text;\n this.replaceLastReasoningContent(msg, this.partialReasoningBuffer);\n } else if (!this.finalReasoningReplacedThisEvent) {\n this.finalReasoningReplacedThisEvent = true;\n this.partialReasoningBuffer = \"\";\n this.replaceLastReasoningContent(msg, part.text);\n } else {\n this.appendContent(msg, { type: \"reasoning\", text: part.text });\n }\n return;\n }\n\n // Regular text\n if (part.text != null) {\n const msg = this.getOrCreateAiMessage(event);\n if (event.partial) {\n this.partialTextBuffer += part.text;\n this.replaceLastTextContent(msg, this.partialTextBuffer);\n } else if (!this.finalTextReplacedThisEvent) {\n this.finalTextReplacedThisEvent = true;\n this.partialTextBuffer = \"\";\n this.replaceLastTextContent(msg, part.text);\n } else {\n this.appendContent(msg, { type: \"text\", text: part.text });\n }\n return;\n }\n\n // Function call — skip partial events (args may be incomplete)\n if (part.functionCall) {\n if (event.partial) return;\n const msg = this.getOrCreateAiMessage(event);\n const toolCall: AdkToolCall = {\n id: part.functionCall.id ?? generateId(),\n name: part.functionCall.name,\n args: part.functionCall.args as ReadonlyJSONObject,\n argsText: JSON.stringify(part.functionCall.args),\n };\n const existing = [...(msg.tool_calls ?? [])];\n const idx = existing.findIndex((tc) => tc.id === toolCall.id);\n if (idx >= 0) {\n existing[idx] = toolCall;\n } else {\n existing.push(toolCall);\n }\n const updated: InProgressMessage = {\n ...msg,\n content: [...this.getContentArray(msg)],\n tool_calls: existing,\n };\n this.messagesMap.set(updated.id, updated);\n return;\n }\n\n // Function response → tool message\n if (part.functionResponse) {\n this.finalizeCurrentMessage();\n const toolMsg: AdkMessage = {\n id: toolMessageId(event, partIndex),\n type: \"tool\",\n tool_call_id: part.functionResponse.id ?? \"\",\n name: part.functionResponse.name,\n content: JSON.stringify(part.functionResponse.response),\n status: \"success\",\n };\n this.messagesMap.set(toolMsg.id, toolMsg);\n return;\n }\n\n // Executable code\n if (part.executableCode) {\n const msg = this.getOrCreateAiMessage(event);\n this.appendContent(msg, {\n type: \"code\",\n code: part.executableCode.code,\n language: part.executableCode.language ?? \"python\",\n });\n return;\n }\n\n // Code execution result\n if (part.codeExecutionResult) {\n const msg = this.getOrCreateAiMessage(event);\n this.appendContent(msg, {\n type: \"code_result\",\n output: part.codeExecutionResult.output,\n outcome: part.codeExecutionResult.outcome ?? \"OUTCOME_OK\",\n });\n return;\n }\n\n if (part.inlineData) {\n const msg = this.getOrCreateAiMessage(event);\n this.appendContent(\n msg,\n inlineDataToPart(part.inlineData.mimeType, part.inlineData.data),\n );\n return;\n }\n\n if (part.fileData) {\n const msg = this.getOrCreateAiMessage(event);\n this.appendContent(\n msg,\n fileDataToPart(part.fileData.fileUri, part.fileData.mimeType),\n );\n }\n }\n\n private trackMessageMetadata(event: AdkEvent): void {\n if (\n !this.currentMessageId ||\n (!event.groundingMetadata &&\n !event.citationMetadata &&\n !event.usageMetadata)\n )\n return;\n\n const existing = this.messageMetadataMap.get(this.currentMessageId) ?? {};\n const updated: AdkMessageMetadata = { ...existing };\n if (event.groundingMetadata)\n updated.groundingMetadata = event.groundingMetadata;\n if (event.citationMetadata)\n updated.citationMetadata = event.citationMetadata;\n if (event.usageMetadata) updated.usageMetadata = event.usageMetadata;\n this.messageMetadataMap.set(this.currentMessageId, updated);\n }\n\n private getContentArray(msg: AdkMessage): AdkMessageContentPart[] {\n return Array.isArray(msg.content)\n ? (msg.content as AdkMessageContentPart[])\n : [];\n }\n\n private getOrCreateAiMessage(event: AdkEvent): InProgressMessage {\n if (this.currentMessageId) {\n const existing = this.messagesMap.get(this.currentMessageId);\n if (existing && existing.type === \"ai\") {\n return existing;\n }\n }\n\n const ordinal = this.aiMessageOrdinals.get(event.id ?? \"\") ?? 0;\n this.aiMessageOrdinals.set(event.id ?? \"\", ordinal + 1);\n const id = aiMessageId(event, ordinal);\n const msg: InProgressMessage = {\n id,\n type: \"ai\",\n content: [] as AdkMessageContentPart[],\n ...(event.author != null && { author: event.author }),\n ...(event.branch != null && { branch: event.branch }),\n };\n this.messagesMap.set(id, msg);\n this.currentMessageId = id;\n this.partialTextBuffer = \"\";\n this.partialReasoningBuffer = \"\";\n return msg;\n }\n\n private appendContent(\n msg: InProgressMessage,\n part: AdkMessageContentPart,\n ): void {\n const content = [...this.getContentArray(msg), part];\n const updated: InProgressMessage = { ...msg, content };\n this.messagesMap.set(updated.id, updated);\n }\n\n private replaceLastTextContent(msg: InProgressMessage, text: string): void {\n const content = [...this.getContentArray(msg)];\n const lastTextIdx = content.findLastIndex((p) => p.type === \"text\");\n if (lastTextIdx >= 0) {\n content[lastTextIdx] = { type: \"text\", text };\n } else {\n content.push({ type: \"text\", text });\n }\n const updated: InProgressMessage = { ...msg, content };\n this.messagesMap.set(updated.id, updated);\n }\n\n private replaceLastReasoningContent(\n msg: InProgressMessage,\n text: string,\n ): void {\n const content = [...this.getContentArray(msg)];\n const lastIdx = content.findLastIndex((p) => p.type === \"reasoning\");\n if (lastIdx >= 0) {\n content[lastIdx] = { type: \"reasoning\", text };\n } else {\n content.push({ type: \"reasoning\", text });\n }\n const updated: InProgressMessage = { ...msg, content };\n this.messagesMap.set(updated.id, updated);\n }\n\n private finalizeCurrentMessage(): void {\n this.partialTextBuffer = \"\";\n this.partialReasoningBuffer = \"\";\n this.currentMessageId = null;\n }\n\n getMessages(): AdkMessage[] {\n return [...this.messagesMap.values()];\n }\n\n getStateDelta(): Record<string, unknown> {\n return { ...this.accumulatedStateDelta };\n }\n\n getArtifactDelta(): Record<string, number> {\n return { ...this.accumulatedArtifactDelta };\n }\n\n getAgentInfo(): { name?: string | undefined; branch?: string | undefined } {\n return { ...this.lastAgentInfo };\n }\n\n getLastTransferToAgent(): string | undefined {\n return this.lastTransferToAgent;\n }\n\n getLongRunningToolIds(): string[] {\n return [...this.pendingLongRunningToolIds];\n }\n\n getToolConfirmations(): AdkToolConfirmation[] {\n return [...this.toolConfirmations];\n }\n\n getAuthRequests(): AdkAuthRequest[] {\n return [...this.authRequests];\n }\n\n isEscalated(): boolean {\n return this.escalated;\n }\n\n getMessageMetadata(): Map<string, AdkMessageMetadata> {\n return new Map(this.messageMetadataMap);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { generateId, getExternalStoreMessages } from "@assistant-ui/core";
|
|
2
1
|
import { createToolCallCancellationStub, parseDataUrl, resolveFilePartSource, scanPendingToolCalls } from "@assistant-ui/core/internal";
|
|
2
|
+
import { generateId, getExternalStoreMessages } from "@assistant-ui/core";
|
|
3
3
|
//#region src/convertToAdkMessages.ts
|
|
4
4
|
/** Exported for unit tests. */
|
|
5
5
|
const getMessageContent = (msg) => {
|
package/dist/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","names":[],"sources":["../src/hooks.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","names":[],"sources":["../src/hooks.ts"],"mappings":";;;;cAwBa;EAAA;EAAA;;;cAIA,0BAAkB;;cAIlB,mBAEH,UAAU,cAAc,QAAQ,yBAAoB;;cAKjD;;cAIA,+BAAuB;;cAIvB,0BAAkB;;cAIlB,uBAAe;;cAIf;;cAGA,6BAAqB,YAAA;;cAMrB,0BAGT,oBACA,oBACA,UAAU,sBAAiB;;cAQlB,yBAEH,oBAAoB,YAAY,sBAAiB;;cAiB9C,0BAEH,oBAAoB,QAAQ,sBAAiB;;cAyC1C,sBAAc;;cAGd,uBAAe;;cAGf,uBAAe"}
|
package/dist/hooks.js
CHANGED
|
@@ -2,6 +2,7 @@ import { adkExtras } from "./adkExtras.js";
|
|
|
2
2
|
import { toAdkConfirmationReply } from "./adkToolApproval.js";
|
|
3
3
|
import { generateId } from "@assistant-ui/core";
|
|
4
4
|
import { useAui } from "@assistant-ui/store";
|
|
5
|
+
import { useShallowSelector } from "@assistant-ui/store/internal";
|
|
5
6
|
//#region src/hooks.ts
|
|
6
7
|
const EMPTY_STATE_DELTA = {};
|
|
7
8
|
const EMPTY_ARTIFACT_DELTA = {};
|
|
@@ -62,17 +63,14 @@ const useAdkSubmitInput = () => {
|
|
|
62
63
|
const APP_PREFIX = "app:";
|
|
63
64
|
const USER_PREFIX = "user:";
|
|
64
65
|
const TEMP_PREFIX = "temp:";
|
|
65
|
-
const filterByPrefix = (state, prefix) =>
|
|
66
|
-
|
|
67
|
-
for (const key of Object.keys(state)) if (key.startsWith(prefix)) result[key.slice(prefix.length)] = state[key];
|
|
68
|
-
return result;
|
|
69
|
-
};
|
|
66
|
+
const filterByPrefix = (state, prefix) => Object.fromEntries(Object.entries(state).filter(([key]) => key.startsWith(prefix)).map(([key, value]) => [key.slice(prefix.length), value]));
|
|
67
|
+
const useAdkStateByPrefix = (prefix) => adkExtras.use(useShallowSelector((e) => filterByPrefix(e.stateDelta, prefix)), EMPTY_STATE_DELTA);
|
|
70
68
|
/** Returns app-level state (keys prefixed with `app:`, prefix stripped). */
|
|
71
|
-
const useAdkAppState = () =>
|
|
69
|
+
const useAdkAppState = () => useAdkStateByPrefix(APP_PREFIX);
|
|
72
70
|
/** Returns user-level state (keys prefixed with `user:`, prefix stripped). */
|
|
73
|
-
const useAdkUserState = () =>
|
|
71
|
+
const useAdkUserState = () => useAdkStateByPrefix(USER_PREFIX);
|
|
74
72
|
/** Returns temp state (keys prefixed with `temp:`, prefix stripped). Not persisted. */
|
|
75
|
-
const useAdkTempState = () =>
|
|
73
|
+
const useAdkTempState = () => useAdkStateByPrefix(TEMP_PREFIX);
|
|
76
74
|
//#endregion
|
|
77
75
|
export { useAdkAgentInfo, useAdkAppState, useAdkArtifacts, useAdkAuthRequests, useAdkConfirmTool, useAdkEscalation, useAdkLongRunningToolIds, useAdkMessageMetadata, useAdkSend, useAdkSessionState, useAdkSubmitAuth, useAdkSubmitInput, useAdkTempState, useAdkToolConfirmations, useAdkUserState };
|
|
78
76
|
|
package/dist/hooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","names":[],"sources":["../src/hooks.ts"],"sourcesContent":["import { generateId } from \"@assistant-ui/core\";\nimport { useAui } from \"@assistant-ui/store\";\nimport type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport { adkExtras } from \"./adkExtras\";\nimport { toAdkConfirmationReply } from \"./adkToolApproval\";\nimport type {\n AdkMessage,\n AdkSendMessageConfig,\n AdkToolConfirmation,\n AdkAuthCredential,\n AdkAuthRequest,\n AdkMessageMetadata,\n} from \"./types\";\n\nconst EMPTY_STATE_DELTA: Record<string, unknown> = {};\nconst EMPTY_ARTIFACT_DELTA: Record<string, number> = {};\nconst EMPTY_LONG_RUNNING_TOOL_IDS: string[] = [];\nconst EMPTY_TOOL_CONFIRMATIONS: AdkToolConfirmation[] = [];\nconst EMPTY_AUTH_REQUESTS: AdkAuthRequest[] = [];\nconst EMPTY_MESSAGE_METADATA = new Map<string, AdkMessageMetadata>();\n\n/** Returns the name and branch of the currently active ADK agent. */\nexport const useAdkAgentInfo = () =>\n adkExtras.use((e) => e.agentInfo, undefined);\n\n/** Returns the accumulated session state delta from ADK events. */\nexport const useAdkSessionState = () =>\n adkExtras.use((e) => e.stateDelta, EMPTY_STATE_DELTA);\n\n/** Returns a function to send raw ADK messages. */\nexport const useAdkSend = () => {\n const aui = useAui();\n return (messages: AdkMessage[], config: AdkSendMessageConfig) =>\n adkExtras.get(aui).send(messages, config);\n};\n\n/** Returns the IDs of long-running tools awaiting external input. */\nexport const useAdkLongRunningToolIds = () =>\n adkExtras.use((e) => e.longRunningToolIds, EMPTY_LONG_RUNNING_TOOL_IDS);\n\n/** Returns pending tool confirmation requests (from SecurityPlugin etc). */\nexport const useAdkToolConfirmations = () =>\n adkExtras.use((e) => e.toolConfirmations, EMPTY_TOOL_CONFIRMATIONS);\n\n/** Returns pending auth credential requests from tools. */\nexport const useAdkAuthRequests = () =>\n adkExtras.use((e) => e.authRequests, EMPTY_AUTH_REQUESTS);\n\n/** Returns the accumulated artifact delta (filename → version). */\nexport const useAdkArtifacts = () =>\n adkExtras.use((e) => e.artifactDelta, EMPTY_ARTIFACT_DELTA);\n\n/** Returns whether any agent has escalated (requested human handoff). */\nexport const useAdkEscalation = () => adkExtras.use((e) => e.escalated, false);\n\n/** Returns per-message metadata (grounding, citation, usage). Keyed by message ID. */\nexport const useAdkMessageMetadata = () =>\n adkExtras.use((e) => e.messageMetadata, EMPTY_MESSAGE_METADATA);\n\n// ── Convenience helpers for interactive flows ──\n\n/** Returns a function to confirm or deny a pending tool confirmation. */\nexport const useAdkConfirmTool = () => {\n const aui = useAui();\n return (\n toolCallId: string,\n confirmed: boolean,\n payload?: ReadonlyJSONValue,\n ) =>\n adkExtras\n .get(aui)\n .send([toAdkConfirmationReply(toolCallId, confirmed, payload)], {});\n};\n\n/** Returns a function to submit auth credentials for a pending auth request. */\nexport const useAdkSubmitAuth = () => {\n const aui = useAui();\n return (toolCallId: string, credential: AdkAuthCredential) =>\n adkExtras.get(aui).send(\n [\n {\n id: generateId(),\n type: \"tool\",\n tool_call_id: toolCallId,\n name: \"adk_request_credential\",\n content: JSON.stringify(credential),\n status: \"success\",\n },\n ],\n {},\n );\n};\n\n/** Returns a function to submit the user's answer for a pending `adk_request_input` HITL interrupt. */\nexport const useAdkSubmitInput = () => {\n const aui = useAui();\n return (toolCallId: string, result: ReadonlyJSONValue) =>\n adkExtras.get(aui).send(\n [\n {\n id: generateId(),\n type: \"tool\",\n tool_call_id: toolCallId,\n name: \"adk_request_input\",\n content: JSON.stringify({ result }),\n status: \"success\",\n },\n ],\n {},\n );\n};\n\n// ── State prefix helpers ──\n\nconst APP_PREFIX = \"app:\";\nconst USER_PREFIX = \"user:\";\nconst TEMP_PREFIX = \"temp:\";\n\nconst filterByPrefix = (\n state: Record<string, unknown>,\n prefix: string,\n): Record<string, unknown>
|
|
1
|
+
{"version":3,"file":"hooks.js","names":[],"sources":["../src/hooks.ts"],"sourcesContent":["import { generateId } from \"@assistant-ui/core\";\nimport { useAui } from \"@assistant-ui/store\";\nimport { useShallowSelector } from \"@assistant-ui/store/internal\";\nimport type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport { adkExtras } from \"./adkExtras\";\nimport { toAdkConfirmationReply } from \"./adkToolApproval\";\nimport type {\n AdkMessage,\n AdkSendMessageConfig,\n AdkToolConfirmation,\n AdkAuthCredential,\n AdkAuthRequest,\n AdkMessageMetadata,\n AdkRuntimeExtras,\n} from \"./types\";\n\nconst EMPTY_STATE_DELTA: Record<string, unknown> = {};\nconst EMPTY_ARTIFACT_DELTA: Record<string, number> = {};\nconst EMPTY_LONG_RUNNING_TOOL_IDS: string[] = [];\nconst EMPTY_TOOL_CONFIRMATIONS: AdkToolConfirmation[] = [];\nconst EMPTY_AUTH_REQUESTS: AdkAuthRequest[] = [];\nconst EMPTY_MESSAGE_METADATA = new Map<string, AdkMessageMetadata>();\n\n/** Returns the name and branch of the currently active ADK agent. */\nexport const useAdkAgentInfo = () =>\n adkExtras.use((e) => e.agentInfo, undefined);\n\n/** Returns the accumulated session state delta from ADK events. */\nexport const useAdkSessionState = () =>\n adkExtras.use((e) => e.stateDelta, EMPTY_STATE_DELTA);\n\n/** Returns a function to send raw ADK messages. */\nexport const useAdkSend = () => {\n const aui = useAui();\n return (messages: AdkMessage[], config: AdkSendMessageConfig) =>\n adkExtras.get(aui).send(messages, config);\n};\n\n/** Returns the IDs of long-running tools awaiting external input. */\nexport const useAdkLongRunningToolIds = () =>\n adkExtras.use((e) => e.longRunningToolIds, EMPTY_LONG_RUNNING_TOOL_IDS);\n\n/** Returns pending tool confirmation requests (from SecurityPlugin etc). */\nexport const useAdkToolConfirmations = () =>\n adkExtras.use((e) => e.toolConfirmations, EMPTY_TOOL_CONFIRMATIONS);\n\n/** Returns pending auth credential requests from tools. */\nexport const useAdkAuthRequests = () =>\n adkExtras.use((e) => e.authRequests, EMPTY_AUTH_REQUESTS);\n\n/** Returns the accumulated artifact delta (filename → version). */\nexport const useAdkArtifacts = () =>\n adkExtras.use((e) => e.artifactDelta, EMPTY_ARTIFACT_DELTA);\n\n/** Returns whether any agent has escalated (requested human handoff). */\nexport const useAdkEscalation = () => adkExtras.use((e) => e.escalated, false);\n\n/** Returns per-message metadata (grounding, citation, usage). Keyed by message ID. */\nexport const useAdkMessageMetadata = () =>\n adkExtras.use((e) => e.messageMetadata, EMPTY_MESSAGE_METADATA);\n\n// ── Convenience helpers for interactive flows ──\n\n/** Returns a function to confirm or deny a pending tool confirmation. */\nexport const useAdkConfirmTool = () => {\n const aui = useAui();\n return (\n toolCallId: string,\n confirmed: boolean,\n payload?: ReadonlyJSONValue,\n ) =>\n adkExtras\n .get(aui)\n .send([toAdkConfirmationReply(toolCallId, confirmed, payload)], {});\n};\n\n/** Returns a function to submit auth credentials for a pending auth request. */\nexport const useAdkSubmitAuth = () => {\n const aui = useAui();\n return (toolCallId: string, credential: AdkAuthCredential) =>\n adkExtras.get(aui).send(\n [\n {\n id: generateId(),\n type: \"tool\",\n tool_call_id: toolCallId,\n name: \"adk_request_credential\",\n content: JSON.stringify(credential),\n status: \"success\",\n },\n ],\n {},\n );\n};\n\n/** Returns a function to submit the user's answer for a pending `adk_request_input` HITL interrupt. */\nexport const useAdkSubmitInput = () => {\n const aui = useAui();\n return (toolCallId: string, result: ReadonlyJSONValue) =>\n adkExtras.get(aui).send(\n [\n {\n id: generateId(),\n type: \"tool\",\n tool_call_id: toolCallId,\n name: \"adk_request_input\",\n content: JSON.stringify({ result }),\n status: \"success\",\n },\n ],\n {},\n );\n};\n\n// ── State prefix helpers ──\n\nconst APP_PREFIX = \"app:\";\nconst USER_PREFIX = \"user:\";\nconst TEMP_PREFIX = \"temp:\";\n\nconst filterByPrefix = (\n state: Record<string, unknown>,\n prefix: string,\n): Record<string, unknown> =>\n Object.fromEntries(\n Object.entries(state)\n .filter(([key]) => key.startsWith(prefix))\n .map(([key, value]) => [key.slice(prefix.length), value]),\n );\n\nconst useAdkStateByPrefix = (prefix: string) =>\n adkExtras.use(\n useShallowSelector((e: AdkRuntimeExtras) =>\n filterByPrefix(e.stateDelta, prefix),\n ),\n EMPTY_STATE_DELTA,\n );\n\n/** Returns app-level state (keys prefixed with `app:`, prefix stripped). */\nexport const useAdkAppState = () => useAdkStateByPrefix(APP_PREFIX);\n\n/** Returns user-level state (keys prefixed with `user:`, prefix stripped). */\nexport const useAdkUserState = () => useAdkStateByPrefix(USER_PREFIX);\n\n/** Returns temp state (keys prefixed with `temp:`, prefix stripped). Not persisted. */\nexport const useAdkTempState = () => useAdkStateByPrefix(TEMP_PREFIX);\n"],"mappings":";;;;;;AAgBA,MAAM,oBAA6C,CAAC;AACpD,MAAM,uBAA+C,CAAC;AACtD,MAAM,8BAAwC,CAAC;AAC/C,MAAM,2BAAkD,CAAC;AACzD,MAAM,sBAAwC,CAAC;AAC/C,MAAM,yCAAyB,IAAI,IAAgC;;AAGnE,MAAa,wBACX,UAAU,KAAK,MAAM,EAAE,WAAW,KAAA,CAAS;;AAG7C,MAAa,2BACX,UAAU,KAAK,MAAM,EAAE,YAAY,iBAAiB;;AAGtD,MAAa,mBAAmB;CAC9B,MAAM,MAAM,OAAO;CACnB,QAAQ,UAAwB,WAC9B,UAAU,IAAI,GAAG,CAAC,CAAC,KAAK,UAAU,MAAM;AAC5C;;AAGA,MAAa,iCACX,UAAU,KAAK,MAAM,EAAE,oBAAoB,2BAA2B;;AAGxE,MAAa,gCACX,UAAU,KAAK,MAAM,EAAE,mBAAmB,wBAAwB;;AAGpE,MAAa,2BACX,UAAU,KAAK,MAAM,EAAE,cAAc,mBAAmB;;AAG1D,MAAa,wBACX,UAAU,KAAK,MAAM,EAAE,eAAe,oBAAoB;;AAG5D,MAAa,yBAAyB,UAAU,KAAK,MAAM,EAAE,WAAW,KAAK;;AAG7E,MAAa,8BACX,UAAU,KAAK,MAAM,EAAE,iBAAiB,sBAAsB;;AAKhE,MAAa,0BAA0B;CACrC,MAAM,MAAM,OAAO;CACnB,QACE,YACA,WACA,YAEA,UACG,IAAI,GAAG,CAAC,CACR,KAAK,CAAC,uBAAuB,YAAY,WAAW,OAAO,CAAC,GAAG,CAAC,CAAC;AACxE;;AAGA,MAAa,yBAAyB;CACpC,MAAM,MAAM,OAAO;CACnB,QAAQ,YAAoB,eAC1B,UAAU,IAAI,GAAG,CAAC,CAAC,KACjB,CACE;EACE,IAAI,WAAW;EACf,MAAM;EACN,cAAc;EACd,MAAM;EACN,SAAS,KAAK,UAAU,UAAU;EAClC,QAAQ;CACV,CACF,GACA,CAAC,CACH;AACJ;;AAGA,MAAa,0BAA0B;CACrC,MAAM,MAAM,OAAO;CACnB,QAAQ,YAAoB,WAC1B,UAAU,IAAI,GAAG,CAAC,CAAC,KACjB,CACE;EACE,IAAI,WAAW;EACf,MAAM;EACN,cAAc;EACd,MAAM;EACN,SAAS,KAAK,UAAU,EAAE,OAAO,CAAC;EAClC,QAAQ;CACV,CACF,GACA,CAAC,CACH;AACJ;AAIA,MAAM,aAAa;AACnB,MAAM,cAAc;AACpB,MAAM,cAAc;AAEpB,MAAM,kBACJ,OACA,WAEA,OAAO,YACL,OAAO,QAAQ,KAAK,CAAC,CAClB,QAAQ,CAAC,SAAS,IAAI,WAAW,MAAM,CAAC,CAAC,CACzC,KAAK,CAAC,KAAK,WAAW,CAAC,IAAI,MAAM,OAAO,MAAM,GAAG,KAAK,CAAC,CAC5D;AAEF,MAAM,uBAAuB,WAC3B,UAAU,IACR,oBAAoB,MAClB,eAAe,EAAE,YAAY,MAAM,CACrC,GACA,iBACF;;AAGF,MAAa,uBAAuB,oBAAoB,UAAU;;AAGlE,MAAa,wBAAwB,oBAAoB,WAAW;;AAGpE,MAAa,wBAAwB,oBAAoB,WAAW"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseAdkEvent.d.ts","names":[],"sources":["../src/parseAdkEvent.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"parseAdkEvent.d.ts","names":[],"sources":["../src/parseAdkEvent.ts"],"mappings":";;iBAUgB,mBACd,gBACA,sBACC"}
|
package/dist/parseAdkEvent.js
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
|
+
import { isRecord } from "@assistant-ui/core/internal";
|
|
1
2
|
//#region src/parseAdkEvent.ts
|
|
3
|
+
const invalidField = (errorPrefix, field, expectation) => /* @__PURE__ */ new Error(`${errorPrefix}: expected "${field}" to be ${expectation}.`);
|
|
2
4
|
function parseAdkEventValue(value, errorPrefix) {
|
|
3
|
-
if (
|
|
4
|
-
const { id: rawId, ...event } = value;
|
|
5
|
+
if (!isRecord(value) || Object.keys(value).length === 0) throw new Error(`${errorPrefix}: expected a non-empty object.`);
|
|
6
|
+
const { id: rawId, content: rawContent, ...event } = value;
|
|
5
7
|
if (rawId != null && typeof rawId !== "string" && (typeof rawId !== "number" || !Number.isFinite(rawId))) throw new Error(`${errorPrefix}: expected "id" to be a string or finite number when present.`);
|
|
8
|
+
let content;
|
|
9
|
+
if (rawContent != null) {
|
|
10
|
+
if (!isRecord(rawContent)) throw invalidField(errorPrefix, "content", "an object when present");
|
|
11
|
+
const { parts, ...contentFields } = rawContent;
|
|
12
|
+
if (parts != null && (!Array.isArray(parts) || !parts.every(isRecord))) throw invalidField(errorPrefix, "content.parts", "an array of objects when present");
|
|
13
|
+
content = {
|
|
14
|
+
...contentFields,
|
|
15
|
+
...parts != null && { parts }
|
|
16
|
+
};
|
|
17
|
+
}
|
|
6
18
|
const errorMessage = "error" in event && typeof event.error === "string" ? event.error : void 0;
|
|
7
19
|
return {
|
|
8
20
|
...event,
|
|
21
|
+
...content !== void 0 && { content },
|
|
9
22
|
...rawId != null && { id: String(rawId) },
|
|
10
23
|
...errorMessage !== void 0 && !("errorMessage" in event) && !("error_message" in event) && { errorMessage }
|
|
11
24
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseAdkEvent.js","names":[],"sources":["../src/parseAdkEvent.ts"],"sourcesContent":["import type { AdkEvent } from \"./types\";\n\
|
|
1
|
+
{"version":3,"file":"parseAdkEvent.js","names":[],"sources":["../src/parseAdkEvent.ts"],"sourcesContent":["import { isRecord } from \"@assistant-ui/core/internal\";\nimport type { AdkEvent } from \"./types\";\n\nconst invalidField = (\n errorPrefix: string,\n field: string,\n expectation: string,\n): Error =>\n new Error(`${errorPrefix}: expected \"${field}\" to be ${expectation}.`);\n\nexport function parseAdkEventValue(\n value: unknown,\n errorPrefix: string,\n): AdkEvent {\n if (!isRecord(value) || Object.keys(value).length === 0) {\n throw new Error(`${errorPrefix}: expected a non-empty object.`);\n }\n\n const {\n id: rawId,\n content: rawContent,\n ...event\n } = value as Record<string, unknown>;\n if (\n rawId != null &&\n typeof rawId !== \"string\" &&\n (typeof rawId !== \"number\" || !Number.isFinite(rawId))\n ) {\n throw new Error(\n `${errorPrefix}: expected \"id\" to be a string or finite number when present.`,\n );\n }\n\n let content: Record<string, unknown> | undefined;\n if (rawContent != null) {\n if (!isRecord(rawContent)) {\n throw invalidField(errorPrefix, \"content\", \"an object when present\");\n }\n\n const { parts, ...contentFields } = rawContent;\n if (parts != null && (!Array.isArray(parts) || !parts.every(isRecord))) {\n throw invalidField(\n errorPrefix,\n \"content.parts\",\n \"an array of objects when present\",\n );\n }\n\n content = {\n ...contentFields,\n ...(parts != null && { parts }),\n };\n }\n\n const errorMessage =\n \"error\" in event && typeof event.error === \"string\"\n ? event.error\n : undefined;\n return {\n ...event,\n ...(content !== undefined && { content }),\n ...(rawId != null && { id: String(rawId) }),\n ...(errorMessage !== undefined &&\n !(\"errorMessage\" in event) &&\n !(\"error_message\" in event) && {\n errorMessage,\n }),\n } as AdkEvent;\n}\n"],"mappings":";;AAGA,MAAM,gBACJ,aACA,OACA,gCAEA,IAAI,MAAM,GAAG,YAAY,cAAc,MAAM,UAAU,YAAY,EAAE;AAEvE,SAAgB,mBACd,OACA,aACU;CACV,IAAI,CAAC,SAAS,KAAK,KAAK,OAAO,KAAK,KAAK,CAAC,CAAC,WAAW,GACpD,MAAM,IAAI,MAAM,GAAG,YAAY,+BAA+B;CAGhE,MAAM,EACJ,IAAI,OACJ,SAAS,YACT,GAAG,UACD;CACJ,IACE,SAAS,QACT,OAAO,UAAU,aAChB,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK,IAEpD,MAAM,IAAI,MACR,GAAG,YAAY,8DACjB;CAGF,IAAI;CACJ,IAAI,cAAc,MAAM;EACtB,IAAI,CAAC,SAAS,UAAU,GACtB,MAAM,aAAa,aAAa,WAAW,wBAAwB;EAGrE,MAAM,EAAE,OAAO,GAAG,kBAAkB;EACpC,IAAI,SAAS,SAAS,CAAC,MAAM,QAAQ,KAAK,KAAK,CAAC,MAAM,MAAM,QAAQ,IAClE,MAAM,aACJ,aACA,iBACA,kCACF;EAGF,UAAU;GACR,GAAG;GACH,GAAI,SAAS,QAAQ,EAAE,MAAM;EAC/B;CACF;CAEA,MAAM,eACJ,WAAW,SAAS,OAAO,MAAM,UAAU,WACvC,MAAM,QACN,KAAA;CACN,OAAO;EACL,GAAG;EACH,GAAI,YAAY,KAAA,KAAa,EAAE,QAAQ;EACvC,GAAI,SAAS,QAAQ,EAAE,IAAI,OAAO,KAAK,EAAE;EACzC,GAAI,iBAAiB,KAAA,KACnB,EAAE,kBAAkB,UACpB,EAAE,mBAAmB,UAAU,EAC7B,aACF;CACJ;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAdkMessages.d.ts","names":[],"sources":["../src/useAdkMessages.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"useAdkMessages.d.ts","names":[],"sources":["../src/useAdkMessages.ts"],"mappings":";;KA+BY;EACV,QAAQ;EACR;IACE,UAAU;IACV,gBAAgB;IAChB,kBAAkB;;;cAcT,mBAAkB,QAAA,iBAG5B;;;;IAIQ;IACE;;;;;;;;EAkFW,cAAA,aAAA,cAAY,QAAU,yBAAoB;;EAnDhB,cAAA,MAAA;EA+BvC,kBAAA,MAAA;EAnBI,gBAAA,UAAA"}
|
package/dist/useAdkMessages.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { contentToParts } from "./contentToParts.js";
|
|
2
2
|
import { AdkEventAccumulator } from "./AdkEventAccumulator.js";
|
|
3
|
+
import { abortableIterable, invokeUserCallback, openAbortableIterable } from "@assistant-ui/core/internal";
|
|
3
4
|
import { generateId } from "@assistant-ui/core";
|
|
4
|
-
import { invokeUserCallback } from "@assistant-ui/core/internal";
|
|
5
5
|
import { useAui } from "@assistant-ui/store";
|
|
6
6
|
import { useCallback, useEffect, useInsertionEffect, useMemo, useRef, useState } from "react";
|
|
7
7
|
//#region src/useAdkMessages.ts
|
|
@@ -73,17 +73,20 @@ const useAdkMessages = ({ stream, eventHandlers }) => {
|
|
|
73
73
|
const accumulator = new AdkEventAccumulator(messagesRef.current.filter((m) => !resentIds.has(m.id)));
|
|
74
74
|
for (const event of messagesToEvents(newMessagesWithId)) accumulator.processEvent(event);
|
|
75
75
|
setMessagesImmediate(accumulator.getMessages());
|
|
76
|
+
abortControllerRef.current?.abort();
|
|
76
77
|
const abortController = new AbortController();
|
|
77
78
|
abortControllerRef.current = abortController;
|
|
78
79
|
try {
|
|
79
|
-
const response = await stream(newMessagesWithId, {
|
|
80
|
+
const response = await openAbortableIterable(stream(newMessagesWithId, {
|
|
80
81
|
...config,
|
|
81
82
|
abortSignal: abortController.signal,
|
|
82
83
|
initialize: async () => {
|
|
83
84
|
return await aui.threadListItem.initialize();
|
|
84
85
|
}
|
|
85
|
-
});
|
|
86
|
-
|
|
86
|
+
}), abortController.signal);
|
|
87
|
+
if (!response) return;
|
|
88
|
+
for await (const event of abortableIterable(response, abortController.signal)) {
|
|
89
|
+
if (abortController.signal.aborted || abortControllerRef.current !== abortController) break;
|
|
87
90
|
const updatedMessages = accumulator.processEvent(event);
|
|
88
91
|
setMessagesImmediate(updatedMessages);
|
|
89
92
|
setStateDelta({
|
|
@@ -112,7 +115,7 @@ const useAdkMessages = ({ stream, eventHandlers }) => {
|
|
|
112
115
|
if (event.errorCode || event.errorMessage) invokeAdkRuntimeCallback("onError", onError, event.errorMessage ?? event.errorCode);
|
|
113
116
|
}
|
|
114
117
|
} catch (error) {
|
|
115
|
-
if (!abortController.signal.aborted && !(error instanceof Error && error.name === "AbortError")) throw error;
|
|
118
|
+
if (!abortController.signal.aborted && abortControllerRef.current === abortController && !(error instanceof Error && error.name === "AbortError")) throw error;
|
|
116
119
|
} finally {
|
|
117
120
|
if (abortControllerRef.current === abortController) abortControllerRef.current = null;
|
|
118
121
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAdkMessages.js","names":[],"sources":["../src/useAdkMessages.ts"],"sourcesContent":["import {\n useState,\n useCallback,\n useEffect,\n useInsertionEffect,\n useRef,\n useMemo,\n} 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 // setMessagesImmediate is the only writer of the messages state and publishes\n // this ref with it, so the ref never trails a commit.\n const messagesRef = useRef(messages);\n const stateDeltaRef = useRef(stateDelta);\n useInsertionEffect(() => {\n stateDeltaRef.current = stateDelta;\n }, [stateDelta]);\n const artifactDeltaRef = useRef(artifactDelta);\n useInsertionEffect(() => {\n artifactDeltaRef.current = artifactDelta;\n }, [artifactDelta]);\n const messageMetadataRef = useRef(messageMetadata);\n useInsertionEffect(() => {\n messageMetadataRef.current = messageMetadata;\n }, [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":"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"}
|
|
1
|
+
{"version":3,"file":"useAdkMessages.js","names":[],"sources":["../src/useAdkMessages.ts"],"sourcesContent":["import {\n useState,\n useCallback,\n useEffect,\n useInsertionEffect,\n useRef,\n useMemo,\n} from \"react\";\nimport { generateId } from \"@assistant-ui/core\";\nimport { useAui } from \"@assistant-ui/store\";\nimport {\n abortableIterable,\n invokeUserCallback,\n openAbortableIterable,\n} 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 // setMessagesImmediate is the only writer of the messages state and publishes\n // this ref with it, so the ref never trails a commit.\n const messagesRef = useRef(messages);\n const stateDeltaRef = useRef(stateDelta);\n useInsertionEffect(() => {\n stateDeltaRef.current = stateDelta;\n }, [stateDelta]);\n const artifactDeltaRef = useRef(artifactDelta);\n useInsertionEffect(() => {\n artifactDeltaRef.current = artifactDelta;\n }, [artifactDelta]);\n const messageMetadataRef = useRef(messageMetadata);\n useInsertionEffect(() => {\n messageMetadataRef.current = messageMetadata;\n }, [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 // Google ADK replaces active runs, while React LangGraph queues sends.\n abortControllerRef.current?.abort();\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n\n try {\n const response = await openAbortableIterable(\n stream(newMessagesWithId, {\n ...config,\n abortSignal: abortController.signal,\n initialize: async () => {\n return await aui.threadListItem.initialize();\n },\n }),\n abortController.signal,\n );\n if (!response) return;\n\n for await (const event of abortableIterable(\n response,\n abortController.signal,\n )) {\n if (\n abortController.signal.aborted ||\n abortControllerRef.current !== abortController\n ) {\n break;\n }\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 abortControllerRef.current === abortController &&\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":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAdkRuntime.d.ts","names":[],"sources":["../src/useAdkRuntime.ts"],"mappings":";;;;KA4DY,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;;
|
|
1
|
+
{"version":3,"file":"useAdkRuntime.d.ts","names":[],"sources":["../src/useAdkRuntime.ts"],"mappings":";;;;KA4DY,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;;cAkYN,kBAAiB,OAAA,gBAAA,QAAA,QAAA,UAAA,qBAAA,WAO3B,sDAAoB"}
|
package/dist/useAdkRuntime.js
CHANGED
|
@@ -3,9 +3,9 @@ import { projectAdkToolApprovals, toAdkToolConfirmationReply } from "./adkToolAp
|
|
|
3
3
|
import { convertAdkMessage, createAdkMessageConverter } from "./convertAdkMessages.js";
|
|
4
4
|
import { getMessageContent, getPendingCancellations, toAdkUserMessage, truncateAdkMessages } from "./convertToAdkMessages.js";
|
|
5
5
|
import { useAdkMessages } from "./useAdkMessages.js";
|
|
6
|
+
import { createAbortableThreadLoad, createCloudThreadListAdapterCreateFallback } from "@assistant-ui/core/internal";
|
|
6
7
|
import { generateId, pickExternalStoreSharedOptions } from "@assistant-ui/core";
|
|
7
8
|
import { useCloudThreadListAdapter, useExternalMessageConverter, useExternalStoreRuntime, useRemoteThreadListRuntime } from "@assistant-ui/core/react";
|
|
8
|
-
import { createAbortableThreadLoad, createCloudThreadListAdapterCreateFallback } from "@assistant-ui/core/internal";
|
|
9
9
|
import { useAui } from "@assistant-ui/store";
|
|
10
10
|
import { useCallback, useEffect, useInsertionEffect, useMemo, useRef, useState } from "react";
|
|
11
11
|
//#region src/useAdkRuntime.ts
|
|
@@ -34,12 +34,14 @@ const useAdkRuntimeImpl = (options) => {
|
|
|
34
34
|
useInsertionEffect(() => {
|
|
35
35
|
isRunningRef.current = effectiveIsRunning;
|
|
36
36
|
}, [effectiveIsRunning]);
|
|
37
|
+
const runGenerationRef = useRef(0);
|
|
37
38
|
const handleSendMessage = async (msgs, config) => {
|
|
39
|
+
const generation = ++runGenerationRef.current;
|
|
38
40
|
try {
|
|
39
41
|
setIsRunning(true);
|
|
40
42
|
await sendMessage(msgs, config);
|
|
41
43
|
} finally {
|
|
42
|
-
setIsRunning(false);
|
|
44
|
+
if (runGenerationRef.current === generation) setIsRunning(false);
|
|
43
45
|
}
|
|
44
46
|
};
|
|
45
47
|
const { approvals: toolApprovals, key: toolApprovalsKey } = projectAdkToolApprovals(messages);
|