@assistant-ui/react-google-adk 0.0.30 → 0.0.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AdkClient.d.ts +26 -29
- package/dist/AdkClient.d.ts.map +1 -1
- package/dist/AdkClient.js +5 -3
- package/dist/AdkClient.js.map +1 -1
- package/dist/AdkEventAccumulator.d.ts +41 -45
- package/dist/AdkEventAccumulator.d.ts.map +1 -1
- package/dist/AdkEventAccumulator.js +63 -99
- package/dist/AdkEventAccumulator.js.map +1 -1
- package/dist/AdkSessionAdapter.d.ts +41 -39
- package/dist/AdkSessionAdapter.d.ts.map +1 -1
- package/dist/AdkSessionAdapter.js +11 -7
- package/dist/AdkSessionAdapter.js.map +1 -1
- package/dist/adkAuthRequest.d.ts +17 -0
- package/dist/adkAuthRequest.d.ts.map +1 -0
- package/dist/adkAuthRequest.js +45 -0
- package/dist/adkAuthRequest.js.map +1 -0
- package/dist/adkExtras.d.ts +2 -5
- package/dist/adkExtras.d.ts.map +1 -1
- package/dist/adkToolApproval.d.ts +18 -21
- package/dist/adkToolApproval.d.ts.map +1 -1
- package/dist/adkToolApproval.js +1 -3
- package/dist/adkToolApproval.js.map +1 -1
- package/dist/contentToParts.d.ts +2 -5
- package/dist/contentToParts.d.ts.map +1 -1
- package/dist/convertAdkMessages.d.ts +5 -8
- package/dist/convertAdkMessages.d.ts.map +1 -1
- package/dist/convertAdkMessages.js +4 -3
- package/dist/convertAdkMessages.js.map +1 -1
- package/dist/convertToAdkMessages.d.ts +36 -39
- package/dist/convertToAdkMessages.d.ts.map +1 -1
- package/dist/hooks.d.ts +25 -23
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +12 -10
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +11 -10
- package/dist/index.d.ts.map +1 -0
- package/dist/normalizeAdkPart.d.ts +2 -0
- package/dist/normalizeAdkPart.d.ts.map +1 -0
- package/dist/normalizeAdkPart.js +31 -0
- package/dist/normalizeAdkPart.js.map +1 -0
- package/dist/parseAdkEvent.d.ts +2 -5
- package/dist/parseAdkEvent.d.ts.map +1 -1
- package/dist/raceWithAbortSignal.d.ts +2 -0
- package/dist/raceWithAbortSignal.d.ts.map +1 -0
- package/dist/raceWithAbortSignal.js +45 -0
- package/dist/raceWithAbortSignal.js.map +1 -0
- package/dist/sdkIdentity.d.ts +2 -5
- package/dist/sdkIdentity.d.ts.map +1 -1
- package/dist/sdkIdentity.js +1 -1
- package/dist/server/adkEventStream.d.ts +25 -27
- package/dist/server/adkEventStream.d.ts.map +1 -1
- package/dist/server/adkEventStream.js +23 -15
- package/dist/server/adkEventStream.js.map +1 -1
- package/dist/server/createAdkApiRoute.d.ts +23 -25
- package/dist/server/createAdkApiRoute.d.ts.map +1 -1
- package/dist/server/index.d.ts +4 -4
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/parseAdkRequest.d.ts +18 -20
- package/dist/server/parseAdkRequest.d.ts.map +1 -1
- package/dist/structuredEvents.d.ts +2 -5
- package/dist/structuredEvents.d.ts.map +1 -1
- package/dist/structuredEvents.js +1 -1
- package/dist/structuredEvents.js.map +1 -1
- package/dist/toAdkFunctionResponse.d.ts +2 -5
- package/dist/toAdkFunctionResponse.d.ts.map +1 -1
- package/dist/trimTrailingSlashes.d.ts +1 -4
- package/dist/trimTrailingSlashes.d.ts.map +1 -1
- package/dist/types.d.ts +253 -256
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/useAdkMessages.d.ts +26 -29
- package/dist/useAdkMessages.d.ts.map +1 -1
- package/dist/useAdkMessages.js +2 -0
- package/dist/useAdkMessages.js.map +1 -1
- package/dist/useAdkRuntime.d.ts +50 -52
- package/dist/useAdkRuntime.d.ts.map +1 -1
- package/dist/useAdkRuntime.js +1 -1
- package/package.json +10 -9
- package/src/AdkClient.test.ts +50 -0
- package/src/AdkClient.ts +10 -3
- package/src/AdkEventAccumulator.test.ts +312 -11
- package/src/AdkEventAccumulator.ts +68 -142
- package/src/AdkSessionAdapter.test.ts +284 -1
- package/src/AdkSessionAdapter.ts +32 -8
- package/src/adkAuthRequest.test.ts +101 -0
- package/src/adkAuthRequest.ts +50 -0
- package/src/adkToolApproval.test.ts +0 -4
- package/src/adkToolApproval.ts +1 -3
- package/src/convertAdkMessages.test.ts +41 -0
- package/src/convertAdkMessages.ts +19 -7
- package/src/hooks.render.test.tsx +95 -2
- package/src/hooks.ts +12 -13
- package/src/normalizeAdkPart.ts +35 -0
- package/src/raceWithAbortSignal.test.ts +73 -0
- package/src/raceWithAbortSignal.ts +48 -0
- package/src/server/adkEventStream.test.ts +147 -0
- package/src/server/adkEventStream.ts +27 -20
- package/src/structuredEvents.test.ts +69 -0
- package/src/structuredEvents.ts +4 -1
- package/src/types.ts +1 -1
- package/src/useAdkMessages.test.ts +102 -3
- package/src/useAdkMessages.ts +2 -0
- package/src/useAdkRuntime.replacement.test.tsx +11 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdkEventAccumulator.js","names":[],"sources":["../src/AdkEventAccumulator.ts"],"sourcesContent":["import { generateId } from \"@assistant-ui/core\";\nimport { isRecord } from \"@assistant-ui/core/internal\";\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\";\nimport { isAdkFunctionError } from \"./toAdkFunctionResponse\";\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 (isRecord(result.inlineData)) {\n const data = result.inlineData;\n if (\"mime_type\" in data && !(\"mimeType\" in data))\n result.inlineData = { ...data, mimeType: data.mime_type };\n }\n if (isRecord(result.fileData)) {\n const data = result.fileData;\n result.fileData = {\n ...data,\n ...(\"mime_type\" in data &&\n !(\"mimeType\" in data) && { mimeType: data.mime_type }),\n ...(\"file_uri\" in data &&\n !(\"fileUri\" in data) && { fileUri: data.file_uri }),\n };\n }\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(\n initialMessages?: AdkMessage[],\n initialLongRunningToolIds?: readonly string[],\n ) {\n if (initialMessages) {\n for (const msg of initialMessages) {\n this.messagesMap.set(msg.id, msg);\n }\n }\n if (initialLongRunningToolIds) {\n this.pendingLongRunningToolIds = new Set(initialLongRunningToolIds);\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: isAdkFunctionError(part.functionResponse.response)\n ? \"error\"\n : \"success\",\n });\n // Only a user-authored response settles a long-running call; the response ADK authors for one is the tool's interim result.\n this.pendingLongRunningToolIds.delete(part.functionResponse.id);\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: isAdkFunctionError(part.functionResponse.response)\n ? \"error\"\n : \"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 { isRecord } from \"@assistant-ui/core/internal\";\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\";\nimport { normalizeAdkPart } from \"./normalizeAdkPart\";\nimport { projectAdkToolApprovals } from \"./adkToolApproval\";\nimport { isAdkFunctionError } from \"./toAdkFunctionResponse\";\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 mediaToContentPart = ({\n inlineData,\n fileData,\n}: Record<string, unknown>): AdkMessageContentPart | undefined => {\n if (isRecord(inlineData)) {\n const { mimeType, data } = inlineData;\n if (typeof mimeType !== \"string\" || typeof data !== \"string\") return;\n return mimeType.startsWith(\"image/\")\n ? { type: \"image\", mimeType, data }\n : { type: \"file\", mimeType, data };\n }\n if (!isRecord(fileData)) return;\n const { fileUri, mimeType } = fileData;\n if (typeof fileUri !== \"string\") return;\n return typeof mimeType !== \"string\" || mimeType.startsWith(\"image/\")\n ? { type: \"image_url\", url: fileUri }\n : { type: \"file_url\", url: fileUri, mimeType };\n};\n\n// ── Snake_case normalization ──\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 Record<string, unknown>[];\n result.content = { ...content, parts: parts.map(normalizeAdkPart) };\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 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(\n initialMessages?: AdkMessage[],\n initialLongRunningToolIds?: readonly string[],\n ) {\n if (initialMessages) {\n for (const msg of initialMessages) {\n this.messagesMap.set(msg.id, msg);\n }\n }\n if (initialLongRunningToolIds) {\n this.pendingLongRunningToolIds = new Set(initialLongRunningToolIds);\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 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 || part.fileData) {\n const mediaPart = mediaToContentPart(part);\n if (mediaPart) humanParts.push(mediaPart);\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: isAdkFunctionError(part.functionResponse.response)\n ? \"error\"\n : \"success\",\n });\n // Only a user-authored response settles a long-running call; the response ADK authors for one is the tool's interim result.\n this.pendingLongRunningToolIds.delete(part.functionResponse.id);\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 // 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: isAdkFunctionError(part.functionResponse.response)\n ? \"error\"\n : \"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 const mediaPart = mediaToContentPart(part);\n if (!mediaPart) return;\n const msg = this.getOrCreateAiMessage(event);\n this.appendContent(msg, mediaPart);\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 // ADK resumes a confirmation or credential request only on a reply that quotes its synthetic call's id, so those calls are the whole record; requestedToolConfirmations and requestedAuthConfigs key the gated call instead, which no reply answers.\n private getRequestCalls(name: string): AdkToolCall[] {\n const calls = new Map<string, AdkToolCall>();\n for (const msg of this.messagesMap.values()) {\n if (msg.type !== \"ai\") continue;\n for (const call of msg.tool_calls ?? []) {\n if (call.name === name && !calls.has(call.id)) calls.set(call.id, call);\n }\n }\n return [...calls.values()];\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 const { approvals } = projectAdkToolApprovals(this.getMessages());\n return this.getRequestCalls(ADK_REQUEST_CONFIRMATION)\n .filter(({ id }) => approvals.get(id)?.approved === undefined)\n .map(({ id, args = {} }) => {\n const original = (args.originalFunctionCall ??\n args.original_function_call) as Record<string, unknown> | undefined;\n const confirmation = (args.toolConfirmation ??\n args.tool_confirmation) as Record<string, unknown> | undefined;\n return {\n toolCallId: id,\n toolName: (original?.name as string) ?? \"\",\n args: (original?.args as Record<string, unknown>) ?? {},\n hint: (confirmation?.hint as string) ?? \"\",\n confirmed: false,\n payload: confirmation?.payload,\n };\n });\n }\n\n getAuthRequests(): AdkAuthRequest[] {\n const answered = new Set<string>();\n for (const msg of this.messagesMap.values()) {\n if (msg.type === \"tool\") answered.add(msg.tool_call_id);\n }\n return this.getRequestCalls(ADK_REQUEST_CREDENTIAL)\n .filter(({ id }) => !answered.has(id))\n .map(({ id, args = {} }) => ({\n toolCallId: id,\n authConfig: args.auth_config ?? args.authConfig,\n }));\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,42 +1,45 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>) | undefined;
|
|
1
|
+
import type { RemoteThreadListAdapter } from "@assistant-ui/core";
|
|
2
|
+
import type { AdkThreadSnapshot } from "./types.js";
|
|
3
|
+
export type AdkSessionAdapterOptions = {
|
|
4
|
+
/**
|
|
5
|
+
* ADK server base URL (e.g. "http://localhost:8000").
|
|
6
|
+
*/
|
|
7
|
+
apiUrl: string;
|
|
8
|
+
/**
|
|
9
|
+
* ADK application name.
|
|
10
|
+
*/
|
|
11
|
+
appName: string;
|
|
12
|
+
/**
|
|
13
|
+
* ADK user ID.
|
|
14
|
+
*/
|
|
15
|
+
userId: string;
|
|
16
|
+
/**
|
|
17
|
+
* Extra headers for API requests.
|
|
18
|
+
*/
|
|
19
|
+
headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>) | undefined;
|
|
21
20
|
};
|
|
22
|
-
type AdkArtifactData = {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
export type AdkArtifactData = {
|
|
22
|
+
inlineData?: {
|
|
23
|
+
mimeType: string;
|
|
24
|
+
data: string;
|
|
25
|
+
} | undefined;
|
|
26
|
+
fileData?: {
|
|
27
|
+
fileUri: string;
|
|
28
|
+
mimeType?: string | undefined;
|
|
29
|
+
} | undefined;
|
|
30
|
+
text?: string | undefined;
|
|
28
31
|
};
|
|
29
32
|
type AdkSessionAdapterResult = {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
adapter: RemoteThreadListAdapter;
|
|
34
|
+
load: (sessionId: string, options?: {
|
|
35
|
+
signal?: AbortSignal | undefined;
|
|
36
|
+
}) => Promise<AdkThreadSnapshot>;
|
|
37
|
+
artifacts: {
|
|
38
|
+
list: (sessionId: string) => Promise<string[]>;
|
|
39
|
+
load: (sessionId: string, artifactName: string, version?: number) => Promise<AdkArtifactData>;
|
|
40
|
+
listVersions: (sessionId: string, artifactName: string) => Promise<number[]>;
|
|
41
|
+
delete: (sessionId: string, artifactName: string) => Promise<void>;
|
|
42
|
+
};
|
|
40
43
|
};
|
|
41
44
|
/**
|
|
42
45
|
* Creates a `RemoteThreadListAdapter` backed by ADK's session REST API,
|
|
@@ -57,7 +60,6 @@ type AdkSessionAdapterResult = {
|
|
|
57
60
|
* });
|
|
58
61
|
* ```
|
|
59
62
|
*/
|
|
60
|
-
declare function createAdkSessionAdapter(options: AdkSessionAdapterOptions): AdkSessionAdapterResult;
|
|
61
|
-
|
|
62
|
-
export { AdkArtifactData, AdkSessionAdapterOptions, createAdkSessionAdapter };
|
|
63
|
+
export declare function createAdkSessionAdapter(options: AdkSessionAdapterOptions): AdkSessionAdapterResult;
|
|
64
|
+
export {};
|
|
63
65
|
//# sourceMappingURL=AdkSessionAdapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdkSessionAdapter.d.ts","
|
|
1
|
+
{"version":3,"file":"AdkSessionAdapter.d.ts","sourceRoot":"","sources":["../src/AdkSessionAdapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,uBAAuB,EAGxB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,KAAK,EAAc,iBAAiB,EAAE,mBAAgB;AAI7D,MAAM,MAAM,wBAAwB,GAAG;IACrC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,CAAC,EACJ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtB,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAChE,SAAS,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,UAAU,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAC5D,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,GAAG,SAAS,CAAC;IAC1E,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B,CAAC;AAEF,KAAK,uBAAuB,GAAG;IAC7B,OAAO,EAAE,uBAAuB,CAAC;IACjC,IAAI,EAAE,CACJ,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;KAAE,KAC3C,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAChC,SAAS,EAAE;QACT,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/C,IAAI,EAAE,CACJ,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,MAAM,KACb,OAAO,CAAC,eAAe,CAAC,CAAC;QAC9B,YAAY,EAAE,CACZ,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,KACjB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACvB,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACpE,CAAC;CACH,CAAC;AA+IF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,uBAAuB,CAiMzB"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { parseAdkEventValue } from "./parseAdkEvent.js";
|
|
2
|
+
import { raceWithAbortSignal } from "./raceWithAbortSignal.js";
|
|
2
3
|
import { trimTrailingSlashes } from "./trimTrailingSlashes.js";
|
|
4
|
+
import { normalizeAdkPart } from "./normalizeAdkPart.js";
|
|
3
5
|
import { AdkEventAccumulator } from "./AdkEventAccumulator.js";
|
|
4
6
|
//#region src/AdkSessionAdapter.ts
|
|
5
7
|
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -31,12 +33,14 @@ const parseAdkArtifactListResponse = (value) => {
|
|
|
31
33
|
});
|
|
32
34
|
};
|
|
33
35
|
const parseAdkArtifactResponse = (value) => {
|
|
34
|
-
if (!isRecord(value)) throw new Error("Invalid ADK artifact load response: expected an object containing \"text\" or \"
|
|
35
|
-
const
|
|
36
|
-
|
|
36
|
+
if (!isRecord(value)) throw new Error("Invalid ADK artifact load response: expected an object containing \"text\", \"inlineData\", or \"fileData\".");
|
|
37
|
+
const normalizedValue = normalizeAdkPart(value);
|
|
38
|
+
const { text, inlineData, fileData } = normalizedValue;
|
|
39
|
+
if (text === void 0 && inlineData === void 0 && fileData === void 0) throw new Error("Invalid ADK artifact load response: expected an object containing \"text\", \"inlineData\", or \"fileData\".");
|
|
37
40
|
if (text !== void 0 && typeof text !== "string") throw new Error("Invalid ADK artifact load response: \"text\" must be a string when present.");
|
|
38
41
|
if (inlineData !== void 0 && (!isRecord(inlineData) || typeof inlineData.mimeType !== "string" || typeof inlineData.data !== "string")) throw new Error("Invalid ADK artifact load response: \"inlineData\" must contain string \"mimeType\" and \"data\" fields.");
|
|
39
|
-
|
|
42
|
+
if (fileData !== void 0 && (!isRecord(fileData) || typeof fileData.fileUri !== "string" || fileData.mimeType !== void 0 && typeof fileData.mimeType !== "string")) throw new Error("Invalid ADK artifact load response: \"fileData\" must contain a string \"fileUri\" and an optional string \"mimeType\" field.");
|
|
43
|
+
return normalizedValue;
|
|
40
44
|
};
|
|
41
45
|
const parseAdkArtifactVersionsResponse = (value) => {
|
|
42
46
|
if (!Array.isArray(value)) throw new Error("Invalid ADK artifact versions response: expected an array of version numbers.");
|
|
@@ -67,9 +71,9 @@ const parseAdkArtifactVersionsResponse = (value) => {
|
|
|
67
71
|
function createAdkSessionAdapter(options) {
|
|
68
72
|
const { apiUrl, appName, userId } = options;
|
|
69
73
|
const baseUrl = `${trimTrailingSlashes(apiUrl)}/apps/${encodeURIComponent(appName)}/users/${encodeURIComponent(userId)}/sessions`;
|
|
70
|
-
const getHeaders = async () => {
|
|
74
|
+
const getHeaders = async (signal) => {
|
|
71
75
|
if (!options.headers) return {};
|
|
72
|
-
if (typeof options.headers === "function") return await options.headers
|
|
76
|
+
if (typeof options.headers === "function") return await raceWithAbortSignal(signal, options.headers);
|
|
73
77
|
return options.headers;
|
|
74
78
|
};
|
|
75
79
|
const adapter = {
|
|
@@ -131,7 +135,7 @@ function createAdkSessionAdapter(options) {
|
|
|
131
135
|
}
|
|
132
136
|
};
|
|
133
137
|
const load = async (sessionId, options) => {
|
|
134
|
-
const headers = await getHeaders();
|
|
138
|
+
const headers = await getHeaders(options?.signal);
|
|
135
139
|
const res = await fetch(`${baseUrl}/${encodeURIComponent(sessionId)}`, {
|
|
136
140
|
headers,
|
|
137
141
|
...options?.signal ? { signal: options.signal } : {}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdkSessionAdapter.js","names":[],"sources":["../src/AdkSessionAdapter.ts"],"sourcesContent":["import type { AssistantStream, AssistantStreamChunk } from \"assistant-stream\";\nimport type {\n RemoteThreadInitializeResponse,\n RemoteThreadListAdapter,\n RemoteThreadListResponse,\n RemoteThreadMetadata,\n} from \"@assistant-ui/core\";\nimport { AdkEventAccumulator } from \"./AdkEventAccumulator\";\nimport { parseAdkEventValue } from \"./parseAdkEvent\";\nimport type { AdkMessage, AdkThreadSnapshot } from \"./types\";\nimport { trimTrailingSlashes } from \"./trimTrailingSlashes\";\n\nexport type AdkSessionAdapterOptions = {\n /**\n * ADK server base URL (e.g. \"http://localhost:8000\").\n */\n apiUrl: string;\n\n /**\n * ADK application name.\n */\n appName: string;\n\n /**\n * ADK user ID.\n */\n userId: string;\n\n /**\n * Extra headers for API requests.\n */\n headers?:\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>)\n | undefined;\n};\n\nexport type AdkArtifactData = {\n inlineData?: { mimeType: string; data: string } | undefined;\n text?: string | undefined;\n};\n\ntype AdkSessionAdapterResult = {\n adapter: RemoteThreadListAdapter;\n load: (\n sessionId: string,\n options?: { signal?: AbortSignal | undefined },\n ) => Promise<AdkThreadSnapshot>;\n artifacts: {\n list: (sessionId: string) => Promise<string[]>;\n load: (\n sessionId: string,\n artifactName: string,\n version?: number,\n ) => Promise<AdkArtifactData>;\n listVersions: (\n sessionId: string,\n artifactName: string,\n ) => Promise<number[]>;\n delete: (sessionId: string, artifactName: string) => Promise<void>;\n };\n};\n\ntype AdkSessionResponse = {\n id: string;\n events?: unknown;\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst isAdkSessionResponse = (value: unknown): value is AdkSessionResponse => {\n if (!isRecord(value)) return false;\n\n const id = value.id;\n return typeof id === \"string\" && id.length > 0;\n};\n\nconst parseAdkSessionResponse = (\n value: unknown,\n operation: \"create\" | \"fetch\" | \"load\",\n): AdkSessionResponse => {\n if (!isAdkSessionResponse(value)) {\n throw new Error(\n `Invalid ADK session ${operation} response: expected an object with a non-empty string \"id\".`,\n );\n }\n return value;\n};\n\nconst parseAdkSessionListResponse = (value: unknown): AdkSessionResponse[] => {\n if (!Array.isArray(value)) {\n throw new Error(\n \"Invalid ADK session list response: expected an array of sessions.\",\n );\n }\n\n return value.map((session, index) => {\n if (!isAdkSessionResponse(session)) {\n throw new Error(\n `Invalid ADK session list response: session at index ${index} must have a non-empty string \"id\".`,\n );\n }\n return session;\n });\n};\n\nconst parseAdkArtifactListResponse = (value: unknown): string[] => {\n if (!Array.isArray(value)) {\n throw new Error(\n \"Invalid ADK artifact list response: expected an array of artifact names.\",\n );\n }\n\n return value.map((artifact, index) => {\n if (typeof artifact === \"string\" && artifact.length > 0) {\n return artifact;\n }\n\n if (isRecord(artifact)) {\n const filename = artifact.filename;\n if (typeof filename === \"string\" && filename.length > 0) {\n return filename;\n }\n }\n\n throw new Error(\n `Invalid ADK artifact list response: artifact at index ${index} must be a non-empty string or an object with a non-empty string \"filename\".`,\n );\n });\n};\n\nconst parseAdkArtifactResponse = (value: unknown): AdkArtifactData => {\n if (!isRecord(value)) {\n throw new Error(\n 'Invalid ADK artifact load response: expected an object containing \"text\" or \"inlineData\".',\n );\n }\n\n const { text, inlineData } = value;\n if (text === undefined && inlineData === undefined) {\n throw new Error(\n 'Invalid ADK artifact load response: expected an object containing \"text\" or \"inlineData\".',\n );\n }\n\n if (text !== undefined && typeof text !== \"string\") {\n throw new Error(\n 'Invalid ADK artifact load response: \"text\" must be a string when present.',\n );\n }\n\n if (\n inlineData !== undefined &&\n (!isRecord(inlineData) ||\n typeof inlineData.mimeType !== \"string\" ||\n typeof inlineData.data !== \"string\")\n ) {\n throw new Error(\n 'Invalid ADK artifact load response: \"inlineData\" must contain string \"mimeType\" and \"data\" fields.',\n );\n }\n\n return value as AdkArtifactData;\n};\n\nconst parseAdkArtifactVersionsResponse = (value: unknown): number[] => {\n if (!Array.isArray(value)) {\n throw new Error(\n \"Invalid ADK artifact versions response: expected an array of version numbers.\",\n );\n }\n\n return value.map((version, index) => {\n if (\n typeof version !== \"number\" ||\n !Number.isInteger(version) ||\n version < 0\n ) {\n throw new Error(\n `Invalid ADK artifact versions response: version at index ${index} must be a non-negative integer.`,\n );\n }\n return version;\n });\n};\n\n/**\n * Creates a `RemoteThreadListAdapter` backed by ADK's session REST API,\n * plus a `load` function that reconstructs messages from session events.\n *\n * @example\n * ```ts\n * const { adapter, load } = createAdkSessionAdapter({\n * apiUrl: \"http://localhost:8000\",\n * appName: \"my-app\",\n * userId: \"user-1\",\n * });\n *\n * const runtime = useAdkRuntime({\n * stream: createAdkStream({ ... }),\n * sessionAdapter: adapter,\n * load,\n * });\n * ```\n */\nexport function createAdkSessionAdapter(\n options: AdkSessionAdapterOptions,\n): AdkSessionAdapterResult {\n const { apiUrl, appName, userId } = options;\n const normalizedApiUrl = trimTrailingSlashes(apiUrl);\n const baseUrl = `${normalizedApiUrl}/apps/${encodeURIComponent(appName)}/users/${encodeURIComponent(userId)}/sessions`;\n\n const getHeaders = async (): Promise<Record<string, string>> => {\n if (!options.headers) return {};\n if (typeof options.headers === \"function\") return await options.headers();\n return options.headers;\n };\n\n const adapter: RemoteThreadListAdapter = {\n async list(): Promise<RemoteThreadListResponse> {\n const headers = await getHeaders();\n const res = await fetch(baseUrl, { headers });\n if (!res.ok) {\n throw new Error(`Failed to list sessions: ${res.status}`);\n }\n const data = parseAdkSessionListResponse(await res.json());\n\n const threads: RemoteThreadMetadata[] = data.map((session) => ({\n status: \"regular\" as const,\n remoteId: session.id,\n externalId: session.id,\n title: undefined,\n }));\n\n return { threads };\n },\n\n async initialize(\n _threadId: string,\n ): Promise<RemoteThreadInitializeResponse> {\n const headers = await getHeaders();\n const res = await fetch(baseUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...headers },\n body: JSON.stringify({}),\n });\n if (!res.ok) {\n throw new Error(`Failed to create session: ${res.status}`);\n }\n const session = parseAdkSessionResponse(await res.json(), \"create\");\n return { remoteId: session.id, externalId: session.id };\n },\n\n async delete(remoteId: string): Promise<void> {\n const headers = await getHeaders();\n const res = await fetch(`${baseUrl}/${encodeURIComponent(remoteId)}`, {\n method: \"DELETE\",\n headers,\n });\n if (!res.ok && res.status !== 404) {\n throw new Error(`Failed to delete session: ${res.status}`);\n }\n },\n\n async rename(): Promise<void> {\n // ADK sessions don't support titles\n },\n\n async archive(): Promise<void> {\n // ADK sessions don't support archiving\n },\n\n async unarchive(): Promise<void> {\n // ADK sessions don't support archiving\n },\n\n generateTitle(): Promise<AssistantStream> {\n // Title generation not supported without assistant-cloud\n return Promise.resolve(\n new ReadableStream<AssistantStreamChunk>({\n start(controller) {\n controller.close();\n },\n }),\n );\n },\n\n async fetch(threadId: string): Promise<RemoteThreadMetadata> {\n const headers = await getHeaders();\n const res = await fetch(`${baseUrl}/${encodeURIComponent(threadId)}`, {\n headers,\n });\n if (!res.ok) {\n throw new Error(`Session not found: ${res.status}`);\n }\n const session = parseAdkSessionResponse(await res.json(), \"fetch\");\n return {\n status: \"regular\",\n remoteId: session.id,\n externalId: session.id,\n title: undefined,\n };\n },\n };\n\n const load = async (\n sessionId: string,\n options?: { signal?: AbortSignal | undefined },\n ): Promise<AdkThreadSnapshot> => {\n const headers = await getHeaders();\n const res = await fetch(`${baseUrl}/${encodeURIComponent(sessionId)}`, {\n headers,\n ...(options?.signal ? { signal: options.signal } : {}),\n });\n if (!res.ok) {\n throw new Error(`Failed to load session: ${res.status}`);\n }\n const session = parseAdkSessionResponse(await res.json(), \"load\");\n\n if (session.events !== undefined && !Array.isArray(session.events)) {\n throw new Error(\n 'Invalid ADK session load response: expected \"events\" to be an array when present.',\n );\n }\n\n // Events carry ordered state and tool transitions, so partial replay can\n // produce a plausible but incorrect thread.\n const events = session.events?.map((event, index) =>\n parseAdkEventValue(event, `Invalid ADK session event at index ${index}`),\n );\n\n if (!events?.length) {\n return { messages: [] };\n }\n\n const accumulator = new AdkEventAccumulator();\n let messages: AdkMessage[] = [];\n for (const event of events) {\n messages = accumulator.processEvent(event);\n }\n // The per-turn state rides along, so a refetch can swap the thread over in\n // one commit instead of reconstructing it from the messages alone.\n return {\n messages,\n longRunningToolIds: accumulator.getLongRunningToolIds(),\n toolConfirmations: accumulator.getToolConfirmations(),\n authRequests: accumulator.getAuthRequests(),\n escalated: accumulator.isEscalated(),\n messageMetadata: accumulator.getMessageMetadata(),\n stateDelta: accumulator.getStateDelta(),\n artifactDelta: accumulator.getArtifactDelta(),\n agentInfo: accumulator.getAgentInfo(),\n };\n };\n\n const artifactBaseUrl = (sessionId: string) =>\n `${baseUrl}/${encodeURIComponent(sessionId)}/artifacts`;\n\n const artifacts: AdkSessionAdapterResult[\"artifacts\"] = {\n async list(sessionId) {\n const headers = await getHeaders();\n const res = await fetch(artifactBaseUrl(sessionId), { headers });\n if (!res.ok) throw new Error(`Failed to list artifacts: ${res.status}`);\n return parseAdkArtifactListResponse(await res.json());\n },\n\n async load(sessionId, artifactName, version?) {\n const headers = await getHeaders();\n let url = `${artifactBaseUrl(sessionId)}/${encodeURIComponent(artifactName)}`;\n if (version != null) url += `/versions/${version}`;\n const res = await fetch(url, { headers });\n if (!res.ok) throw new Error(`Failed to load artifact: ${res.status}`);\n return parseAdkArtifactResponse(await res.json());\n },\n\n async listVersions(sessionId, artifactName) {\n const headers = await getHeaders();\n const url = `${artifactBaseUrl(sessionId)}/${encodeURIComponent(artifactName)}/versions`;\n const res = await fetch(url, { headers });\n if (!res.ok) {\n throw new Error(`Failed to list artifact versions: ${res.status}`);\n }\n return parseAdkArtifactVersionsResponse(await res.json());\n },\n\n async delete(sessionId, artifactName) {\n const headers = await getHeaders();\n const url = `${artifactBaseUrl(sessionId)}/${encodeURIComponent(artifactName)}`;\n const res = await fetch(url, { method: \"DELETE\", headers });\n if (!res.ok && res.status !== 404) {\n throw new Error(`Failed to delete artifact: ${res.status}`);\n }\n },\n };\n\n return { adapter, load, artifacts };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AdkSessionAdapter.js","names":[],"sources":["../src/AdkSessionAdapter.ts"],"sourcesContent":["import type { AssistantStream, AssistantStreamChunk } from \"assistant-stream\";\nimport type {\n RemoteThreadInitializeResponse,\n RemoteThreadListAdapter,\n RemoteThreadListResponse,\n RemoteThreadMetadata,\n} from \"@assistant-ui/core\";\nimport { AdkEventAccumulator } from \"./AdkEventAccumulator\";\nimport { normalizeAdkPart } from \"./normalizeAdkPart\";\nimport { parseAdkEventValue } from \"./parseAdkEvent\";\nimport type { AdkMessage, AdkThreadSnapshot } from \"./types\";\nimport { trimTrailingSlashes } from \"./trimTrailingSlashes\";\nimport { raceWithAbortSignal } from \"./raceWithAbortSignal\";\n\nexport type AdkSessionAdapterOptions = {\n /**\n * ADK server base URL (e.g. \"http://localhost:8000\").\n */\n apiUrl: string;\n\n /**\n * ADK application name.\n */\n appName: string;\n\n /**\n * ADK user ID.\n */\n userId: string;\n\n /**\n * Extra headers for API requests.\n */\n headers?:\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>)\n | undefined;\n};\n\nexport type AdkArtifactData = {\n inlineData?: { mimeType: string; data: string } | undefined;\n fileData?: { fileUri: string; mimeType?: string | undefined } | undefined;\n text?: string | undefined;\n};\n\ntype AdkSessionAdapterResult = {\n adapter: RemoteThreadListAdapter;\n load: (\n sessionId: string,\n options?: { signal?: AbortSignal | undefined },\n ) => Promise<AdkThreadSnapshot>;\n artifacts: {\n list: (sessionId: string) => Promise<string[]>;\n load: (\n sessionId: string,\n artifactName: string,\n version?: number,\n ) => Promise<AdkArtifactData>;\n listVersions: (\n sessionId: string,\n artifactName: string,\n ) => Promise<number[]>;\n delete: (sessionId: string, artifactName: string) => Promise<void>;\n };\n};\n\ntype AdkSessionResponse = {\n id: string;\n events?: unknown;\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst isAdkSessionResponse = (value: unknown): value is AdkSessionResponse => {\n if (!isRecord(value)) return false;\n\n const id = value.id;\n return typeof id === \"string\" && id.length > 0;\n};\n\nconst parseAdkSessionResponse = (\n value: unknown,\n operation: \"create\" | \"fetch\" | \"load\",\n): AdkSessionResponse => {\n if (!isAdkSessionResponse(value)) {\n throw new Error(\n `Invalid ADK session ${operation} response: expected an object with a non-empty string \"id\".`,\n );\n }\n return value;\n};\n\nconst parseAdkSessionListResponse = (value: unknown): AdkSessionResponse[] => {\n if (!Array.isArray(value)) {\n throw new Error(\n \"Invalid ADK session list response: expected an array of sessions.\",\n );\n }\n\n return value.map((session, index) => {\n if (!isAdkSessionResponse(session)) {\n throw new Error(\n `Invalid ADK session list response: session at index ${index} must have a non-empty string \"id\".`,\n );\n }\n return session;\n });\n};\n\nconst parseAdkArtifactListResponse = (value: unknown): string[] => {\n if (!Array.isArray(value)) {\n throw new Error(\n \"Invalid ADK artifact list response: expected an array of artifact names.\",\n );\n }\n\n return value.map((artifact, index) => {\n if (typeof artifact === \"string\" && artifact.length > 0) {\n return artifact;\n }\n\n if (isRecord(artifact)) {\n const filename = artifact.filename;\n if (typeof filename === \"string\" && filename.length > 0) {\n return filename;\n }\n }\n\n throw new Error(\n `Invalid ADK artifact list response: artifact at index ${index} must be a non-empty string or an object with a non-empty string \"filename\".`,\n );\n });\n};\n\nconst parseAdkArtifactResponse = (value: unknown): AdkArtifactData => {\n if (!isRecord(value)) {\n throw new Error(\n 'Invalid ADK artifact load response: expected an object containing \"text\", \"inlineData\", or \"fileData\".',\n );\n }\n\n const normalizedValue = normalizeAdkPart(value);\n const { text, inlineData, fileData } = normalizedValue;\n if (\n text === undefined &&\n inlineData === undefined &&\n fileData === undefined\n ) {\n throw new Error(\n 'Invalid ADK artifact load response: expected an object containing \"text\", \"inlineData\", or \"fileData\".',\n );\n }\n\n if (text !== undefined && typeof text !== \"string\") {\n throw new Error(\n 'Invalid ADK artifact load response: \"text\" must be a string when present.',\n );\n }\n\n if (\n inlineData !== undefined &&\n (!isRecord(inlineData) ||\n typeof inlineData.mimeType !== \"string\" ||\n typeof inlineData.data !== \"string\")\n ) {\n throw new Error(\n 'Invalid ADK artifact load response: \"inlineData\" must contain string \"mimeType\" and \"data\" fields.',\n );\n }\n\n if (\n fileData !== undefined &&\n (!isRecord(fileData) ||\n typeof fileData.fileUri !== \"string\" ||\n (fileData.mimeType !== undefined &&\n typeof fileData.mimeType !== \"string\"))\n ) {\n throw new Error(\n 'Invalid ADK artifact load response: \"fileData\" must contain a string \"fileUri\" and an optional string \"mimeType\" field.',\n );\n }\n\n return normalizedValue as AdkArtifactData;\n};\n\nconst parseAdkArtifactVersionsResponse = (value: unknown): number[] => {\n if (!Array.isArray(value)) {\n throw new Error(\n \"Invalid ADK artifact versions response: expected an array of version numbers.\",\n );\n }\n\n return value.map((version, index) => {\n if (\n typeof version !== \"number\" ||\n !Number.isInteger(version) ||\n version < 0\n ) {\n throw new Error(\n `Invalid ADK artifact versions response: version at index ${index} must be a non-negative integer.`,\n );\n }\n return version;\n });\n};\n\n/**\n * Creates a `RemoteThreadListAdapter` backed by ADK's session REST API,\n * plus a `load` function that reconstructs messages from session events.\n *\n * @example\n * ```ts\n * const { adapter, load } = createAdkSessionAdapter({\n * apiUrl: \"http://localhost:8000\",\n * appName: \"my-app\",\n * userId: \"user-1\",\n * });\n *\n * const runtime = useAdkRuntime({\n * stream: createAdkStream({ ... }),\n * sessionAdapter: adapter,\n * load,\n * });\n * ```\n */\nexport function createAdkSessionAdapter(\n options: AdkSessionAdapterOptions,\n): AdkSessionAdapterResult {\n const { apiUrl, appName, userId } = options;\n const normalizedApiUrl = trimTrailingSlashes(apiUrl);\n const baseUrl = `${normalizedApiUrl}/apps/${encodeURIComponent(appName)}/users/${encodeURIComponent(userId)}/sessions`;\n\n const getHeaders = async (\n signal?: AbortSignal,\n ): Promise<Record<string, string>> => {\n if (!options.headers) return {};\n if (typeof options.headers === \"function\") {\n return await raceWithAbortSignal(signal, options.headers);\n }\n return options.headers;\n };\n\n const adapter: RemoteThreadListAdapter = {\n async list(): Promise<RemoteThreadListResponse> {\n const headers = await getHeaders();\n const res = await fetch(baseUrl, { headers });\n if (!res.ok) {\n throw new Error(`Failed to list sessions: ${res.status}`);\n }\n const data = parseAdkSessionListResponse(await res.json());\n\n const threads: RemoteThreadMetadata[] = data.map((session) => ({\n status: \"regular\" as const,\n remoteId: session.id,\n externalId: session.id,\n title: undefined,\n }));\n\n return { threads };\n },\n\n async initialize(\n _threadId: string,\n ): Promise<RemoteThreadInitializeResponse> {\n const headers = await getHeaders();\n const res = await fetch(baseUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...headers },\n body: JSON.stringify({}),\n });\n if (!res.ok) {\n throw new Error(`Failed to create session: ${res.status}`);\n }\n const session = parseAdkSessionResponse(await res.json(), \"create\");\n return { remoteId: session.id, externalId: session.id };\n },\n\n async delete(remoteId: string): Promise<void> {\n const headers = await getHeaders();\n const res = await fetch(`${baseUrl}/${encodeURIComponent(remoteId)}`, {\n method: \"DELETE\",\n headers,\n });\n if (!res.ok && res.status !== 404) {\n throw new Error(`Failed to delete session: ${res.status}`);\n }\n },\n\n async rename(): Promise<void> {\n // ADK sessions don't support titles\n },\n\n async archive(): Promise<void> {\n // ADK sessions don't support archiving\n },\n\n async unarchive(): Promise<void> {\n // ADK sessions don't support archiving\n },\n\n generateTitle(): Promise<AssistantStream> {\n // Title generation not supported without assistant-cloud\n return Promise.resolve(\n new ReadableStream<AssistantStreamChunk>({\n start(controller) {\n controller.close();\n },\n }),\n );\n },\n\n async fetch(threadId: string): Promise<RemoteThreadMetadata> {\n const headers = await getHeaders();\n const res = await fetch(`${baseUrl}/${encodeURIComponent(threadId)}`, {\n headers,\n });\n if (!res.ok) {\n throw new Error(`Session not found: ${res.status}`);\n }\n const session = parseAdkSessionResponse(await res.json(), \"fetch\");\n return {\n status: \"regular\",\n remoteId: session.id,\n externalId: session.id,\n title: undefined,\n };\n },\n };\n\n const load = async (\n sessionId: string,\n options?: { signal?: AbortSignal | undefined },\n ): Promise<AdkThreadSnapshot> => {\n const headers = await getHeaders(options?.signal);\n const res = await fetch(`${baseUrl}/${encodeURIComponent(sessionId)}`, {\n headers,\n ...(options?.signal ? { signal: options.signal } : {}),\n });\n if (!res.ok) {\n throw new Error(`Failed to load session: ${res.status}`);\n }\n const session = parseAdkSessionResponse(await res.json(), \"load\");\n\n if (session.events !== undefined && !Array.isArray(session.events)) {\n throw new Error(\n 'Invalid ADK session load response: expected \"events\" to be an array when present.',\n );\n }\n\n // Events carry ordered state and tool transitions, so partial replay can\n // produce a plausible but incorrect thread.\n const events = session.events?.map((event, index) =>\n parseAdkEventValue(event, `Invalid ADK session event at index ${index}`),\n );\n\n if (!events?.length) {\n return { messages: [] };\n }\n\n const accumulator = new AdkEventAccumulator();\n let messages: AdkMessage[] = [];\n for (const event of events) {\n messages = accumulator.processEvent(event);\n }\n // The per-turn state rides along, so a refetch can swap the thread over in\n // one commit instead of reconstructing it from the messages alone.\n return {\n messages,\n longRunningToolIds: accumulator.getLongRunningToolIds(),\n toolConfirmations: accumulator.getToolConfirmations(),\n authRequests: accumulator.getAuthRequests(),\n escalated: accumulator.isEscalated(),\n messageMetadata: accumulator.getMessageMetadata(),\n stateDelta: accumulator.getStateDelta(),\n artifactDelta: accumulator.getArtifactDelta(),\n agentInfo: accumulator.getAgentInfo(),\n };\n };\n\n const artifactBaseUrl = (sessionId: string) =>\n `${baseUrl}/${encodeURIComponent(sessionId)}/artifacts`;\n\n const artifacts: AdkSessionAdapterResult[\"artifacts\"] = {\n async list(sessionId) {\n const headers = await getHeaders();\n const res = await fetch(artifactBaseUrl(sessionId), { headers });\n if (!res.ok) throw new Error(`Failed to list artifacts: ${res.status}`);\n return parseAdkArtifactListResponse(await res.json());\n },\n\n async load(sessionId, artifactName, version?) {\n const headers = await getHeaders();\n let url = `${artifactBaseUrl(sessionId)}/${encodeURIComponent(artifactName)}`;\n if (version != null) url += `/versions/${version}`;\n const res = await fetch(url, { headers });\n if (!res.ok) throw new Error(`Failed to load artifact: ${res.status}`);\n return parseAdkArtifactResponse(await res.json());\n },\n\n async listVersions(sessionId, artifactName) {\n const headers = await getHeaders();\n const url = `${artifactBaseUrl(sessionId)}/${encodeURIComponent(artifactName)}/versions`;\n const res = await fetch(url, { headers });\n if (!res.ok) {\n throw new Error(`Failed to list artifact versions: ${res.status}`);\n }\n return parseAdkArtifactVersionsResponse(await res.json());\n },\n\n async delete(sessionId, artifactName) {\n const headers = await getHeaders();\n const url = `${artifactBaseUrl(sessionId)}/${encodeURIComponent(artifactName)}`;\n const res = await fetch(url, { method: \"DELETE\", headers });\n if (!res.ok && res.status !== 404) {\n throw new Error(`Failed to delete artifact: ${res.status}`);\n }\n },\n };\n\n return { adapter, load, artifacts };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AdkAuthCredential, AdkAuthRequest, AdkMessage } from "./types.js";
|
|
2
|
+
export declare const ADK_REQUEST_CREDENTIAL = "adk_request_credential";
|
|
3
|
+
/**
|
|
4
|
+
* ADK binds a credential reply to the `adk_request_credential` call it issued
|
|
5
|
+
* and takes only `exchangedAuthCredential` off the response, so the reply is
|
|
6
|
+
* the request's own auth config with the credential filled in, as ADK's
|
|
7
|
+
* reference client sends it: adk-python validates the response as a whole auth
|
|
8
|
+
* config, and it exchanges an OAuth2 code with the client id, redirect uri and
|
|
9
|
+
* state the request carried, so the caller's fields land over the request's
|
|
10
|
+
* exchanged credential rather than replacing it. An id that is not a pending
|
|
11
|
+
* request would send a reply adk-js ignores and adk-python answers by
|
|
12
|
+
* requesting again, so it throws instead.
|
|
13
|
+
*/
|
|
14
|
+
export declare const toAdkAuthReply: (toolCallId: string, credential: AdkAuthCredential, requests: readonly AdkAuthRequest[]) => AdkMessage & {
|
|
15
|
+
type: "tool";
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=adkAuthRequest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adkAuthRequest.d.ts","sourceRoot":"","sources":["../src/adkAuthRequest.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,UAAU,EAAE,mBAAgB;AAE7E,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAK/D;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,GACzB,YAAY,MAAM,EAClB,YAAY,iBAAiB,EAC7B,UAAU,SAAS,cAAc,EAAE,KAClC,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAyB7B,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { isRecord } from "@assistant-ui/core/internal";
|
|
2
|
+
import { generateId } from "@assistant-ui/core";
|
|
3
|
+
//#region src/adkAuthRequest.ts
|
|
4
|
+
const ADK_REQUEST_CREDENTIAL = "adk_request_credential";
|
|
5
|
+
const recordOf = (value) => isRecord(value) ? value : {};
|
|
6
|
+
/**
|
|
7
|
+
* ADK binds a credential reply to the `adk_request_credential` call it issued
|
|
8
|
+
* and takes only `exchangedAuthCredential` off the response, so the reply is
|
|
9
|
+
* the request's own auth config with the credential filled in, as ADK's
|
|
10
|
+
* reference client sends it: adk-python validates the response as a whole auth
|
|
11
|
+
* config, and it exchanges an OAuth2 code with the client id, redirect uri and
|
|
12
|
+
* state the request carried, so the caller's fields land over the request's
|
|
13
|
+
* exchanged credential rather than replacing it. An id that is not a pending
|
|
14
|
+
* request would send a reply adk-js ignores and adk-python answers by
|
|
15
|
+
* requesting again, so it throws instead.
|
|
16
|
+
*/
|
|
17
|
+
const toAdkAuthReply = (toolCallId, credential, requests) => {
|
|
18
|
+
const request = requests.find((r) => r.toolCallId === toolCallId);
|
|
19
|
+
if (request === void 0) throw new Error(`No pending ADK auth request for tool call id "${toolCallId}"`);
|
|
20
|
+
const authConfig = recordOf(request.authConfig);
|
|
21
|
+
const requested = recordOf(authConfig.exchangedAuthCredential);
|
|
22
|
+
const oauth2 = {
|
|
23
|
+
...recordOf(requested.oauth2),
|
|
24
|
+
...credential.oauth2
|
|
25
|
+
};
|
|
26
|
+
return {
|
|
27
|
+
id: generateId(),
|
|
28
|
+
type: "tool",
|
|
29
|
+
tool_call_id: toolCallId,
|
|
30
|
+
name: ADK_REQUEST_CREDENTIAL,
|
|
31
|
+
content: JSON.stringify({
|
|
32
|
+
...authConfig,
|
|
33
|
+
exchangedAuthCredential: {
|
|
34
|
+
...requested,
|
|
35
|
+
...credential,
|
|
36
|
+
...Object.keys(oauth2).length > 0 && { oauth2 }
|
|
37
|
+
}
|
|
38
|
+
}),
|
|
39
|
+
status: "success"
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
//#endregion
|
|
43
|
+
export { ADK_REQUEST_CREDENTIAL, toAdkAuthReply };
|
|
44
|
+
|
|
45
|
+
//# sourceMappingURL=adkAuthRequest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adkAuthRequest.js","names":[],"sources":["../src/adkAuthRequest.ts"],"sourcesContent":["import { generateId } from \"@assistant-ui/core\";\nimport { isRecord } from \"@assistant-ui/core/internal\";\nimport type { AdkAuthCredential, AdkAuthRequest, AdkMessage } from \"./types\";\n\nexport const ADK_REQUEST_CREDENTIAL = \"adk_request_credential\";\n\nconst recordOf = (value: unknown): Record<string, unknown> =>\n isRecord(value) ? value : {};\n\n/**\n * ADK binds a credential reply to the `adk_request_credential` call it issued\n * and takes only `exchangedAuthCredential` off the response, so the reply is\n * the request's own auth config with the credential filled in, as ADK's\n * reference client sends it: adk-python validates the response as a whole auth\n * config, and it exchanges an OAuth2 code with the client id, redirect uri and\n * state the request carried, so the caller's fields land over the request's\n * exchanged credential rather than replacing it. An id that is not a pending\n * request would send a reply adk-js ignores and adk-python answers by\n * requesting again, so it throws instead.\n */\nexport const toAdkAuthReply = (\n toolCallId: string,\n credential: AdkAuthCredential,\n requests: readonly AdkAuthRequest[],\n): AdkMessage & { type: \"tool\" } => {\n const request = requests.find((r) => r.toolCallId === toolCallId);\n if (request === undefined)\n throw new Error(\n `No pending ADK auth request for tool call id \"${toolCallId}\"`,\n );\n\n const authConfig = recordOf(request.authConfig);\n const requested = recordOf(authConfig.exchangedAuthCredential);\n const oauth2 = { ...recordOf(requested.oauth2), ...credential.oauth2 };\n return {\n id: generateId(),\n type: \"tool\",\n tool_call_id: toolCallId,\n name: ADK_REQUEST_CREDENTIAL,\n content: JSON.stringify({\n ...authConfig,\n exchangedAuthCredential: {\n ...requested,\n ...credential,\n ...(Object.keys(oauth2).length > 0 && { oauth2 }),\n },\n }),\n status: \"success\",\n };\n};\n"],"mappings":";;;AAIA,MAAa,yBAAyB;AAEtC,MAAM,YAAY,UAChB,SAAS,KAAK,IAAI,QAAQ,CAAC;;;;;;;;;;;;AAa7B,MAAa,kBACX,YACA,YACA,aACkC;CAClC,MAAM,UAAU,SAAS,MAAM,MAAM,EAAE,eAAe,UAAU;CAChE,IAAI,YAAY,KAAA,GACd,MAAM,IAAI,MACR,iDAAiD,WAAW,EAC9D;CAEF,MAAM,aAAa,SAAS,QAAQ,UAAU;CAC9C,MAAM,YAAY,SAAS,WAAW,uBAAuB;CAC7D,MAAM,SAAS;EAAE,GAAG,SAAS,UAAU,MAAM;EAAG,GAAG,WAAW;CAAO;CACrE,OAAO;EACL,IAAI,WAAW;EACf,MAAM;EACN,cAAc;EACd,MAAM;EACN,SAAS,KAAK,UAAU;GACtB,GAAG;GACH,yBAAyB;IACvB,GAAG;IACH,GAAG;IACH,GAAI,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,KAAK,EAAE,OAAO;GACjD;EACF,CAAC;EACD,QAAQ;CACV;AACF"}
|
package/dist/adkExtras.d.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { AdkRuntimeExtras } from "./types.js";
|
|
2
|
-
|
|
3
|
-
declare const adkExtras: import("@assistant-ui/core/react").RuntimeExtras<AdkRuntimeExtras>;
|
|
4
|
-
//#endregion
|
|
5
|
-
export { adkExtras };
|
|
1
|
+
import type { AdkRuntimeExtras } from "./types.js";
|
|
2
|
+
export declare const adkExtras: import("@assistant-ui/core/react").RuntimeExtras<AdkRuntimeExtras>;
|
|
6
3
|
//# sourceMappingURL=adkExtras.d.ts.map
|
package/dist/adkExtras.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adkExtras.d.ts","
|
|
1
|
+
{"version":3,"file":"adkExtras.d.ts","sourceRoot":"","sources":["../src/adkExtras.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAgB;AAEhD,eAAO,MAAM,SAAS,oEAAyD,CAAC"}
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ReadonlyJSONValue } from "assistant-stream/utils";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
key: string;
|
|
1
|
+
import type { RespondToToolApprovalOptions, ToolCallMessagePart } from "@assistant-ui/core";
|
|
2
|
+
import type { ReadonlyJSONValue } from "assistant-stream/utils";
|
|
3
|
+
import type { AdkMessage } from "./types.js";
|
|
4
|
+
export type AdkToolApproval = NonNullable<ToolCallMessagePart["approval"]>;
|
|
5
|
+
export declare const ADK_REQUEST_CONFIRMATION = "adk_request_confirmation";
|
|
6
|
+
export type AdkToolApprovalProjection = {
|
|
7
|
+
approvals: ReadonlyMap<string, AdkToolApproval>;
|
|
8
|
+
/**
|
|
9
|
+
* Identity of the decision state. Core re-converts a cached message object
|
|
10
|
+
* only when the converter callback changes, so the callback is rebuilt when
|
|
11
|
+
* this key moves rather than on every render.
|
|
12
|
+
*/
|
|
13
|
+
key: string;
|
|
15
14
|
};
|
|
16
15
|
/**
|
|
17
16
|
* ADK requests a confirmation by emitting a synthetic `adk_request_confirmation`
|
|
@@ -23,18 +22,16 @@ type AdkToolApprovalProjection = {
|
|
|
23
22
|
* rather than left bare, which would let it answer by writing a tool result the
|
|
24
23
|
* agent never produced.
|
|
25
24
|
*/
|
|
26
|
-
declare const projectAdkToolApprovals: (messages: readonly AdkMessage[]) => AdkToolApprovalProjection;
|
|
27
|
-
declare const toAdkConfirmationReply: (toolCallId: string, confirmed: boolean, payload?: ReadonlyJSONValue) => AdkMessage & {
|
|
28
|
-
|
|
25
|
+
export declare const projectAdkToolApprovals: (messages: readonly AdkMessage[]) => AdkToolApprovalProjection;
|
|
26
|
+
export declare const toAdkConfirmationReply: (toolCallId: string, confirmed: boolean, payload?: ReadonlyJSONValue) => AdkMessage & {
|
|
27
|
+
type: "tool";
|
|
29
28
|
};
|
|
30
29
|
/**
|
|
31
30
|
* ADK confirmations are a plain confirm/reject pair, so no option or reason
|
|
32
31
|
* from core has a field to land in. An id that is not an open gate would send a
|
|
33
32
|
* reply ADK silently ignores, so it throws instead.
|
|
34
33
|
*/
|
|
35
|
-
declare const toAdkToolConfirmationReply: ({ approvalId, approved }: RespondToToolApprovalOptions, approvals: ReadonlyMap<string, AdkToolApproval>) => AdkMessage & {
|
|
36
|
-
|
|
34
|
+
export declare const toAdkToolConfirmationReply: ({ approvalId, approved }: RespondToToolApprovalOptions, approvals: ReadonlyMap<string, AdkToolApproval>) => AdkMessage & {
|
|
35
|
+
type: "tool";
|
|
37
36
|
};
|
|
38
|
-
//#endregion
|
|
39
|
-
export { ADK_REQUEST_CONFIRMATION, AdkToolApproval, AdkToolApprovalProjection, projectAdkToolApprovals, toAdkConfirmationReply, toAdkToolConfirmationReply };
|
|
40
37
|
//# sourceMappingURL=adkToolApproval.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adkToolApproval.d.ts","
|
|
1
|
+
{"version":3,"file":"adkToolApproval.d.ts","sourceRoot":"","sources":["../src/adkToolApproval.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,4BAA4B,EAC5B,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAgB;AAE1C,MAAM,MAAM,eAAe,GAAG,WAAW,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC,CAAC;AAE3E,eAAO,MAAM,wBAAwB,6BAA6B,CAAC;AA2FnE,MAAM,MAAM,yBAAyB,GAAG;IACtC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAChD;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,GAClC,UAAU,SAAS,UAAU,EAAE,KAC9B,yBAuDF,CAAC;AAEF,eAAO,MAAM,sBAAsB,GACjC,YAAY,MAAM,EAClB,WAAW,OAAO,EAClB,UAAU,iBAAiB,KAC1B,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAU5B,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,GACrC,0BAA0B,4BAA4B,EACtD,WAAW,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC,KAC9C,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAQ7B,CAAC"}
|
package/dist/adkToolApproval.js
CHANGED
|
@@ -76,9 +76,7 @@ const readConfirmation = (content) => {
|
|
|
76
76
|
*/
|
|
77
77
|
const sourceEventOf = (toolMessageId) => toolMessageId.replace(/:\d+$/, "");
|
|
78
78
|
/**
|
|
79
|
-
* ADK builds the confirmation request around the call it gates, carrying that
|
|
80
|
-
* call verbatim in `originalFunctionCall` — spelled `original_function_call` by
|
|
81
|
-
* ADK Python, which the accumulator reads the same way.
|
|
79
|
+
* ADK builds the confirmation request around the call it gates, carrying that call verbatim in `originalFunctionCall`; `original_function_call` is accepted as well, matching the accumulator.
|
|
82
80
|
*/
|
|
83
81
|
const gatedCallIdOf = (args) => {
|
|
84
82
|
if (typeof args !== "object" || args === null) return void 0;
|