@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":"adkToolApproval.js","names":[],"sources":["../src/adkToolApproval.ts"],"sourcesContent":["import { generateId } from \"@assistant-ui/core\";\nimport type {\n RespondToToolApprovalOptions,\n ToolCallMessagePart,\n} from \"@assistant-ui/core\";\nimport type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport type { AdkMessage } from \"./types\";\n\nexport type AdkToolApproval = NonNullable<ToolCallMessagePart[\"approval\"]>;\n\nexport const ADK_REQUEST_CONFIRMATION = \"adk_request_confirmation\";\n\nconst parseJson = (raw: string): unknown => {\n try {\n return JSON.parse(raw);\n } catch {\n return undefined;\n }\n};\n\ntype AdkConfirmationRead = {\n /**\n * False only where ADK raises reading the reply, which aborts every function\n * response in the same event rather than denying this one.\n */\n readable: boolean;\n /** Undefined where ADK records no confirmation and the gate stays open. */\n confirmed: boolean | undefined;\n};\n\n/**\n * The value the transport puts on `functionResponse.response`: the reply\n * content parsed, or the raw text where it is not JSON.\n */\nconst wireResponseOf = (content: string): unknown => {\n const parsed = parseJson(content);\n return parsed === undefined ? content : parsed;\n};\n\n/**\n * Mirrors ADK's own reading of a confirmation reply, whose three outcomes the\n * gate has to distinguish. A falsy response records nothing, so the gate stays\n * open and its siblings are untouched. Otherwise ADK either unwraps its client\n * wrapper — a lone `response` key whose value it parses as JSON text — or reads\n * `confirmed` off the response directly, and resumes the tool unconfirmed\n * (a denial) for anything that is not explicitly `true`; a bare string, number,\n * or array is such a denial, not an unreadable reply. Only where that reading\n * raises is the reply unreadable, and the raise is uncaught in ADK, so the\n * whole event it belongs to is abandoned.\n */\nconst readConfirmation = (content: unknown): AdkConfirmationRead => {\n if (typeof content !== \"string\")\n return { readable: false, confirmed: undefined };\n const response = wireResponseOf(content);\n try {\n if (!response) return { readable: true, confirmed: undefined };\n const record = response as Record<string, unknown>;\n const decide = (value: unknown) =>\n typeof value === \"object\" &&\n value !== null &&\n (value as { confirmed?: unknown }).confirmed === true;\n // `in` raises on a primitive response, as ADK's own wrapper test does.\n if (Object.keys(record).length === 1 && \"response\" in record) {\n const inner = parseJson(String(record.response));\n // ADK parses the wrapped text without a `try`, so it raises here.\n if (inner === undefined) return { readable: false, confirmed: undefined };\n if (!inner) return { readable: true, confirmed: undefined };\n return { readable: true, confirmed: decide(inner) };\n }\n return { readable: true, confirmed: decide(record) };\n } catch {\n return { readable: false, confirmed: undefined };\n }\n};\n\n/**\n * ADK's confirmation processor parses every function response in an event\n * before running any tool, so one unreadable reply aborts the event and none of\n * its siblings execute. The accumulator mints a tool message id of\n * `<eventId>:<partIndex>` per response, so that prefix is the batch ADK either\n * runs whole or not at all; a locally minted reply carries a bare uuid and is\n * its own batch.\n */\nconst sourceEventOf = (toolMessageId: string): string =>\n toolMessageId.replace(/:\\d+$/, \"\");\n\n/**\n * ADK builds the confirmation request around the call it gates, carrying that\n * call verbatim in `originalFunctionCall` — spelled `original_function_call` by\n * ADK Python, which the accumulator reads the same way.\n */\nconst gatedCallIdOf = (args: unknown): string | undefined => {\n if (typeof args !== \"object\" || args === null) return undefined;\n const record = args as {\n originalFunctionCall?: unknown;\n original_function_call?: unknown;\n };\n const original = record.originalFunctionCall ?? record.original_function_call;\n if (typeof original !== \"object\" || original === null) return undefined;\n const id = (original as { id?: unknown }).id;\n return typeof id === \"string\" && id.length > 0 ? id : undefined;\n};\n\nexport type AdkToolApprovalProjection = {\n approvals: ReadonlyMap<string, AdkToolApproval>;\n /**\n * Identity of the decision state. Core re-converts a cached message object\n * only when the converter callback changes, so the callback is rebuilt when\n * this key moves rather than on every render.\n */\n key: string;\n};\n\n/**\n * ADK requests a confirmation by emitting a synthetic `adk_request_confirmation`\n * tool call carrying a fresh id, and resumes only when a reply quotes that id.\n * The gated tool's own id is never answerable, so every approval carries the\n * synthetic id — but ADK yields the gated call to the client first, in its own\n * event, so both calls sit result-less in the transcript and both would render\n * an approval control. The gated call is therefore mapped to the same approval\n * rather than left bare, which would let it answer by writing a tool result the\n * agent never produced.\n */\nexport const projectAdkToolApprovals = (\n messages: readonly AdkMessage[],\n): AdkToolApprovalProjection => {\n const batches = new Map<\n string,\n { readable: boolean; entries: [string, boolean | undefined][] }\n >();\n for (const message of messages) {\n if (message.type !== \"tool\") continue;\n if (message.name !== ADK_REQUEST_CONFIRMATION) continue;\n const key = sourceEventOf(message.id);\n let batch = batches.get(key);\n if (batch === undefined) {\n batch = { readable: true, entries: [] };\n batches.set(key, batch);\n }\n const { readable, confirmed } = readConfirmation(message.content);\n if (!readable) batch.readable = false;\n batch.entries.push([message.tool_call_id, confirmed]);\n }\n\n const replies = new Map<string, boolean>();\n for (const batch of batches.values()) {\n for (const [toolCallId, confirmed] of batch.entries) {\n if (batch.readable && confirmed !== undefined)\n replies.set(toolCallId, confirmed);\n else replies.delete(toolCallId);\n }\n }\n\n const approvals = new Map<string, AdkToolApproval>();\n for (const message of messages) {\n if (message.type !== \"ai\") continue;\n for (const call of message.tool_calls ?? []) {\n if (call.name !== ADK_REQUEST_CONFIRMATION) continue;\n const approved = replies.get(call.id);\n const approval: AdkToolApproval = {\n id: call.id,\n ...(approved !== undefined && { approved }),\n };\n approvals.set(call.id, approval);\n // ADK yields the gated call in its own event before the confirmation is\n // requested, so that call is also in the transcript, result-less, and\n // inherits the message's `requires-action` status. Left ungated it\n // renders a second approval control with no approval behind it, which\n // answers by writing a tool result the agent never produced. The same\n // approval carries the synthetic id, so answering either one replies to\n // the gate ADK is actually waiting on.\n const gatedId = gatedCallIdOf(call.args);\n if (gatedId !== undefined) approvals.set(gatedId, approval);\n }\n }\n\n return {\n approvals,\n key: approvals.size === 0 ? \"\" : JSON.stringify([...approvals]),\n };\n};\n\nexport const toAdkConfirmationReply = (\n toolCallId: string,\n confirmed: boolean,\n payload?: ReadonlyJSONValue,\n): AdkMessage & { type: \"tool\" } => ({\n id: generateId(),\n type: \"tool\",\n tool_call_id: toolCallId,\n name: ADK_REQUEST_CONFIRMATION,\n content: JSON.stringify({\n confirmed,\n ...(payload != null && { payload }),\n }),\n status: \"success\",\n});\n\n/**\n * ADK confirmations are a plain confirm/reject pair, so no option or reason\n * from core has a field to land in. An id that is not an open gate would send a\n * reply ADK silently ignores, so it throws instead.\n */\nexport const toAdkToolConfirmationReply = (\n { approvalId, approved }: RespondToToolApprovalOptions,\n approvals: ReadonlyMap<string, AdkToolApproval>,\n): AdkMessage & { type: \"tool\" } => {\n const approval = approvals.get(approvalId);\n if (approval === undefined || approval.approved !== undefined)\n throw new Error(\n `No pending ADK tool confirmation for approval id \"${approvalId}\"`,\n );\n\n return toAdkConfirmationReply(approvalId, approved);\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"adkToolApproval.js","names":[],"sources":["../src/adkToolApproval.ts"],"sourcesContent":["import { generateId } from \"@assistant-ui/core\";\nimport type {\n RespondToToolApprovalOptions,\n ToolCallMessagePart,\n} from \"@assistant-ui/core\";\nimport type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport type { AdkMessage } from \"./types\";\n\nexport type AdkToolApproval = NonNullable<ToolCallMessagePart[\"approval\"]>;\n\nexport const ADK_REQUEST_CONFIRMATION = \"adk_request_confirmation\";\n\nconst parseJson = (raw: string): unknown => {\n try {\n return JSON.parse(raw);\n } catch {\n return undefined;\n }\n};\n\ntype AdkConfirmationRead = {\n /**\n * False only where ADK raises reading the reply, which aborts every function\n * response in the same event rather than denying this one.\n */\n readable: boolean;\n /** Undefined where ADK records no confirmation and the gate stays open. */\n confirmed: boolean | undefined;\n};\n\n/**\n * The value the transport puts on `functionResponse.response`: the reply\n * content parsed, or the raw text where it is not JSON.\n */\nconst wireResponseOf = (content: string): unknown => {\n const parsed = parseJson(content);\n return parsed === undefined ? content : parsed;\n};\n\n/**\n * Mirrors ADK's own reading of a confirmation reply, whose three outcomes the\n * gate has to distinguish. A falsy response records nothing, so the gate stays\n * open and its siblings are untouched. Otherwise ADK either unwraps its client\n * wrapper — a lone `response` key whose value it parses as JSON text — or reads\n * `confirmed` off the response directly, and resumes the tool unconfirmed\n * (a denial) for anything that is not explicitly `true`; a bare string, number,\n * or array is such a denial, not an unreadable reply. Only where that reading\n * raises is the reply unreadable, and the raise is uncaught in ADK, so the\n * whole event it belongs to is abandoned.\n */\nconst readConfirmation = (content: unknown): AdkConfirmationRead => {\n if (typeof content !== \"string\")\n return { readable: false, confirmed: undefined };\n const response = wireResponseOf(content);\n try {\n if (!response) return { readable: true, confirmed: undefined };\n const record = response as Record<string, unknown>;\n const decide = (value: unknown) =>\n typeof value === \"object\" &&\n value !== null &&\n (value as { confirmed?: unknown }).confirmed === true;\n // `in` raises on a primitive response, as ADK's own wrapper test does.\n if (Object.keys(record).length === 1 && \"response\" in record) {\n const inner = parseJson(String(record.response));\n // ADK parses the wrapped text without a `try`, so it raises here.\n if (inner === undefined) return { readable: false, confirmed: undefined };\n if (!inner) return { readable: true, confirmed: undefined };\n return { readable: true, confirmed: decide(inner) };\n }\n return { readable: true, confirmed: decide(record) };\n } catch {\n return { readable: false, confirmed: undefined };\n }\n};\n\n/**\n * ADK's confirmation processor parses every function response in an event\n * before running any tool, so one unreadable reply aborts the event and none of\n * its siblings execute. The accumulator mints a tool message id of\n * `<eventId>:<partIndex>` per response, so that prefix is the batch ADK either\n * runs whole or not at all; a locally minted reply carries a bare uuid and is\n * its own batch.\n */\nconst sourceEventOf = (toolMessageId: string): string =>\n toolMessageId.replace(/:\\d+$/, \"\");\n\n/**\n * 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.\n */\nconst gatedCallIdOf = (args: unknown): string | undefined => {\n if (typeof args !== \"object\" || args === null) return undefined;\n const record = args as {\n originalFunctionCall?: unknown;\n original_function_call?: unknown;\n };\n const original = record.originalFunctionCall ?? record.original_function_call;\n if (typeof original !== \"object\" || original === null) return undefined;\n const id = (original as { id?: unknown }).id;\n return typeof id === \"string\" && id.length > 0 ? id : undefined;\n};\n\nexport type AdkToolApprovalProjection = {\n approvals: ReadonlyMap<string, AdkToolApproval>;\n /**\n * Identity of the decision state. Core re-converts a cached message object\n * only when the converter callback changes, so the callback is rebuilt when\n * this key moves rather than on every render.\n */\n key: string;\n};\n\n/**\n * ADK requests a confirmation by emitting a synthetic `adk_request_confirmation`\n * tool call carrying a fresh id, and resumes only when a reply quotes that id.\n * The gated tool's own id is never answerable, so every approval carries the\n * synthetic id — but ADK yields the gated call to the client first, in its own\n * event, so both calls sit result-less in the transcript and both would render\n * an approval control. The gated call is therefore mapped to the same approval\n * rather than left bare, which would let it answer by writing a tool result the\n * agent never produced.\n */\nexport const projectAdkToolApprovals = (\n messages: readonly AdkMessage[],\n): AdkToolApprovalProjection => {\n const batches = new Map<\n string,\n { readable: boolean; entries: [string, boolean | undefined][] }\n >();\n for (const message of messages) {\n if (message.type !== \"tool\") continue;\n if (message.name !== ADK_REQUEST_CONFIRMATION) continue;\n const key = sourceEventOf(message.id);\n let batch = batches.get(key);\n if (batch === undefined) {\n batch = { readable: true, entries: [] };\n batches.set(key, batch);\n }\n const { readable, confirmed } = readConfirmation(message.content);\n if (!readable) batch.readable = false;\n batch.entries.push([message.tool_call_id, confirmed]);\n }\n\n const replies = new Map<string, boolean>();\n for (const batch of batches.values()) {\n for (const [toolCallId, confirmed] of batch.entries) {\n if (batch.readable && confirmed !== undefined)\n replies.set(toolCallId, confirmed);\n else replies.delete(toolCallId);\n }\n }\n\n const approvals = new Map<string, AdkToolApproval>();\n for (const message of messages) {\n if (message.type !== \"ai\") continue;\n for (const call of message.tool_calls ?? []) {\n if (call.name !== ADK_REQUEST_CONFIRMATION) continue;\n const approved = replies.get(call.id);\n const approval: AdkToolApproval = {\n id: call.id,\n ...(approved !== undefined && { approved }),\n };\n approvals.set(call.id, approval);\n // ADK yields the gated call in its own event before the confirmation is\n // requested, so that call is also in the transcript, result-less, and\n // inherits the message's `requires-action` status. Left ungated it\n // renders a second approval control with no approval behind it, which\n // answers by writing a tool result the agent never produced. The same\n // approval carries the synthetic id, so answering either one replies to\n // the gate ADK is actually waiting on.\n const gatedId = gatedCallIdOf(call.args);\n if (gatedId !== undefined) approvals.set(gatedId, approval);\n }\n }\n\n return {\n approvals,\n key: approvals.size === 0 ? \"\" : JSON.stringify([...approvals]),\n };\n};\n\nexport const toAdkConfirmationReply = (\n toolCallId: string,\n confirmed: boolean,\n payload?: ReadonlyJSONValue,\n): AdkMessage & { type: \"tool\" } => ({\n id: generateId(),\n type: \"tool\",\n tool_call_id: toolCallId,\n name: ADK_REQUEST_CONFIRMATION,\n content: JSON.stringify({\n confirmed,\n ...(payload != null && { payload }),\n }),\n status: \"success\",\n});\n\n/**\n * ADK confirmations are a plain confirm/reject pair, so no option or reason\n * from core has a field to land in. An id that is not an open gate would send a\n * reply ADK silently ignores, so it throws instead.\n */\nexport const toAdkToolConfirmationReply = (\n { approvalId, approved }: RespondToToolApprovalOptions,\n approvals: ReadonlyMap<string, AdkToolApproval>,\n): AdkMessage & { type: \"tool\" } => {\n const approval = approvals.get(approvalId);\n if (approval === undefined || approval.approved !== undefined)\n throw new Error(\n `No pending ADK tool confirmation for approval id \"${approvalId}\"`,\n );\n\n return toAdkConfirmationReply(approvalId, approved);\n};\n"],"mappings":"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"}
|
package/dist/contentToParts.d.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { AdkEventPart, AdkMessage } from "./types.js";
|
|
2
|
-
|
|
3
|
-
declare const contentToParts: (content: AdkMessage["content"]) => AdkEventPart[];
|
|
4
|
-
//#endregion
|
|
5
|
-
export { contentToParts };
|
|
1
|
+
import type { AdkEventPart, AdkMessage } from "./types.js";
|
|
2
|
+
export declare const contentToParts: (content: AdkMessage["content"]) => AdkEventPart[];
|
|
6
3
|
//# sourceMappingURL=contentToParts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contentToParts.d.ts","
|
|
1
|
+
{"version":3,"file":"contentToParts.d.ts","sourceRoot":"","sources":["../src/contentToParts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAyB,mBAAgB;AAE/E,eAAO,MAAM,cAAc,GACzB,SAAS,UAAU,CAAC,SAAS,CAAC,KAC7B,YAAY,EAiCd,CAAC"}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { AdkToolApproval } from "./adkToolApproval.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
declare const
|
|
6
|
-
declare const convertAdkMessage: useExternalMessageConverter.Callback<AdkMessage>;
|
|
7
|
-
//#endregion
|
|
8
|
-
export { convertAdkMessage, createAdkMessageConverter };
|
|
1
|
+
import type { useExternalMessageConverter } from "@assistant-ui/core/react";
|
|
2
|
+
import { type AdkToolApproval } from "./adkToolApproval.js";
|
|
3
|
+
import type { AdkMessage } from "./types.js";
|
|
4
|
+
export declare const createAdkMessageConverter: (approvals: ReadonlyMap<string, AdkToolApproval>) => useExternalMessageConverter.Callback<AdkMessage>;
|
|
5
|
+
export declare const convertAdkMessage: useExternalMessageConverter.Callback<AdkMessage>;
|
|
9
6
|
//# sourceMappingURL=convertAdkMessages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convertAdkMessages.d.ts","
|
|
1
|
+
{"version":3,"file":"convertAdkMessages.d.ts","sourceRoot":"","sources":["../src/convertAdkMessages.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EAEL,KAAK,eAAe,EACrB,6BAA0B;AAC3B,OAAO,KAAK,EAAE,UAAU,EAAyB,mBAAgB;AA4FjE,eAAO,MAAM,yBAAyB,GAElC,WAAW,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC,KAC9C,2BAA2B,CAAC,QAAQ,CAAC,UAAU,CAgEjD,CAAC;AAEJ,eAAO,MAAM,iBAAiB,EAAE,2BAA2B,CAAC,QAAQ,CAAC,UAAU,CACnC,CAAC"}
|
|
@@ -6,15 +6,16 @@ const contentToParts = (content, role) => {
|
|
|
6
6
|
type: "text",
|
|
7
7
|
text: content
|
|
8
8
|
}];
|
|
9
|
-
|
|
9
|
+
if (!Array.isArray(content)) return [];
|
|
10
|
+
return content.filter((part) => typeof part === "object" && part !== null).map((part) => {
|
|
10
11
|
switch (part.type) {
|
|
11
12
|
case "text": return {
|
|
12
13
|
type: "text",
|
|
13
|
-
text: part.text
|
|
14
|
+
text: typeof part.text === "string" ? part.text : ""
|
|
14
15
|
};
|
|
15
16
|
case "reasoning": return {
|
|
16
17
|
type: "reasoning",
|
|
17
|
-
text: part.text
|
|
18
|
+
text: typeof part.text === "string" ? part.text : ""
|
|
18
19
|
};
|
|
19
20
|
case "image": return {
|
|
20
21
|
type: "image",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convertAdkMessages.js","names":[],"sources":["../src/convertAdkMessages.ts"],"sourcesContent":["\"use client\";\n\nimport type { ToolCallMessagePart } from \"@assistant-ui/core\";\nimport type { useExternalMessageConverter } from \"@assistant-ui/core/react\";\nimport {\n ADK_REQUEST_CONFIRMATION,\n type AdkToolApproval,\n} from \"./adkToolApproval\";\nimport type { AdkMessage, AdkMessageContentPart } from \"./types\";\n\ntype ContentPart =\n | { type: \"text\"; text: string }\n | { type: \"reasoning\"; text: string }\n | { type: \"image\"; image: string }\n | {\n type: \"file\";\n data: string;\n mimeType: string;\n filename?: string;\n sourceType?: \"url\";\n }\n | { type: \"data\"; name: string; data: unknown };\n\nconst contentToParts = (\n content: AdkMessage[\"content\"],\n role: \"user\" | \"assistant\",\n): ContentPart[] => {\n if (typeof content === \"string\")\n return [{ type: \"text\" as const, text: content }];\n\n return (
|
|
1
|
+
{"version":3,"file":"convertAdkMessages.js","names":[],"sources":["../src/convertAdkMessages.ts"],"sourcesContent":["\"use client\";\n\nimport type { ToolCallMessagePart } from \"@assistant-ui/core\";\nimport type { useExternalMessageConverter } from \"@assistant-ui/core/react\";\nimport {\n ADK_REQUEST_CONFIRMATION,\n type AdkToolApproval,\n} from \"./adkToolApproval\";\nimport type { AdkMessage, AdkMessageContentPart } from \"./types\";\n\ntype ContentPart =\n | { type: \"text\"; text: string }\n | { type: \"reasoning\"; text: string }\n | { type: \"image\"; image: string }\n | {\n type: \"file\";\n data: string;\n mimeType: string;\n filename?: string;\n sourceType?: \"url\";\n }\n | { type: \"data\"; name: string; data: unknown };\n\nconst contentToParts = (\n content: AdkMessage[\"content\"],\n role: \"user\" | \"assistant\",\n): ContentPart[] => {\n if (typeof content === \"string\")\n return [{ type: \"text\" as const, text: content }];\n if (!Array.isArray(content)) return [];\n\n return content\n .filter(\n (part): part is AdkMessageContentPart =>\n typeof part === \"object\" && part !== null,\n )\n .map((part): ContentPart | null => {\n switch (part.type) {\n case \"text\":\n return {\n type: \"text\",\n text: typeof part.text === \"string\" ? part.text : \"\",\n };\n case \"reasoning\":\n return {\n type: \"reasoning\",\n text: typeof part.text === \"string\" ? part.text : \"\",\n };\n case \"image\":\n return {\n type: \"image\",\n image: `data:${part.mimeType};base64,${part.data}`,\n };\n case \"image_url\":\n return { type: \"image\", image: part.url };\n case \"file\":\n return {\n type: \"file\",\n data: part.data,\n mimeType: part.mimeType,\n ...(part.filename != null && { filename: part.filename }),\n };\n case \"file_url\":\n if (role === \"user\") {\n return {\n type: \"file\",\n data: part.url,\n mimeType: part.mimeType ?? \"application/octet-stream\",\n sourceType: \"url\",\n };\n }\n return {\n type: \"data\",\n name: \"file_url\",\n data: {\n url: part.url,\n ...(part.mimeType != null && { mimeType: part.mimeType }),\n },\n };\n case \"code\":\n return {\n type: \"data\",\n name: \"executable_code\",\n data: { code: part.code, language: part.language },\n };\n case \"code_result\":\n return {\n type: \"data\",\n name: \"code_execution_result\",\n data: { output: part.output, outcome: part.outcome },\n };\n default:\n return null;\n }\n })\n .filter((p): p is NonNullable<typeof p> => p !== null);\n};\n\nconst EMPTY_APPROVALS: ReadonlyMap<string, AdkToolApproval> = new Map();\n\nexport const createAdkMessageConverter =\n (\n approvals: ReadonlyMap<string, AdkToolApproval>,\n ): useExternalMessageConverter.Callback<AdkMessage> =>\n (message) => {\n switch (message.type) {\n case \"human\":\n return {\n role: \"user\",\n id: message.id,\n content: contentToParts(message.content, \"user\"),\n };\n\n case \"ai\": {\n const toolCallParts: ToolCallMessagePart[] =\n message.tool_calls?.map((tc) => {\n const approval = approvals.get(tc.id);\n return {\n type: \"tool-call\",\n toolCallId: tc.id,\n toolName: tc.name,\n args: tc.args,\n argsText: tc.argsText ?? JSON.stringify(tc.args),\n ...(approval && { approval }),\n };\n }) ?? [];\n\n return {\n role: \"assistant\",\n id: message.id,\n content: [\n ...contentToParts(message.content, \"assistant\"),\n ...toolCallParts,\n ],\n ...(message.status && { status: message.status }),\n ...(message.author && {\n metadata: {\n custom: { author: message.author, branch: message.branch },\n },\n }),\n };\n }\n\n case \"tool\": {\n // A confirmation reply ADK could not read leaves its gate undecided.\n // The reply is not the agent's output, so it is dropped rather than\n // shown as the call's result while the gate waits to be answered again.\n // Only a reply to the confirmation itself is dropped: the gated call\n // carries the same approval, and its own result is the agent's real\n // output.\n const approval = approvals.get(message.tool_call_id);\n if (\n message.name === ADK_REQUEST_CONFIRMATION &&\n approval !== undefined &&\n approval.approved === undefined\n )\n return [];\n\n return {\n role: \"tool\",\n toolCallId: message.tool_call_id,\n toolName: message.name,\n result: message.content,\n isError: message.status === \"error\",\n };\n }\n }\n };\n\nexport const convertAdkMessage: useExternalMessageConverter.Callback<AdkMessage> =\n createAdkMessageConverter(EMPTY_APPROVALS);\n"],"mappings":";;;AAuBA,MAAM,kBACJ,SACA,SACkB;CAClB,IAAI,OAAO,YAAY,UACrB,OAAO,CAAC;EAAE,MAAM;EAAiB,MAAM;CAAQ,CAAC;CAClD,IAAI,CAAC,MAAM,QAAQ,OAAO,GAAG,OAAO,CAAC;CAErC,OAAO,QACJ,QACE,SACC,OAAO,SAAS,YAAY,SAAS,IACzC,CAAC,CACA,KAAK,SAA6B;EACjC,QAAQ,KAAK,MAAb;GACE,KAAK,QACH,OAAO;IACL,MAAM;IACN,MAAM,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO;GACpD;GACF,KAAK,aACH,OAAO;IACL,MAAM;IACN,MAAM,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO;GACpD;GACF,KAAK,SACH,OAAO;IACL,MAAM;IACN,OAAO,QAAQ,KAAK,SAAS,UAAU,KAAK;GAC9C;GACF,KAAK,aACH,OAAO;IAAE,MAAM;IAAS,OAAO,KAAK;GAAI;GAC1C,KAAK,QACH,OAAO;IACL,MAAM;IACN,MAAM,KAAK;IACX,UAAU,KAAK;IACf,GAAI,KAAK,YAAY,QAAQ,EAAE,UAAU,KAAK,SAAS;GACzD;GACF,KAAK;IACH,IAAI,SAAS,QACX,OAAO;KACL,MAAM;KACN,MAAM,KAAK;KACX,UAAU,KAAK,YAAY;KAC3B,YAAY;IACd;IAEF,OAAO;KACL,MAAM;KACN,MAAM;KACN,MAAM;MACJ,KAAK,KAAK;MACV,GAAI,KAAK,YAAY,QAAQ,EAAE,UAAU,KAAK,SAAS;KACzD;IACF;GACF,KAAK,QACH,OAAO;IACL,MAAM;IACN,MAAM;IACN,MAAM;KAAE,MAAM,KAAK;KAAM,UAAU,KAAK;IAAS;GACnD;GACF,KAAK,eACH,OAAO;IACL,MAAM;IACN,MAAM;IACN,MAAM;KAAE,QAAQ,KAAK;KAAQ,SAAS,KAAK;IAAQ;GACrD;GACF,SACE,OAAO;EACX;CACF,CAAC,CAAC,CACD,QAAQ,MAAkC,MAAM,IAAI;AACzD;AAEA,MAAM,kCAAwD,IAAI,IAAI;AAEtE,MAAa,6BAET,eAED,YAAY;CACX,QAAQ,QAAQ,MAAhB;EACE,KAAK,SACH,OAAO;GACL,MAAM;GACN,IAAI,QAAQ;GACZ,SAAS,eAAe,QAAQ,SAAS,MAAM;EACjD;EAEF,KAAK,MAAM;GACT,MAAM,gBACJ,QAAQ,YAAY,KAAK,OAAO;IAC9B,MAAM,WAAW,UAAU,IAAI,GAAG,EAAE;IACpC,OAAO;KACL,MAAM;KACN,YAAY,GAAG;KACf,UAAU,GAAG;KACb,MAAM,GAAG;KACT,UAAU,GAAG,YAAY,KAAK,UAAU,GAAG,IAAI;KAC/C,GAAI,YAAY,EAAE,SAAS;IAC7B;GACF,CAAC,KAAK,CAAC;GAET,OAAO;IACL,MAAM;IACN,IAAI,QAAQ;IACZ,SAAS,CACP,GAAG,eAAe,QAAQ,SAAS,WAAW,GAC9C,GAAG,aACL;IACA,GAAI,QAAQ,UAAU,EAAE,QAAQ,QAAQ,OAAO;IAC/C,GAAI,QAAQ,UAAU,EACpB,UAAU,EACR,QAAQ;KAAE,QAAQ,QAAQ;KAAQ,QAAQ,QAAQ;IAAO,EAC3D,EACF;GACF;EACF;EAEA,KAAK,QAAQ;GAOX,MAAM,WAAW,UAAU,IAAI,QAAQ,YAAY;GACnD,IACE,QAAQ,SAAA,8BACR,aAAa,KAAA,KACb,SAAS,aAAa,KAAA,GAEtB,OAAO,CAAC;GAEV,OAAO;IACL,MAAM;IACN,YAAY,QAAQ;IACpB,UAAU,QAAQ;IAClB,QAAQ,QAAQ;IAChB,SAAS,QAAQ,WAAW;GAC9B;EACF;CACF;AACF;AAEF,MAAa,oBACX,0BAA0B,eAAe"}
|
|
@@ -1,41 +1,40 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
//#region src/convertToAdkMessages.d.ts
|
|
1
|
+
import { type AppendMessage, type ThreadMessage } from "@assistant-ui/core";
|
|
2
|
+
import type { AdkMessage } from "./types.js";
|
|
4
3
|
/** Exported for unit tests. */
|
|
5
|
-
declare const getMessageContent: (msg: AppendMessage) => string | ({
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
export declare const getMessageContent: (msg: AppendMessage) => string | ({
|
|
5
|
+
type: "text";
|
|
6
|
+
text: string;
|
|
7
|
+
mimeType?: never;
|
|
8
|
+
data?: never;
|
|
9
|
+
url?: never;
|
|
11
10
|
} | {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
type: "image";
|
|
12
|
+
mimeType: string;
|
|
13
|
+
data: string;
|
|
14
|
+
text?: never;
|
|
15
|
+
url?: never;
|
|
17
16
|
} | {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
type: "image_url";
|
|
18
|
+
url: string;
|
|
19
|
+
text?: never;
|
|
20
|
+
mimeType?: never;
|
|
21
|
+
data?: never;
|
|
23
22
|
} | {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
type: "file_url";
|
|
24
|
+
url: string;
|
|
25
|
+
mimeType: string;
|
|
26
|
+
text?: never;
|
|
27
|
+
data?: never;
|
|
29
28
|
} | {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
filename?: string;
|
|
30
|
+
type: "file";
|
|
31
|
+
mimeType: string;
|
|
32
|
+
data: string;
|
|
33
|
+
text?: never;
|
|
34
|
+
url?: never;
|
|
36
35
|
})[];
|
|
37
36
|
/** Exported for unit tests. */
|
|
38
|
-
declare const getPendingToolCalls: (messages: AdkMessage[]) => AdkToolCall[];
|
|
37
|
+
export declare const getPendingToolCalls: (messages: AdkMessage[]) => import("./types.js").AdkToolCall[];
|
|
39
38
|
/**
|
|
40
39
|
* Exported for unit tests.
|
|
41
40
|
*
|
|
@@ -45,14 +44,12 @@ declare const getPendingToolCalls: (messages: AdkMessage[]) => AdkToolCall[];
|
|
|
45
44
|
* `adk_request_credential`). Those must be answered through a dedicated tool
|
|
46
45
|
* UI + submit helper, not auto-cancelled.
|
|
47
46
|
*/
|
|
48
|
-
declare const getPendingCancellations: (messages: AdkMessage[], longRunningToolIds: readonly string[]) => Array<AdkMessage & {
|
|
49
|
-
|
|
47
|
+
export declare const getPendingCancellations: (messages: AdkMessage[], longRunningToolIds: readonly string[]) => Array<AdkMessage & {
|
|
48
|
+
type: "tool";
|
|
50
49
|
}>;
|
|
51
|
-
declare const truncateAdkMessages: (threadMessages: readonly ThreadMessage[], parentId: string | null) => AdkMessage[];
|
|
52
|
-
declare const toAdkUserMessage: (msg: AppendMessage, id?: string) => AdkMessage & {
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
export declare const truncateAdkMessages: (threadMessages: readonly ThreadMessage[], parentId: string | null) => AdkMessage[];
|
|
51
|
+
export declare const toAdkUserMessage: (msg: AppendMessage, id?: string) => AdkMessage & {
|
|
52
|
+
type: "human";
|
|
53
|
+
id: string;
|
|
55
54
|
};
|
|
56
|
-
//#endregion
|
|
57
|
-
export { getMessageContent, getPendingCancellations, getPendingToolCalls, toAdkUserMessage, truncateAdkMessages };
|
|
58
55
|
//# sourceMappingURL=convertToAdkMessages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convertToAdkMessages.d.ts","
|
|
1
|
+
{"version":3,"file":"convertToAdkMessages.d.ts","sourceRoot":"","sources":["../src/convertToAdkMessages.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAC;AAQ5B,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAgB;AAE1C,+BAA+B;AAC/B,eAAO,MAAM,iBAAiB,GAAI,KAAK,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAwEnD,CAAC;AAEF,+BAA+B;AAC/B,eAAO,MAAM,mBAAmB,GAAI,UAAU,UAAU,EAAE,uCAczD,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,GAClC,UAAU,UAAU,EAAE,EACtB,oBAAoB,SAAS,MAAM,EAAE,KACpC,KAAK,CAAC,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAWrC,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,gBAAgB,SAAS,aAAa,EAAE,EACxC,UAAU,MAAM,GAAG,IAAI,KACtB,UAAU,EASZ,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC3B,KAAK,aAAa,EAClB,WAAiB,KAChB,UAAU,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAIzC,CAAC"}
|
package/dist/hooks.d.ts
CHANGED
|
@@ -1,39 +1,41 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
//#region src/hooks.d.ts
|
|
1
|
+
import type { ReadonlyJSONValue } from "assistant-stream/utils";
|
|
2
|
+
import type { AdkMessage, AdkSendMessageConfig, AdkToolConfirmation, AdkAuthCredential, AdkAuthRequest, AdkMessageMetadata } from "./types.js";
|
|
4
3
|
/** Returns the name and branch of the currently active ADK agent. */
|
|
5
|
-
declare const useAdkAgentInfo: () => {
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
export declare const useAdkAgentInfo: () => {
|
|
5
|
+
name?: string | undefined;
|
|
6
|
+
branch?: string | undefined;
|
|
8
7
|
} | undefined;
|
|
9
8
|
/** Returns the accumulated session state delta from ADK events. */
|
|
10
|
-
declare const useAdkSessionState: () => Record<string, unknown>;
|
|
9
|
+
export declare const useAdkSessionState: () => Record<string, unknown>;
|
|
11
10
|
/** Returns a function to send raw ADK messages. */
|
|
12
|
-
declare const useAdkSend: () => (messages: AdkMessage[], config: AdkSendMessageConfig) => Promise<void>;
|
|
11
|
+
export declare const useAdkSend: () => (messages: AdkMessage[], config: AdkSendMessageConfig) => Promise<void>;
|
|
13
12
|
/** Returns the IDs of long-running tools awaiting external input. */
|
|
14
|
-
declare const useAdkLongRunningToolIds: () => string[];
|
|
13
|
+
export declare const useAdkLongRunningToolIds: () => string[];
|
|
15
14
|
/** Returns pending tool confirmation requests (from SecurityPlugin etc). */
|
|
16
|
-
declare const useAdkToolConfirmations: () => AdkToolConfirmation[];
|
|
15
|
+
export declare const useAdkToolConfirmations: () => AdkToolConfirmation[];
|
|
17
16
|
/** Returns pending auth credential requests from tools. */
|
|
18
|
-
declare const useAdkAuthRequests: () => AdkAuthRequest[];
|
|
17
|
+
export declare const useAdkAuthRequests: () => AdkAuthRequest[];
|
|
19
18
|
/** Returns the accumulated artifact delta (filename → version). */
|
|
20
|
-
declare const useAdkArtifacts: () => Record<string, number>;
|
|
19
|
+
export declare const useAdkArtifacts: () => Record<string, number>;
|
|
21
20
|
/** Returns whether any agent has escalated (requested human handoff). */
|
|
22
|
-
declare const useAdkEscalation: () => boolean;
|
|
21
|
+
export declare const useAdkEscalation: () => boolean;
|
|
23
22
|
/** Returns per-message metadata (grounding, citation, usage). Keyed by message ID. */
|
|
24
|
-
declare const useAdkMessageMetadata: () => Map<string, AdkMessageMetadata>;
|
|
23
|
+
export declare const useAdkMessageMetadata: () => Map<string, AdkMessageMetadata>;
|
|
25
24
|
/** Returns a function to confirm or deny a pending tool confirmation. */
|
|
26
|
-
declare const useAdkConfirmTool: () => (toolCallId: string, confirmed: boolean, payload?: ReadonlyJSONValue) => Promise<void>;
|
|
27
|
-
/**
|
|
28
|
-
|
|
25
|
+
export declare const useAdkConfirmTool: () => (toolCallId: string, confirmed: boolean, payload?: ReadonlyJSONValue) => Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Returns a function to submit auth credentials for a pending auth request.
|
|
28
|
+
* The reply carries the request's auth config with the credential as its
|
|
29
|
+
* `exchangedAuthCredential`, which is the shape ADK resumes the tool on, so the
|
|
30
|
+
* id must name a request `useAdkAuthRequests` currently lists.
|
|
31
|
+
*/
|
|
32
|
+
export declare const useAdkSubmitAuth: () => (toolCallId: string, credential: AdkAuthCredential) => Promise<void>;
|
|
29
33
|
/** Returns a function to submit the user's answer for a pending `adk_request_input` HITL interrupt. */
|
|
30
|
-
declare const useAdkSubmitInput: () => (toolCallId: string, result: ReadonlyJSONValue) => Promise<void>;
|
|
34
|
+
export declare const useAdkSubmitInput: () => (toolCallId: string, result: ReadonlyJSONValue) => Promise<void>;
|
|
31
35
|
/** Returns app-level state (keys prefixed with `app:`, prefix stripped). */
|
|
32
|
-
declare const useAdkAppState: () => Record<string, unknown>;
|
|
36
|
+
export declare const useAdkAppState: () => Record<string, unknown>;
|
|
33
37
|
/** Returns user-level state (keys prefixed with `user:`, prefix stripped). */
|
|
34
|
-
declare const useAdkUserState: () => Record<string, unknown>;
|
|
38
|
+
export declare const useAdkUserState: () => Record<string, unknown>;
|
|
35
39
|
/** Returns temp state (keys prefixed with `temp:`, prefix stripped). Not persisted. */
|
|
36
|
-
declare const useAdkTempState: () => Record<string, unknown>;
|
|
37
|
-
//#endregion
|
|
38
|
-
export { useAdkAgentInfo, useAdkAppState, useAdkArtifacts, useAdkAuthRequests, useAdkConfirmTool, useAdkEscalation, useAdkLongRunningToolIds, useAdkMessageMetadata, useAdkSend, useAdkSessionState, useAdkSubmitAuth, useAdkSubmitInput, useAdkTempState, useAdkToolConfirmations, useAdkUserState };
|
|
40
|
+
export declare const useAdkTempState: () => Record<string, unknown>;
|
|
39
41
|
//# sourceMappingURL=hooks.d.ts.map
|
package/dist/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAIhE,OAAO,KAAK,EACV,UAAU,EACV,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAEnB,mBAAgB;AASjB,qEAAqE;AACrE,eAAO,MAAM,eAAe;;;aACkB,CAAC;AAE/C,mEAAmE;AACnE,eAAO,MAAM,kBAAkB,+BACwB,CAAC;AAExD,mDAAmD;AACnD,eAAO,MAAM,UAAU,SAEb,UAAU,UAAU,EAAE,EAAE,QAAQ,oBAAoB,kBAE7D,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,wBAAwB,gBACoC,CAAC;AAE1E,4EAA4E;AAC5E,eAAO,MAAM,uBAAuB,6BACiC,CAAC;AAEtE,2DAA2D;AAC3D,eAAO,MAAM,kBAAkB,wBAC4B,CAAC;AAE5D,mEAAmE;AACnE,eAAO,MAAM,eAAe,8BACiC,CAAC;AAE9D,yEAAyE;AACzE,eAAO,MAAM,gBAAgB,eAAiD,CAAC;AAE/E,sFAAsF;AACtF,eAAO,MAAM,qBAAqB,uCAC+B,CAAC;AAIlE,yEAAyE;AACzE,eAAO,MAAM,iBAAiB,SAG1B,YAAY,MAAM,EAClB,WAAW,OAAO,EAClB,UAAU,iBAAiB,kBAK9B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,SAEnB,YAAY,MAAM,EAAE,YAAY,iBAAiB,kBAO1D,CAAC;AAEF,uGAAuG;AACvG,eAAO,MAAM,iBAAiB,SAEpB,YAAY,MAAM,EAAE,QAAQ,iBAAiB,kBActD,CAAC;AA0BF,4EAA4E;AAC5E,eAAO,MAAM,cAAc,+BAAwC,CAAC;AAEpE,8EAA8E;AAC9E,eAAO,MAAM,eAAe,+BAAyC,CAAC;AAEtE,uFAAuF;AACvF,eAAO,MAAM,eAAe,+BAAyC,CAAC"}
|
package/dist/hooks.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { adkExtras } from "./adkExtras.js";
|
|
2
1
|
import { toAdkConfirmationReply } from "./adkToolApproval.js";
|
|
2
|
+
import { toAdkAuthReply } from "./adkAuthRequest.js";
|
|
3
|
+
import { adkExtras } from "./adkExtras.js";
|
|
3
4
|
import { generateId } from "@assistant-ui/core";
|
|
4
5
|
import { useAui } from "@assistant-ui/store";
|
|
5
6
|
import { useShallowSelector } from "@assistant-ui/store/internal";
|
|
@@ -36,17 +37,18 @@ const useAdkConfirmTool = () => {
|
|
|
36
37
|
const aui = useAui();
|
|
37
38
|
return (toolCallId, confirmed, payload) => adkExtras.get(aui).send([toAdkConfirmationReply(toolCallId, confirmed, payload)], {});
|
|
38
39
|
};
|
|
39
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* Returns a function to submit auth credentials for a pending auth request.
|
|
42
|
+
* The reply carries the request's auth config with the credential as its
|
|
43
|
+
* `exchangedAuthCredential`, which is the shape ADK resumes the tool on, so the
|
|
44
|
+
* id must name a request `useAdkAuthRequests` currently lists.
|
|
45
|
+
*/
|
|
40
46
|
const useAdkSubmitAuth = () => {
|
|
41
47
|
const aui = useAui();
|
|
42
|
-
return (toolCallId, credential) =>
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
name: "adk_request_credential",
|
|
47
|
-
content: JSON.stringify(credential),
|
|
48
|
-
status: "success"
|
|
49
|
-
}], {});
|
|
48
|
+
return (toolCallId, credential) => {
|
|
49
|
+
const extras = adkExtras.get(aui);
|
|
50
|
+
return extras.send([toAdkAuthReply(toolCallId, credential, extras.authRequests)], {});
|
|
51
|
+
};
|
|
50
52
|
};
|
|
51
53
|
/** Returns a function to submit the user's answer for a pending `adk_request_input` HITL interrupt. */
|
|
52
54
|
const useAdkSubmitInput = () => {
|
package/dist/hooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","names":[],"sources":["../src/hooks.ts"],"sourcesContent":["import { generateId } from \"@assistant-ui/core\";\nimport { useAui } from \"@assistant-ui/store\";\nimport { useShallowSelector } from \"@assistant-ui/store/internal\";\nimport type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport { adkExtras } from \"./adkExtras\";\nimport { toAdkConfirmationReply } from \"./adkToolApproval\";\nimport type {\n AdkMessage,\n AdkSendMessageConfig,\n AdkToolConfirmation,\n AdkAuthCredential,\n AdkAuthRequest,\n AdkMessageMetadata,\n AdkRuntimeExtras,\n} from \"./types\";\n\nconst EMPTY_STATE_DELTA: Record<string, unknown> = {};\nconst EMPTY_ARTIFACT_DELTA: Record<string, number> = {};\nconst EMPTY_LONG_RUNNING_TOOL_IDS: string[] = [];\nconst EMPTY_TOOL_CONFIRMATIONS: AdkToolConfirmation[] = [];\nconst EMPTY_AUTH_REQUESTS: AdkAuthRequest[] = [];\nconst EMPTY_MESSAGE_METADATA = new Map<string, AdkMessageMetadata>();\n\n/** Returns the name and branch of the currently active ADK agent. */\nexport const useAdkAgentInfo = () =>\n adkExtras.use((e) => e.agentInfo, undefined);\n\n/** Returns the accumulated session state delta from ADK events. */\nexport const useAdkSessionState = () =>\n adkExtras.use((e) => e.stateDelta, EMPTY_STATE_DELTA);\n\n/** Returns a function to send raw ADK messages. */\nexport const useAdkSend = () => {\n const aui = useAui();\n return (messages: AdkMessage[], config: AdkSendMessageConfig) =>\n adkExtras.get(aui).send(messages, config);\n};\n\n/** Returns the IDs of long-running tools awaiting external input. */\nexport const useAdkLongRunningToolIds = () =>\n adkExtras.use((e) => e.longRunningToolIds, EMPTY_LONG_RUNNING_TOOL_IDS);\n\n/** Returns pending tool confirmation requests (from SecurityPlugin etc). */\nexport const useAdkToolConfirmations = () =>\n adkExtras.use((e) => e.toolConfirmations, EMPTY_TOOL_CONFIRMATIONS);\n\n/** Returns pending auth credential requests from tools. */\nexport const useAdkAuthRequests = () =>\n adkExtras.use((e) => e.authRequests, EMPTY_AUTH_REQUESTS);\n\n/** Returns the accumulated artifact delta (filename → version). */\nexport const useAdkArtifacts = () =>\n adkExtras.use((e) => e.artifactDelta, EMPTY_ARTIFACT_DELTA);\n\n/** Returns whether any agent has escalated (requested human handoff). */\nexport const useAdkEscalation = () => adkExtras.use((e) => e.escalated, false);\n\n/** Returns per-message metadata (grounding, citation, usage). Keyed by message ID. */\nexport const useAdkMessageMetadata = () =>\n adkExtras.use((e) => e.messageMetadata, EMPTY_MESSAGE_METADATA);\n\n// ── Convenience helpers for interactive flows ──\n\n/** Returns a function to confirm or deny a pending tool confirmation. */\nexport const useAdkConfirmTool = () => {\n const aui = useAui();\n return (\n toolCallId: string,\n confirmed: boolean,\n payload?: ReadonlyJSONValue,\n ) =>\n adkExtras\n .get(aui)\n .send([toAdkConfirmationReply(toolCallId, confirmed, payload)], {});\n};\n\n
|
|
1
|
+
{"version":3,"file":"hooks.js","names":[],"sources":["../src/hooks.ts"],"sourcesContent":["import { generateId } from \"@assistant-ui/core\";\nimport { useAui } from \"@assistant-ui/store\";\nimport { useShallowSelector } from \"@assistant-ui/store/internal\";\nimport type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport { toAdkAuthReply } from \"./adkAuthRequest\";\nimport { adkExtras } from \"./adkExtras\";\nimport { toAdkConfirmationReply } from \"./adkToolApproval\";\nimport type {\n AdkMessage,\n AdkSendMessageConfig,\n AdkToolConfirmation,\n AdkAuthCredential,\n AdkAuthRequest,\n AdkMessageMetadata,\n AdkRuntimeExtras,\n} from \"./types\";\n\nconst EMPTY_STATE_DELTA: Record<string, unknown> = {};\nconst EMPTY_ARTIFACT_DELTA: Record<string, number> = {};\nconst EMPTY_LONG_RUNNING_TOOL_IDS: string[] = [];\nconst EMPTY_TOOL_CONFIRMATIONS: AdkToolConfirmation[] = [];\nconst EMPTY_AUTH_REQUESTS: AdkAuthRequest[] = [];\nconst EMPTY_MESSAGE_METADATA = new Map<string, AdkMessageMetadata>();\n\n/** Returns the name and branch of the currently active ADK agent. */\nexport const useAdkAgentInfo = () =>\n adkExtras.use((e) => e.agentInfo, undefined);\n\n/** Returns the accumulated session state delta from ADK events. */\nexport const useAdkSessionState = () =>\n adkExtras.use((e) => e.stateDelta, EMPTY_STATE_DELTA);\n\n/** Returns a function to send raw ADK messages. */\nexport const useAdkSend = () => {\n const aui = useAui();\n return (messages: AdkMessage[], config: AdkSendMessageConfig) =>\n adkExtras.get(aui).send(messages, config);\n};\n\n/** Returns the IDs of long-running tools awaiting external input. */\nexport const useAdkLongRunningToolIds = () =>\n adkExtras.use((e) => e.longRunningToolIds, EMPTY_LONG_RUNNING_TOOL_IDS);\n\n/** Returns pending tool confirmation requests (from SecurityPlugin etc). */\nexport const useAdkToolConfirmations = () =>\n adkExtras.use((e) => e.toolConfirmations, EMPTY_TOOL_CONFIRMATIONS);\n\n/** Returns pending auth credential requests from tools. */\nexport const useAdkAuthRequests = () =>\n adkExtras.use((e) => e.authRequests, EMPTY_AUTH_REQUESTS);\n\n/** Returns the accumulated artifact delta (filename → version). */\nexport const useAdkArtifacts = () =>\n adkExtras.use((e) => e.artifactDelta, EMPTY_ARTIFACT_DELTA);\n\n/** Returns whether any agent has escalated (requested human handoff). */\nexport const useAdkEscalation = () => adkExtras.use((e) => e.escalated, false);\n\n/** Returns per-message metadata (grounding, citation, usage). Keyed by message ID. */\nexport const useAdkMessageMetadata = () =>\n adkExtras.use((e) => e.messageMetadata, EMPTY_MESSAGE_METADATA);\n\n// ── Convenience helpers for interactive flows ──\n\n/** Returns a function to confirm or deny a pending tool confirmation. */\nexport const useAdkConfirmTool = () => {\n const aui = useAui();\n return (\n toolCallId: string,\n confirmed: boolean,\n payload?: ReadonlyJSONValue,\n ) =>\n adkExtras\n .get(aui)\n .send([toAdkConfirmationReply(toolCallId, confirmed, payload)], {});\n};\n\n/**\n * Returns a function to submit auth credentials for a pending auth request.\n * The reply carries the request's auth config with the credential as its\n * `exchangedAuthCredential`, which is the shape ADK resumes the tool on, so the\n * id must name a request `useAdkAuthRequests` currently lists.\n */\nexport const useAdkSubmitAuth = () => {\n const aui = useAui();\n return (toolCallId: string, credential: AdkAuthCredential) => {\n const extras = adkExtras.get(aui);\n return extras.send(\n [toAdkAuthReply(toolCallId, credential, extras.authRequests)],\n {},\n );\n };\n};\n\n/** Returns a function to submit the user's answer for a pending `adk_request_input` HITL interrupt. */\nexport const useAdkSubmitInput = () => {\n const aui = useAui();\n return (toolCallId: string, result: ReadonlyJSONValue) =>\n adkExtras.get(aui).send(\n [\n {\n id: generateId(),\n type: \"tool\",\n tool_call_id: toolCallId,\n name: \"adk_request_input\",\n content: JSON.stringify({ result }),\n status: \"success\",\n },\n ],\n {},\n );\n};\n\n// ── State prefix helpers ──\n\nconst APP_PREFIX = \"app:\";\nconst USER_PREFIX = \"user:\";\nconst TEMP_PREFIX = \"temp:\";\n\nconst filterByPrefix = (\n state: Record<string, unknown>,\n prefix: string,\n): Record<string, unknown> =>\n Object.fromEntries(\n Object.entries(state)\n .filter(([key]) => key.startsWith(prefix))\n .map(([key, value]) => [key.slice(prefix.length), value]),\n );\n\nconst useAdkStateByPrefix = (prefix: string) =>\n adkExtras.use(\n useShallowSelector((e: AdkRuntimeExtras) =>\n filterByPrefix(e.stateDelta, prefix),\n ),\n EMPTY_STATE_DELTA,\n );\n\n/** Returns app-level state (keys prefixed with `app:`, prefix stripped). */\nexport const useAdkAppState = () => useAdkStateByPrefix(APP_PREFIX);\n\n/** Returns user-level state (keys prefixed with `user:`, prefix stripped). */\nexport const useAdkUserState = () => useAdkStateByPrefix(USER_PREFIX);\n\n/** Returns temp state (keys prefixed with `temp:`, prefix stripped). Not persisted. */\nexport const useAdkTempState = () => useAdkStateByPrefix(TEMP_PREFIX);\n"],"mappings":";;;;;;;AAiBA,MAAM,oBAA6C,CAAC;AACpD,MAAM,uBAA+C,CAAC;AACtD,MAAM,8BAAwC,CAAC;AAC/C,MAAM,2BAAkD,CAAC;AACzD,MAAM,sBAAwC,CAAC;AAC/C,MAAM,yCAAyB,IAAI,IAAgC;;AAGnE,MAAa,wBACX,UAAU,KAAK,MAAM,EAAE,WAAW,KAAA,CAAS;;AAG7C,MAAa,2BACX,UAAU,KAAK,MAAM,EAAE,YAAY,iBAAiB;;AAGtD,MAAa,mBAAmB;CAC9B,MAAM,MAAM,OAAO;CACnB,QAAQ,UAAwB,WAC9B,UAAU,IAAI,GAAG,CAAC,CAAC,KAAK,UAAU,MAAM;AAC5C;;AAGA,MAAa,iCACX,UAAU,KAAK,MAAM,EAAE,oBAAoB,2BAA2B;;AAGxE,MAAa,gCACX,UAAU,KAAK,MAAM,EAAE,mBAAmB,wBAAwB;;AAGpE,MAAa,2BACX,UAAU,KAAK,MAAM,EAAE,cAAc,mBAAmB;;AAG1D,MAAa,wBACX,UAAU,KAAK,MAAM,EAAE,eAAe,oBAAoB;;AAG5D,MAAa,yBAAyB,UAAU,KAAK,MAAM,EAAE,WAAW,KAAK;;AAG7E,MAAa,8BACX,UAAU,KAAK,MAAM,EAAE,iBAAiB,sBAAsB;;AAKhE,MAAa,0BAA0B;CACrC,MAAM,MAAM,OAAO;CACnB,QACE,YACA,WACA,YAEA,UACG,IAAI,GAAG,CAAC,CACR,KAAK,CAAC,uBAAuB,YAAY,WAAW,OAAO,CAAC,GAAG,CAAC,CAAC;AACxE;;;;;;;AAQA,MAAa,yBAAyB;CACpC,MAAM,MAAM,OAAO;CACnB,QAAQ,YAAoB,eAAkC;EAC5D,MAAM,SAAS,UAAU,IAAI,GAAG;EAChC,OAAO,OAAO,KACZ,CAAC,eAAe,YAAY,YAAY,OAAO,YAAY,CAAC,GAC5D,CAAC,CACH;CACF;AACF;;AAGA,MAAa,0BAA0B;CACrC,MAAM,MAAM,OAAO;CACnB,QAAQ,YAAoB,WAC1B,UAAU,IAAI,GAAG,CAAC,CAAC,KACjB,CACE;EACE,IAAI,WAAW;EACf,MAAM;EACN,cAAc;EACd,MAAM;EACN,SAAS,KAAK,UAAU,EAAE,OAAO,CAAC;EAClC,QAAQ;CACV,CACF,GACA,CAAC,CACH;AACJ;AAIA,MAAM,aAAa;AACnB,MAAM,cAAc;AACpB,MAAM,cAAc;AAEpB,MAAM,kBACJ,OACA,WAEA,OAAO,YACL,OAAO,QAAQ,KAAK,CAAC,CAClB,QAAQ,CAAC,SAAS,IAAI,WAAW,MAAM,CAAC,CAAC,CACzC,KAAK,CAAC,KAAK,WAAW,CAAC,IAAI,MAAM,OAAO,MAAM,GAAG,KAAK,CAAC,CAC5D;AAEF,MAAM,uBAAuB,WAC3B,UAAU,IACR,oBAAoB,MAClB,eAAe,EAAE,YAAY,MAAM,CACrC,GACA,iBACF;;AAGF,MAAa,uBAAuB,oBAAoB,UAAU;;AAGlE,MAAa,wBAAwB,oBAAoB,WAAW;;AAGpE,MAAa,wBAAwB,oBAAoB,WAAW"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export {
|
|
1
|
+
export { useAdkRuntime, type UseAdkRuntimeOptions } from "./useAdkRuntime.js";
|
|
2
|
+
export { useAdkMessages, type UseAdkMessagesOptions } from "./useAdkMessages.js";
|
|
3
|
+
export { convertAdkMessage } from "./convertAdkMessages.js";
|
|
4
|
+
export type { AdkEvent, AdkEventPart, AdkEventActions, AdkMessage, AdkThreadSnapshot, AdkMessageContentPart, AdkToolCall, AdkToolConfirmation, AdkAuthCredential, AdkAuthCredentialType, AdkAuthRequest, AdkMessageMetadata, AdkRunConfig, AdkSendMessageConfig, AdkStreamCallback, AdkStructuredEvent, OnAdkErrorCallback, OnAdkCustomEventCallback, OnAdkAgentTransferCallback, } from "./types.js";
|
|
5
|
+
export { AdkEventType } from "./types.js";
|
|
6
|
+
export { toAdkStructuredEvents } from "./structuredEvents.js";
|
|
7
|
+
export { AdkEventAccumulator } from "./AdkEventAccumulator.js";
|
|
8
|
+
export { createAdkStream, type CreateAdkStreamOptions } from "./AdkClient.js";
|
|
9
|
+
export { createAdkSessionAdapter, type AdkSessionAdapterOptions, type AdkArtifactData, } from "./AdkSessionAdapter.js";
|
|
10
|
+
export { useAdkAgentInfo, useAdkSessionState, useAdkSend, useAdkLongRunningToolIds, useAdkToolConfirmations, useAdkAuthRequests, useAdkArtifacts, useAdkEscalation, useAdkMessageMetadata, useAdkConfirmTool, useAdkSubmitAuth, useAdkSubmitInput, useAdkAppState, useAdkUserState, useAdkTempState, } from "./hooks.js";
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,2BAAwB;AAE3E,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,4BAAyB;AAE9E,OAAO,EAAE,iBAAiB,EAAE,gCAA6B;AAEzD,YAAY,EACV,QAAQ,EACR,YAAY,EACZ,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,qBAAqB,EACrB,WAAW,EACX,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,EACxB,0BAA0B,GAC3B,mBAAgB;AAEjB,OAAO,EAAE,YAAY,EAAE,mBAAgB;AAEvC,OAAO,EAAE,qBAAqB,EAAE,8BAA2B;AAE3D,OAAO,EAAE,mBAAmB,EAAE,iCAA8B;AAE5D,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,uBAAoB;AAE3E,OAAO,EACL,uBAAuB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,GACrB,+BAA4B;AAE7B,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,UAAU,EACV,wBAAwB,EACxB,uBAAuB,EACvB,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,eAAe,GAChB,mBAAgB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalizeAdkPart.d.ts","sourceRoot":"","sources":["../src/normalizeAdkPart.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,gBAAgB,GAC3B,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,MAAM,CAAC,MAAM,EAAE,OAAO,CA8BxB,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { isRecord } from "@assistant-ui/core/internal";
|
|
2
|
+
//#region src/normalizeAdkPart.ts
|
|
3
|
+
const normalizeAdkPart = (part) => {
|
|
4
|
+
const result = { ...part };
|
|
5
|
+
if ("function_call" in part && !("functionCall" in part)) result.functionCall = part.function_call;
|
|
6
|
+
if ("function_response" in part && !("functionResponse" in part)) result.functionResponse = part.function_response;
|
|
7
|
+
if ("inline_data" in part && !("inlineData" in part)) result.inlineData = part.inline_data;
|
|
8
|
+
if ("file_data" in part && !("fileData" in part)) result.fileData = part.file_data;
|
|
9
|
+
if (isRecord(result.inlineData)) {
|
|
10
|
+
const data = result.inlineData;
|
|
11
|
+
if ("mime_type" in data && !("mimeType" in data)) result.inlineData = {
|
|
12
|
+
...data,
|
|
13
|
+
mimeType: data.mime_type
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
if (isRecord(result.fileData)) {
|
|
17
|
+
const data = result.fileData;
|
|
18
|
+
result.fileData = {
|
|
19
|
+
...data,
|
|
20
|
+
..."mime_type" in data && !("mimeType" in data) && { mimeType: data.mime_type },
|
|
21
|
+
..."file_uri" in data && !("fileUri" in data) && { fileUri: data.file_uri }
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if ("executable_code" in part && !("executableCode" in part)) result.executableCode = part.executable_code;
|
|
25
|
+
if ("code_execution_result" in part && !("codeExecutionResult" in part)) result.codeExecutionResult = part.code_execution_result;
|
|
26
|
+
return result;
|
|
27
|
+
};
|
|
28
|
+
//#endregion
|
|
29
|
+
export { normalizeAdkPart };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=normalizeAdkPart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalizeAdkPart.js","names":[],"sources":["../src/normalizeAdkPart.ts"],"sourcesContent":["import { isRecord } from \"@assistant-ui/core/internal\";\n\nexport const normalizeAdkPart = (\n part: Record<string, unknown>,\n): Record<string, unknown> => {\n const result: Record<string, unknown> = { ...part };\n if (\"function_call\" in part && !(\"functionCall\" in part))\n result.functionCall = part.function_call;\n if (\"function_response\" in part && !(\"functionResponse\" in part))\n result.functionResponse = part.function_response;\n if (\"inline_data\" in part && !(\"inlineData\" in part))\n result.inlineData = part.inline_data;\n if (\"file_data\" in part && !(\"fileData\" in part))\n result.fileData = part.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 part && !(\"executableCode\" in part))\n result.executableCode = part.executable_code;\n if (\"code_execution_result\" in part && !(\"codeExecutionResult\" in part))\n result.codeExecutionResult = part.code_execution_result;\n return result;\n};\n"],"mappings":";;AAEA,MAAa,oBACX,SAC4B;CAC5B,MAAM,SAAkC,EAAE,GAAG,KAAK;CAClD,IAAI,mBAAmB,QAAQ,EAAE,kBAAkB,OACjD,OAAO,eAAe,KAAK;CAC7B,IAAI,uBAAuB,QAAQ,EAAE,sBAAsB,OACzD,OAAO,mBAAmB,KAAK;CACjC,IAAI,iBAAiB,QAAQ,EAAE,gBAAgB,OAC7C,OAAO,aAAa,KAAK;CAC3B,IAAI,eAAe,QAAQ,EAAE,cAAc,OACzC,OAAO,WAAW,KAAK;CACzB,IAAI,SAAS,OAAO,UAAU,GAAG;EAC/B,MAAM,OAAO,OAAO;EACpB,IAAI,eAAe,QAAQ,EAAE,cAAc,OACzC,OAAO,aAAa;GAAE,GAAG;GAAM,UAAU,KAAK;EAAU;CAC5D;CACA,IAAI,SAAS,OAAO,QAAQ,GAAG;EAC7B,MAAM,OAAO,OAAO;EACpB,OAAO,WAAW;GAChB,GAAG;GACH,GAAI,eAAe,QACjB,EAAE,cAAc,SAAS,EAAE,UAAU,KAAK,UAAU;GACtD,GAAI,cAAc,QAChB,EAAE,aAAa,SAAS,EAAE,SAAS,KAAK,SAAS;EACrD;CACF;CACA,IAAI,qBAAqB,QAAQ,EAAE,oBAAoB,OACrD,OAAO,iBAAiB,KAAK;CAC/B,IAAI,2BAA2B,QAAQ,EAAE,yBAAyB,OAChE,OAAO,sBAAsB,KAAK;CACpC,OAAO;AACT"}
|
package/dist/parseAdkEvent.d.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { AdkEvent } from "./types.js";
|
|
2
|
-
|
|
3
|
-
declare function parseAdkEventValue(value: unknown, errorPrefix: string): AdkEvent;
|
|
4
|
-
//#endregion
|
|
5
|
-
export { parseAdkEventValue };
|
|
1
|
+
import type { AdkEvent } from "./types.js";
|
|
2
|
+
export declare function parseAdkEventValue(value: unknown, errorPrefix: string): AdkEvent;
|
|
6
3
|
//# sourceMappingURL=parseAdkEvent.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseAdkEvent.d.ts","
|
|
1
|
+
{"version":3,"file":"parseAdkEvent.d.ts","sourceRoot":"","sources":["../src/parseAdkEvent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,mBAAgB;AASxC,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,OAAO,EACd,WAAW,EAAE,MAAM,GAClB,QAAQ,CAuDV"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raceWithAbortSignal.d.ts","sourceRoot":"","sources":["../src/raceWithAbortSignal.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,mBAAmB,GAAI,CAAC,EACnC,QAAQ,WAAW,GAAG,SAAS,EAC/B,WAAW,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAClC,OAAO,CAAC,CAAC,CAqCX,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//#region src/raceWithAbortSignal.ts
|
|
2
|
+
const getAbortReason = (signal) => {
|
|
3
|
+
if (signal.reason !== void 0) return signal.reason;
|
|
4
|
+
const error = /* @__PURE__ */ new Error("The operation was aborted");
|
|
5
|
+
error.name = "AbortError";
|
|
6
|
+
return error;
|
|
7
|
+
};
|
|
8
|
+
const raceWithAbortSignal = (signal, operation) => {
|
|
9
|
+
if (!signal) try {
|
|
10
|
+
return Promise.resolve(operation());
|
|
11
|
+
} catch (error) {
|
|
12
|
+
return Promise.reject(error);
|
|
13
|
+
}
|
|
14
|
+
if (signal.aborted) return Promise.reject(getAbortReason(signal));
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
let settled = false;
|
|
17
|
+
const cleanup = () => signal.removeEventListener("abort", handleAbort);
|
|
18
|
+
const resolveOnce = (value) => {
|
|
19
|
+
if (settled) return;
|
|
20
|
+
settled = true;
|
|
21
|
+
cleanup();
|
|
22
|
+
resolve(value);
|
|
23
|
+
};
|
|
24
|
+
const rejectOnce = (error) => {
|
|
25
|
+
if (settled) return;
|
|
26
|
+
settled = true;
|
|
27
|
+
cleanup();
|
|
28
|
+
reject(error);
|
|
29
|
+
};
|
|
30
|
+
const handleAbort = () => rejectOnce(getAbortReason(signal));
|
|
31
|
+
signal.addEventListener("abort", handleAbort, { once: true });
|
|
32
|
+
let result;
|
|
33
|
+
try {
|
|
34
|
+
result = operation();
|
|
35
|
+
} catch (error) {
|
|
36
|
+
rejectOnce(error);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
Promise.resolve(result).then(resolveOnce, rejectOnce);
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
//#endregion
|
|
43
|
+
export { raceWithAbortSignal };
|
|
44
|
+
|
|
45
|
+
//# sourceMappingURL=raceWithAbortSignal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raceWithAbortSignal.js","names":[],"sources":["../src/raceWithAbortSignal.ts"],"sourcesContent":["const getAbortReason = (signal: AbortSignal): unknown => {\n if (signal.reason !== undefined) return signal.reason;\n const error = new Error(\"The operation was aborted\");\n error.name = \"AbortError\";\n return error;\n};\n\nexport const raceWithAbortSignal = <T>(\n signal: AbortSignal | undefined,\n operation: () => T | PromiseLike<T>,\n): Promise<T> => {\n if (!signal) {\n try {\n return Promise.resolve(operation());\n } catch (error) {\n return Promise.reject(error);\n }\n }\n if (signal.aborted) return Promise.reject(getAbortReason(signal));\n\n return new Promise<T>((resolve, reject) => {\n let settled = false;\n const cleanup = () => signal.removeEventListener(\"abort\", handleAbort);\n const resolveOnce = (value: T) => {\n if (settled) return;\n settled = true;\n cleanup();\n resolve(value);\n };\n const rejectOnce = (error: unknown) => {\n if (settled) return;\n settled = true;\n cleanup();\n reject(error);\n };\n const handleAbort = () => rejectOnce(getAbortReason(signal));\n\n signal.addEventListener(\"abort\", handleAbort, { once: true });\n let result: T | PromiseLike<T>;\n try {\n result = operation();\n } catch (error) {\n rejectOnce(error);\n return;\n }\n Promise.resolve(result).then(resolveOnce, rejectOnce);\n });\n};\n"],"mappings":";AAAA,MAAM,kBAAkB,WAAiC;CACvD,IAAI,OAAO,WAAW,KAAA,GAAW,OAAO,OAAO;CAC/C,MAAM,wBAAQ,IAAI,MAAM,2BAA2B;CACnD,MAAM,OAAO;CACb,OAAO;AACT;AAEA,MAAa,uBACX,QACA,cACe;CACf,IAAI,CAAC,QACH,IAAI;EACF,OAAO,QAAQ,QAAQ,UAAU,CAAC;CACpC,SAAS,OAAO;EACd,OAAO,QAAQ,OAAO,KAAK;CAC7B;CAEF,IAAI,OAAO,SAAS,OAAO,QAAQ,OAAO,eAAe,MAAM,CAAC;CAEhE,OAAO,IAAI,SAAY,SAAS,WAAW;EACzC,IAAI,UAAU;EACd,MAAM,gBAAgB,OAAO,oBAAoB,SAAS,WAAW;EACrE,MAAM,eAAe,UAAa;GAChC,IAAI,SAAS;GACb,UAAU;GACV,QAAQ;GACR,QAAQ,KAAK;EACf;EACA,MAAM,cAAc,UAAmB;GACrC,IAAI,SAAS;GACb,UAAU;GACV,QAAQ;GACR,OAAO,KAAK;EACd;EACA,MAAM,oBAAoB,WAAW,eAAe,MAAM,CAAC;EAE3D,OAAO,iBAAiB,SAAS,aAAa,EAAE,MAAM,KAAK,CAAC;EAC5D,IAAI;EACJ,IAAI;GACF,SAAS,UAAU;EACrB,SAAS,OAAO;GACd,WAAW,KAAK;GAChB;EACF;EACA,QAAQ,QAAQ,MAAM,CAAC,CAAC,KAAK,aAAa,UAAU;CACtD,CAAC;AACH"}
|
package/dist/sdkIdentity.d.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { SdkIdentity } from "assistant-cloud";
|
|
2
|
-
|
|
3
|
-
declare const ADK_SDK: SdkIdentity;
|
|
4
|
-
//#endregion
|
|
5
|
-
export { ADK_SDK };
|
|
1
|
+
import type { SdkIdentity } from "assistant-cloud";
|
|
2
|
+
export declare const ADK_SDK: SdkIdentity;
|
|
6
3
|
//# sourceMappingURL=sdkIdentity.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdkIdentity.d.ts","
|
|
1
|
+
{"version":3,"file":"sdkIdentity.d.ts","sourceRoot":"","sources":["../src/sdkIdentity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,eAAO,MAAM,OAAO,EAAE,WAMrB,CAAC"}
|