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

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/hooks.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- /// <reference types="@assistant-ui/core/store" />
2
1
  import { AdkAuthCredential, AdkAuthRequest, AdkMessage, AdkMessageMetadata, AdkSendMessageConfig, AdkToolConfirmation } from "./types.js";
3
2
  import { ReadonlyJSONValue } from "assistant-stream/utils";
4
3
 
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","names":[],"sources":["../src/hooks.ts"],"mappings":";;;;cAca,sBAAA;AAAA,KAED,gBAAA;EAAA,CACT,sBAAA;EACD,IAAA,GAAO,QAAA,EAAU,UAAA,IAAc,MAAA,EAAQ,oBAAA,KAAyB,OAAA;EAChE,SAAA;IAAa,IAAA;IAA2B,MAAA;EAAA;EACxC,UAAA,EAAY,MAAA;EACZ,aAAA,EAAe,MAAA;EACf,kBAAA;EACA,iBAAA,EAAmB,mBAAA;EACnB,YAAA,EAAc,cAAA;EACd,SAAA;EACA,eAAA,EAAiB,GAAA,SAAY,kBAAA;AAAA;;cAiBlB,eAAA;EAMZ,IAAA;EAAA,MAAA;AAAA;;cAGY,kBAAA,QAAkB,MAAA;;cASlB,UAAA,SAEH,QAAA,EAAU,UAAA,IAAc,MAAA,EAAQ,oBAAA,KAAoB,OAAA;;cAQjD,wBAAA;;cASA,uBAAA,QAAuB,mBAAA;;cASvB,kBAAA,QAAkB,cAAA;;cASlB,eAAA,QAAe,MAAA;;cASf,gBAAA;;cASA,qBAAA,QAAqB,GAAA,SAAA,kBAAA;;cAWrB,iBAAA,SAGT,UAAA,UACA,SAAA,WACA,OAAA,GAAU,iBAAA,KAAiB,OAAA;;cAwBlB,gBAAA,SAEH,UAAA,UAAoB,UAAA,EAAY,iBAAA,KAAiB,OAAA;;cAoB9C,iBAAA,SAEH,UAAA,UAAoB,MAAA,EAAQ,iBAAA,KAAiB,OAAA;;cAuC1C,cAAA,QAAc,MAAA;;cASd,eAAA,QAAe,MAAA;AAzL5B;AAAA,cAkMa,eAAA,QAAe,MAAA"}
1
+ {"version":3,"file":"hooks.d.ts","names":[],"sources":["../src/hooks.ts"],"mappings":";;;;cAYa,sBAAA;AAAA,KAED,gBAAA;EAAA,CACT,sBAAA;EACD,IAAA,GAAO,QAAA,EAAU,UAAA,IAAc,MAAA,EAAQ,oBAAA,KAAyB,OAAA;EAChE,SAAA;IAAa,IAAA;IAA2B,MAAA;EAAA;EACxC,UAAA,EAAY,MAAA;EACZ,aAAA,EAAe,MAAA;EACf,kBAAA;EACA,iBAAA,EAAmB,mBAAA;EACnB,YAAA,EAAc,cAAA;EACd,SAAA;EACA,eAAA,EAAiB,GAAA,SAAY,kBAAA;AAAA;;cAiBlB,eAAA;EAMZ,IAAA;EAAA,MAAA;AAAA;;cAGY,kBAAA,QAAkB,MAAA;;cASlB,UAAA,SAEH,QAAA,EAAU,UAAA,IAAc,MAAA,EAAQ,oBAAA,KAAoB,OAAA;;cAQjD,wBAAA;;cASA,uBAAA,QAAuB,mBAAA;;cASvB,kBAAA,QAAkB,cAAA;;cASlB,eAAA,QAAe,MAAA;;cASf,gBAAA;;cASA,qBAAA,QAAqB,GAAA,SAAA,kBAAA;;cAWrB,iBAAA,SAGT,UAAA,UACA,SAAA,WACA,OAAA,GAAU,iBAAA,KAAiB,OAAA;;cAwBlB,gBAAA,SAEH,UAAA,UAAoB,UAAA,EAAY,iBAAA,KAAiB,OAAA;;cAoB9C,iBAAA,SAEH,UAAA,UAAoB,MAAA,EAAQ,iBAAA,KAAiB,OAAA;;cAuC1C,cAAA,QAAc,MAAA;;cASd,eAAA,QAAe,MAAA;AAzL5B;AAAA,cAkMa,eAAA,QAAe,MAAA"}
package/dist/hooks.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.js","names":["uuidv4"],"sources":["../src/hooks.ts"],"sourcesContent":["/// <reference types=\"@assistant-ui/core/store\" />\n\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport type {\n AdkMessage,\n AdkSendMessageConfig,\n AdkToolConfirmation,\n AdkAuthCredential,\n AdkAuthRequest,\n AdkMessageMetadata,\n} from \"./types\";\n\nexport const symbolAdkRuntimeExtras = Symbol(\"adk-runtime-extras\");\n\nexport type AdkRuntimeExtras = {\n [symbolAdkRuntimeExtras]: true;\n send: (messages: AdkMessage[], config: AdkSendMessageConfig) => Promise<void>;\n agentInfo: { name?: string | undefined; branch?: string | undefined };\n stateDelta: Record<string, unknown>;\n artifactDelta: Record<string, number>;\n longRunningToolIds: string[];\n toolConfirmations: AdkToolConfirmation[];\n authRequests: AdkAuthRequest[];\n escalated: boolean;\n messageMetadata: Map<string, AdkMessageMetadata>;\n};\n\nconst asAdkRuntimeExtras = (extras: unknown): AdkRuntimeExtras => {\n if (\n typeof extras !== \"object\" ||\n extras == null ||\n !(symbolAdkRuntimeExtras in extras)\n )\n throw new Error(\n \"This method can only be called when you are using useAdkRuntime\",\n );\n\n return extras as AdkRuntimeExtras;\n};\n\n/** Returns the name and branch of the currently active ADK agent. */\nexport const useAdkAgentInfo = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return undefined;\n return asAdkRuntimeExtras(extras).agentInfo;\n });\n};\n\n/** Returns the accumulated session state delta from ADK events. */\nexport const useAdkSessionState = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return {};\n return asAdkRuntimeExtras(extras).stateDelta;\n });\n};\n\n/** Returns a function to send raw ADK messages. */\nexport const useAdkSend = () => {\n const aui = useAui();\n return (messages: AdkMessage[], config: AdkSendMessageConfig) => {\n const extras = aui.thread().getState().extras;\n const { send } = asAdkRuntimeExtras(extras);\n return send(messages, config);\n };\n};\n\n/** Returns the IDs of long-running tools awaiting external input. */\nexport const useAdkLongRunningToolIds = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return [];\n return asAdkRuntimeExtras(extras).longRunningToolIds;\n });\n};\n\n/** Returns pending tool confirmation requests (from SecurityPlugin etc). */\nexport const useAdkToolConfirmations = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return [];\n return asAdkRuntimeExtras(extras).toolConfirmations;\n });\n};\n\n/** Returns pending auth credential requests from tools. */\nexport const useAdkAuthRequests = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return [];\n return asAdkRuntimeExtras(extras).authRequests;\n });\n};\n\n/** Returns the accumulated artifact delta (filename → version). */\nexport const useAdkArtifacts = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return {};\n return asAdkRuntimeExtras(extras).artifactDelta;\n });\n};\n\n/** Returns whether any agent has escalated (requested human handoff). */\nexport const useAdkEscalation = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return false;\n return asAdkRuntimeExtras(extras).escalated;\n });\n};\n\n/** Returns per-message metadata (grounding, citation, usage). Keyed by message ID. */\nexport const useAdkMessageMetadata = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return new Map<string, AdkMessageMetadata>();\n return asAdkRuntimeExtras(extras).messageMetadata;\n });\n};\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 const extras = aui.thread().getState().extras;\n const { send } = asAdkRuntimeExtras(extras);\n return send(\n [\n {\n id: uuidv4(),\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 );\n };\n};\n\n/** Returns a function to submit auth credentials for a pending auth request. */\nexport const useAdkSubmitAuth = () => {\n const aui = useAui();\n return (toolCallId: string, credential: AdkAuthCredential) => {\n const extras = aui.thread().getState().extras;\n const { send } = asAdkRuntimeExtras(extras);\n return send(\n [\n {\n id: uuidv4(),\n type: \"tool\",\n tool_call_id: toolCallId,\n name: \"adk_request_credential\",\n content: JSON.stringify(credential),\n status: \"success\",\n },\n ],\n {},\n );\n };\n};\n\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 const extras = aui.thread().getState().extras;\n const { send } = asAdkRuntimeExtras(extras);\n return send(\n [\n {\n id: uuidv4(),\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\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 const result: Record<string, unknown> = {};\n for (const key of Object.keys(state)) {\n if (key.startsWith(prefix)) {\n result[key.slice(prefix.length)] = state[key];\n }\n }\n return result;\n};\n\n/** Returns app-level state (keys prefixed with `app:`, prefix stripped). */\nexport const useAdkAppState = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return {};\n return filterByPrefix(asAdkRuntimeExtras(extras).stateDelta, APP_PREFIX);\n });\n};\n\n/** Returns user-level state (keys prefixed with `user:`, prefix stripped). */\nexport const useAdkUserState = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return {};\n return filterByPrefix(asAdkRuntimeExtras(extras).stateDelta, USER_PREFIX);\n });\n};\n\n/** Returns temp state (keys prefixed with `temp:`, prefix stripped). Not persisted. */\nexport const useAdkTempState = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return {};\n return filterByPrefix(asAdkRuntimeExtras(extras).stateDelta, TEMP_PREFIX);\n });\n};\n"],"mappings":";;;AAcA,MAAa,yBAAyB,OAAO,oBAAoB;AAejE,MAAM,sBAAsB,WAAsC;CAChE,IACE,OAAO,WAAW,YAClB,UAAU,QACV,EAAE,0BAA0B,SAE5B,MAAM,IAAI,MACR,iEACF;CAEF,OAAO;AACT;;AAGA,MAAa,wBAAwB;CACnC,OAAO,aAAa,MAAM;EACxB,MAAM,SAAS,EAAE,OAAO;EACxB,IAAI,CAAC,QAAQ,OAAO,KAAA;EACpB,OAAO,mBAAmB,MAAM,EAAE;CACpC,CAAC;AACH;;AAGA,MAAa,2BAA2B;CACtC,OAAO,aAAa,MAAM;EACxB,MAAM,SAAS,EAAE,OAAO;EACxB,IAAI,CAAC,QAAQ,OAAO,CAAC;EACrB,OAAO,mBAAmB,MAAM,EAAE;CACpC,CAAC;AACH;;AAGA,MAAa,mBAAmB;CAC9B,MAAM,MAAM,OAAO;CACnB,QAAQ,UAAwB,WAAiC;EAC/D,MAAM,SAAS,IAAI,OAAO,EAAE,SAAS,EAAE;EACvC,MAAM,EAAE,SAAS,mBAAmB,MAAM;EAC1C,OAAO,KAAK,UAAU,MAAM;CAC9B;AACF;;AAGA,MAAa,iCAAiC;CAC5C,OAAO,aAAa,MAAM;EACxB,MAAM,SAAS,EAAE,OAAO;EACxB,IAAI,CAAC,QAAQ,OAAO,CAAC;EACrB,OAAO,mBAAmB,MAAM,EAAE;CACpC,CAAC;AACH;;AAGA,MAAa,gCAAgC;CAC3C,OAAO,aAAa,MAAM;EACxB,MAAM,SAAS,EAAE,OAAO;EACxB,IAAI,CAAC,QAAQ,OAAO,CAAC;EACrB,OAAO,mBAAmB,MAAM,EAAE;CACpC,CAAC;AACH;;AAGA,MAAa,2BAA2B;CACtC,OAAO,aAAa,MAAM;EACxB,MAAM,SAAS,EAAE,OAAO;EACxB,IAAI,CAAC,QAAQ,OAAO,CAAC;EACrB,OAAO,mBAAmB,MAAM,EAAE;CACpC,CAAC;AACH;;AAGA,MAAa,wBAAwB;CACnC,OAAO,aAAa,MAAM;EACxB,MAAM,SAAS,EAAE,OAAO;EACxB,IAAI,CAAC,QAAQ,OAAO,CAAC;EACrB,OAAO,mBAAmB,MAAM,EAAE;CACpC,CAAC;AACH;;AAGA,MAAa,yBAAyB;CACpC,OAAO,aAAa,MAAM;EACxB,MAAM,SAAS,EAAE,OAAO;EACxB,IAAI,CAAC,QAAQ,OAAO;EACpB,OAAO,mBAAmB,MAAM,EAAE;CACpC,CAAC;AACH;;AAGA,MAAa,8BAA8B;CACzC,OAAO,aAAa,MAAM;EACxB,MAAM,SAAS,EAAE,OAAO;EACxB,IAAI,CAAC,QAAQ,uBAAO,IAAI,IAAgC;EACxD,OAAO,mBAAmB,MAAM,EAAE;CACpC,CAAC;AACH;;AAKA,MAAa,0BAA0B;CACrC,MAAM,MAAM,OAAO;CACnB,QACE,YACA,WACA,YACG;EACH,MAAM,SAAS,IAAI,OAAO,EAAE,SAAS,EAAE;EACvC,MAAM,EAAE,SAAS,mBAAmB,MAAM;EAC1C,OAAO,KACL,CACE;GACE,IAAIA,GAAO;GACX,MAAM;GACN,cAAc;GACd,MAAM;GACN,SAAS,KAAK,UAAU;IACtB;IACA,GAAI,WAAW,QAAQ,EAAE,QAAQ;GACnC,CAAC;GACD,QAAQ;EACV,CACF,GACA,CAAC,CACH;CACF;AACF;;AAGA,MAAa,yBAAyB;CACpC,MAAM,MAAM,OAAO;CACnB,QAAQ,YAAoB,eAAkC;EAC5D,MAAM,SAAS,IAAI,OAAO,EAAE,SAAS,EAAE;EACvC,MAAM,EAAE,SAAS,mBAAmB,MAAM;EAC1C,OAAO,KACL,CACE;GACE,IAAIA,GAAO;GACX,MAAM;GACN,cAAc;GACd,MAAM;GACN,SAAS,KAAK,UAAU,UAAU;GAClC,QAAQ;EACV,CACF,GACA,CAAC,CACH;CACF;AACF;;AAGA,MAAa,0BAA0B;CACrC,MAAM,MAAM,OAAO;CACnB,QAAQ,YAAoB,WAA8B;EACxD,MAAM,SAAS,IAAI,OAAO,EAAE,SAAS,EAAE;EACvC,MAAM,EAAE,SAAS,mBAAmB,MAAM;EAC1C,OAAO,KACL,CACE;GACE,IAAIA,GAAO;GACX,MAAM;GACN,cAAc;GACd,MAAM;GACN,SAAS,KAAK,UAAU,EAAE,OAAO,CAAC;GAClC,QAAQ;EACV,CACF,GACA,CAAC,CACH;CACF;AACF;AAIA,MAAM,aAAa;AACnB,MAAM,cAAc;AACpB,MAAM,cAAc;AAEpB,MAAM,kBACJ,OACA,WAC4B;CAC5B,MAAM,SAAkC,CAAC;CACzC,KAAK,MAAM,OAAO,OAAO,KAAK,KAAK,GACjC,IAAI,IAAI,WAAW,MAAM,GACvB,OAAO,IAAI,MAAM,OAAO,MAAM,KAAK,MAAM;CAG7C,OAAO;AACT;;AAGA,MAAa,uBAAuB;CAClC,OAAO,aAAa,MAAM;EACxB,MAAM,SAAS,EAAE,OAAO;EACxB,IAAI,CAAC,QAAQ,OAAO,CAAC;EACrB,OAAO,eAAe,mBAAmB,MAAM,EAAE,YAAY,UAAU;CACzE,CAAC;AACH;;AAGA,MAAa,wBAAwB;CACnC,OAAO,aAAa,MAAM;EACxB,MAAM,SAAS,EAAE,OAAO;EACxB,IAAI,CAAC,QAAQ,OAAO,CAAC;EACrB,OAAO,eAAe,mBAAmB,MAAM,EAAE,YAAY,WAAW;CAC1E,CAAC;AACH;;AAGA,MAAa,wBAAwB;CACnC,OAAO,aAAa,MAAM;EACxB,MAAM,SAAS,EAAE,OAAO;EACxB,IAAI,CAAC,QAAQ,OAAO,CAAC;EACrB,OAAO,eAAe,mBAAmB,MAAM,EAAE,YAAY,WAAW;CAC1E,CAAC;AACH"}
1
+ {"version":3,"file":"hooks.js","names":["uuidv4"],"sources":["../src/hooks.ts"],"sourcesContent":["import { useAui, useAuiState } from \"@assistant-ui/store\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport type {\n AdkMessage,\n AdkSendMessageConfig,\n AdkToolConfirmation,\n AdkAuthCredential,\n AdkAuthRequest,\n AdkMessageMetadata,\n} from \"./types\";\n\nexport const symbolAdkRuntimeExtras = Symbol(\"adk-runtime-extras\");\n\nexport type AdkRuntimeExtras = {\n [symbolAdkRuntimeExtras]: true;\n send: (messages: AdkMessage[], config: AdkSendMessageConfig) => Promise<void>;\n agentInfo: { name?: string | undefined; branch?: string | undefined };\n stateDelta: Record<string, unknown>;\n artifactDelta: Record<string, number>;\n longRunningToolIds: string[];\n toolConfirmations: AdkToolConfirmation[];\n authRequests: AdkAuthRequest[];\n escalated: boolean;\n messageMetadata: Map<string, AdkMessageMetadata>;\n};\n\nconst asAdkRuntimeExtras = (extras: unknown): AdkRuntimeExtras => {\n if (\n typeof extras !== \"object\" ||\n extras == null ||\n !(symbolAdkRuntimeExtras in extras)\n )\n throw new Error(\n \"This method can only be called when you are using useAdkRuntime\",\n );\n\n return extras as AdkRuntimeExtras;\n};\n\n/** Returns the name and branch of the currently active ADK agent. */\nexport const useAdkAgentInfo = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return undefined;\n return asAdkRuntimeExtras(extras).agentInfo;\n });\n};\n\n/** Returns the accumulated session state delta from ADK events. */\nexport const useAdkSessionState = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return {};\n return asAdkRuntimeExtras(extras).stateDelta;\n });\n};\n\n/** Returns a function to send raw ADK messages. */\nexport const useAdkSend = () => {\n const aui = useAui();\n return (messages: AdkMessage[], config: AdkSendMessageConfig) => {\n const extras = aui.thread().getState().extras;\n const { send } = asAdkRuntimeExtras(extras);\n return send(messages, config);\n };\n};\n\n/** Returns the IDs of long-running tools awaiting external input. */\nexport const useAdkLongRunningToolIds = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return [];\n return asAdkRuntimeExtras(extras).longRunningToolIds;\n });\n};\n\n/** Returns pending tool confirmation requests (from SecurityPlugin etc). */\nexport const useAdkToolConfirmations = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return [];\n return asAdkRuntimeExtras(extras).toolConfirmations;\n });\n};\n\n/** Returns pending auth credential requests from tools. */\nexport const useAdkAuthRequests = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return [];\n return asAdkRuntimeExtras(extras).authRequests;\n });\n};\n\n/** Returns the accumulated artifact delta (filename → version). */\nexport const useAdkArtifacts = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return {};\n return asAdkRuntimeExtras(extras).artifactDelta;\n });\n};\n\n/** Returns whether any agent has escalated (requested human handoff). */\nexport const useAdkEscalation = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return false;\n return asAdkRuntimeExtras(extras).escalated;\n });\n};\n\n/** Returns per-message metadata (grounding, citation, usage). Keyed by message ID. */\nexport const useAdkMessageMetadata = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return new Map<string, AdkMessageMetadata>();\n return asAdkRuntimeExtras(extras).messageMetadata;\n });\n};\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 const extras = aui.thread().getState().extras;\n const { send } = asAdkRuntimeExtras(extras);\n return send(\n [\n {\n id: uuidv4(),\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 );\n };\n};\n\n/** Returns a function to submit auth credentials for a pending auth request. */\nexport const useAdkSubmitAuth = () => {\n const aui = useAui();\n return (toolCallId: string, credential: AdkAuthCredential) => {\n const extras = aui.thread().getState().extras;\n const { send } = asAdkRuntimeExtras(extras);\n return send(\n [\n {\n id: uuidv4(),\n type: \"tool\",\n tool_call_id: toolCallId,\n name: \"adk_request_credential\",\n content: JSON.stringify(credential),\n status: \"success\",\n },\n ],\n {},\n );\n };\n};\n\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 const extras = aui.thread().getState().extras;\n const { send } = asAdkRuntimeExtras(extras);\n return send(\n [\n {\n id: uuidv4(),\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\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 const result: Record<string, unknown> = {};\n for (const key of Object.keys(state)) {\n if (key.startsWith(prefix)) {\n result[key.slice(prefix.length)] = state[key];\n }\n }\n return result;\n};\n\n/** Returns app-level state (keys prefixed with `app:`, prefix stripped). */\nexport const useAdkAppState = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return {};\n return filterByPrefix(asAdkRuntimeExtras(extras).stateDelta, APP_PREFIX);\n });\n};\n\n/** Returns user-level state (keys prefixed with `user:`, prefix stripped). */\nexport const useAdkUserState = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return {};\n return filterByPrefix(asAdkRuntimeExtras(extras).stateDelta, USER_PREFIX);\n });\n};\n\n/** Returns temp state (keys prefixed with `temp:`, prefix stripped). Not persisted. */\nexport const useAdkTempState = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return {};\n return filterByPrefix(asAdkRuntimeExtras(extras).stateDelta, TEMP_PREFIX);\n });\n};\n"],"mappings":"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"}
@@ -1,4 +1,3 @@
1
- /// <reference types="@assistant-ui/core/store" />
2
1
  import { AdkAuthRequest, AdkMessage, AdkMessageMetadata, AdkSendMessageConfig, AdkStreamCallback, AdkToolConfirmation, OnAdkAgentTransferCallback, OnAdkCustomEventCallback, OnAdkErrorCallback } from "./types.js";
3
2
 
4
3
  //#region src/useAdkMessages.d.ts
@@ -1 +1 @@
1
- {"version":3,"file":"useAdkMessages.d.ts","names":[],"sources":["../src/useAdkMessages.ts"],"mappings":";;;KAmBY,qBAAA;EACV,MAAA,EAAQ,iBAAA;EACR,aAAA;IACE,OAAA,GAAU,kBAAA;IACV,aAAA,GAAgB,wBAAA;IAChB,eAAA,GAAkB,0BAAA;EAAA;AAAA;AAAA,cAIT,cAAA;EAAkB,MAAA;EAAA;AAAA,GAG5B,qBAAA;;;;;;;;;;;;;6BA2DqB,UAAA,IAAY,MAAA,EAAU,oBAAA,KAAoB,OAAA;;sBA9BhB,UAAA;0BAUvC,UAAA;AAAA"}
1
+ {"version":3,"file":"useAdkMessages.d.ts","names":[],"sources":["../src/useAdkMessages.ts"],"mappings":";;;KAkBY,qBAAA;EACV,MAAA,EAAQ,iBAAA;EACR,aAAA;IACE,OAAA,GAAU,kBAAA;IACV,aAAA,GAAgB,wBAAA;IAChB,eAAA,GAAkB,0BAAA;EAAA;AAAA;AAAA,cAIT,cAAA;EAAkB,MAAA;EAAA;AAAA,GAG5B,qBAAA;;;;;;;;;;;;;6BA2DqB,UAAA,IAAY,MAAA,EAAU,oBAAA,KAAoB,OAAA;;sBA9BhB,UAAA;0BAUvC,UAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"useAdkMessages.js","names":["uuidv4"],"sources":["../src/useAdkMessages.ts"],"sourcesContent":["/// <reference types=\"@assistant-ui/core/store\" />\nimport { useState, useCallback, useRef, useMemo } from \"react\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { useAui } from \"@assistant-ui/store\";\nimport { AdkEventAccumulator } from \"./AdkEventAccumulator\";\nimport { contentToParts } from \"./contentToParts\";\nimport type {\n AdkEvent,\n AdkMessage,\n AdkMessageMetadata,\n AdkSendMessageConfig,\n AdkStreamCallback,\n AdkToolConfirmation,\n AdkAuthRequest,\n OnAdkErrorCallback,\n OnAdkCustomEventCallback,\n OnAdkAgentTransferCallback,\n} from \"./types\";\n\nexport type UseAdkMessagesOptions = {\n stream: AdkStreamCallback;\n eventHandlers?: {\n onError?: OnAdkErrorCallback;\n onCustomEvent?: OnAdkCustomEventCallback;\n onAgentTransfer?: OnAdkAgentTransferCallback;\n };\n};\n\nexport const useAdkMessages = ({\n stream,\n eventHandlers,\n}: UseAdkMessagesOptions) => {\n const [messages, _setMessages] = useState<AdkMessage[]>([]);\n const [stateDelta, setStateDelta] = useState<Record<string, unknown>>({});\n const [agentInfo, setAgentInfo] = useState<{\n name?: string | undefined;\n branch?: string | undefined;\n }>({});\n const [longRunningToolIds, setLongRunningToolIds] = useState<string[]>([]);\n const [artifactDelta, setArtifactDelta] = useState<Record<string, number>>(\n {},\n );\n const [toolConfirmations, setToolConfirmations] = useState<\n AdkToolConfirmation[]\n >([]);\n const [authRequests, setAuthRequests] = useState<AdkAuthRequest[]>([]);\n const [escalated, setEscalated] = useState(false);\n const [messageMetadata, setMessageMetadata] = useState<\n Map<string, AdkMessageMetadata>\n >(new Map());\n const lastTransferToAgentRef = useRef<string | undefined>(undefined);\n const messagesRef = useRef(messages);\n messagesRef.current = messages;\n const stateDeltaRef = useRef(stateDelta);\n stateDeltaRef.current = stateDelta;\n const artifactDeltaRef = useRef(artifactDelta);\n artifactDeltaRef.current = artifactDelta;\n const messageMetadataRef = useRef(messageMetadata);\n messageMetadataRef.current = messageMetadata;\n\n const setMessagesImmediate = useCallback((msgs: AdkMessage[]) => {\n messagesRef.current = msgs;\n _setMessages(msgs);\n }, []);\n\n // Replace the message list AND reset derived per-turn HITL state.\n // Used by truncation paths (edit, reload, load) so that stale interrupt\n // markers and per-message metadata from the removed messages don't leak\n // into the next turn.\n const replaceMessages = useCallback(\n (msgs: AdkMessage[]) => {\n setMessagesImmediate(msgs);\n setLongRunningToolIds([]);\n setToolConfirmations([]);\n setAuthRequests([]);\n setEscalated(false);\n setMessageMetadata(new Map());\n },\n [setMessagesImmediate],\n );\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const { onError, onCustomEvent, onAgentTransfer } = useMemo(\n () => eventHandlers ?? {},\n [eventHandlers],\n );\n\n const aui = useAui();\n const sendMessage = useCallback(\n async (newMessages: AdkMessage[], config: AdkSendMessageConfig) => {\n const newMessagesWithId = newMessages.map((m) =>\n m.id ? m : { ...m, id: uuidv4() },\n ) as AdkMessage[];\n\n const accumulator = new AdkEventAccumulator(messagesRef.current);\n for (const msg of newMessagesWithId) {\n accumulator.processEvent(messageToEvent(msg));\n }\n setMessagesImmediate(accumulator.getMessages());\n\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n\n try {\n const response = await stream(newMessagesWithId, {\n ...config,\n abortSignal: abortController.signal,\n initialize: async () => {\n return await aui.threadListItem().initialize();\n },\n });\n\n for await (const event of response) {\n const updatedMessages = accumulator.processEvent(event);\n setMessagesImmediate(updatedMessages);\n setStateDelta({\n ...stateDeltaRef.current,\n ...accumulator.getStateDelta(),\n });\n setAgentInfo(accumulator.getAgentInfo());\n setLongRunningToolIds(accumulator.getLongRunningToolIds());\n setArtifactDelta({\n ...artifactDeltaRef.current,\n ...accumulator.getArtifactDelta(),\n });\n setToolConfirmations(accumulator.getToolConfirmations());\n setAuthRequests(accumulator.getAuthRequests());\n setEscalated(accumulator.isEscalated());\n {\n const newMeta = accumulator.getMessageMetadata();\n if (newMeta.size > 0) {\n setMessageMetadata(\n new Map([...messageMetadataRef.current, ...newMeta]),\n );\n }\n }\n\n const transfer = accumulator.getLastTransferToAgent();\n if (transfer && transfer !== lastTransferToAgentRef.current) {\n lastTransferToAgentRef.current = transfer;\n onAgentTransfer?.(transfer);\n }\n\n // Fire custom event callback for events with customMetadata\n if (event.customMetadata && onCustomEvent) {\n for (const [key, value] of Object.entries(event.customMetadata)) {\n onCustomEvent(key, value);\n }\n }\n\n if (event.errorCode || event.errorMessage) {\n onError?.(event.errorMessage ?? event.errorCode);\n }\n }\n } catch (error) {\n if (\n !abortController.signal.aborted &&\n !(error instanceof Error && error.name === \"AbortError\")\n ) {\n throw error;\n }\n } finally {\n if (abortControllerRef.current === abortController) {\n abortControllerRef.current = null;\n }\n }\n },\n [\n aui,\n setMessagesImmediate,\n stream,\n onError,\n onCustomEvent,\n onAgentTransfer,\n ],\n );\n\n const cancel = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n }, []);\n\n return {\n messages,\n stateDelta,\n agentInfo,\n longRunningToolIds,\n artifactDelta,\n toolConfirmations,\n authRequests,\n escalated,\n messageMetadata,\n sendMessage,\n cancel,\n setMessages: setMessagesImmediate,\n replaceMessages,\n };\n};\n\n/** @internal — exported for unit tests. */\nexport const messageToEvent = (msg: AdkMessage): AdkEvent => {\n if (msg.type === \"human\") {\n return {\n id: msg.id ?? uuidv4(),\n author: \"user\",\n content: { role: \"user\", parts: contentToParts(msg.content) },\n };\n }\n\n if (msg.type === \"tool\") {\n let response: unknown;\n try {\n response = JSON.parse(msg.content);\n } catch {\n response = msg.content;\n }\n return {\n id: msg.id ?? uuidv4(),\n content: {\n role: \"user\",\n parts: [\n {\n functionResponse: {\n name: msg.name,\n id: msg.tool_call_id,\n response,\n },\n },\n ],\n },\n };\n }\n\n const result: AdkEvent = { id: msg.id ?? uuidv4() };\n if (msg.author != null) result.author = msg.author;\n result.content = {\n role: \"model\",\n parts: [\n ...contentToParts(msg.content),\n ...(msg.tool_calls?.map((tc) => ({\n functionCall: { name: tc.name, id: tc.id, args: { ...tc.args } },\n })) ?? []),\n ],\n };\n return result;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"useAdkMessages.js","names":["uuidv4"],"sources":["../src/useAdkMessages.ts"],"sourcesContent":["import { useState, useCallback, useRef, useMemo } from \"react\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { useAui } from \"@assistant-ui/store\";\nimport { AdkEventAccumulator } from \"./AdkEventAccumulator\";\nimport { contentToParts } from \"./contentToParts\";\nimport type {\n AdkEvent,\n AdkMessage,\n AdkMessageMetadata,\n AdkSendMessageConfig,\n AdkStreamCallback,\n AdkToolConfirmation,\n AdkAuthRequest,\n OnAdkErrorCallback,\n OnAdkCustomEventCallback,\n OnAdkAgentTransferCallback,\n} from \"./types\";\n\nexport type UseAdkMessagesOptions = {\n stream: AdkStreamCallback;\n eventHandlers?: {\n onError?: OnAdkErrorCallback;\n onCustomEvent?: OnAdkCustomEventCallback;\n onAgentTransfer?: OnAdkAgentTransferCallback;\n };\n};\n\nexport const useAdkMessages = ({\n stream,\n eventHandlers,\n}: UseAdkMessagesOptions) => {\n const [messages, _setMessages] = useState<AdkMessage[]>([]);\n const [stateDelta, setStateDelta] = useState<Record<string, unknown>>({});\n const [agentInfo, setAgentInfo] = useState<{\n name?: string | undefined;\n branch?: string | undefined;\n }>({});\n const [longRunningToolIds, setLongRunningToolIds] = useState<string[]>([]);\n const [artifactDelta, setArtifactDelta] = useState<Record<string, number>>(\n {},\n );\n const [toolConfirmations, setToolConfirmations] = useState<\n AdkToolConfirmation[]\n >([]);\n const [authRequests, setAuthRequests] = useState<AdkAuthRequest[]>([]);\n const [escalated, setEscalated] = useState(false);\n const [messageMetadata, setMessageMetadata] = useState<\n Map<string, AdkMessageMetadata>\n >(new Map());\n const lastTransferToAgentRef = useRef<string | undefined>(undefined);\n const messagesRef = useRef(messages);\n messagesRef.current = messages;\n const stateDeltaRef = useRef(stateDelta);\n stateDeltaRef.current = stateDelta;\n const artifactDeltaRef = useRef(artifactDelta);\n artifactDeltaRef.current = artifactDelta;\n const messageMetadataRef = useRef(messageMetadata);\n messageMetadataRef.current = messageMetadata;\n\n const setMessagesImmediate = useCallback((msgs: AdkMessage[]) => {\n messagesRef.current = msgs;\n _setMessages(msgs);\n }, []);\n\n // Replace the message list AND reset derived per-turn HITL state.\n // Used by truncation paths (edit, reload, load) so that stale interrupt\n // markers and per-message metadata from the removed messages don't leak\n // into the next turn.\n const replaceMessages = useCallback(\n (msgs: AdkMessage[]) => {\n setMessagesImmediate(msgs);\n setLongRunningToolIds([]);\n setToolConfirmations([]);\n setAuthRequests([]);\n setEscalated(false);\n setMessageMetadata(new Map());\n },\n [setMessagesImmediate],\n );\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const { onError, onCustomEvent, onAgentTransfer } = useMemo(\n () => eventHandlers ?? {},\n [eventHandlers],\n );\n\n const aui = useAui();\n const sendMessage = useCallback(\n async (newMessages: AdkMessage[], config: AdkSendMessageConfig) => {\n const newMessagesWithId = newMessages.map((m) =>\n m.id ? m : { ...m, id: uuidv4() },\n ) as AdkMessage[];\n\n const accumulator = new AdkEventAccumulator(messagesRef.current);\n for (const msg of newMessagesWithId) {\n accumulator.processEvent(messageToEvent(msg));\n }\n setMessagesImmediate(accumulator.getMessages());\n\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n\n try {\n const response = await stream(newMessagesWithId, {\n ...config,\n abortSignal: abortController.signal,\n initialize: async () => {\n return await aui.threadListItem().initialize();\n },\n });\n\n for await (const event of response) {\n const updatedMessages = accumulator.processEvent(event);\n setMessagesImmediate(updatedMessages);\n setStateDelta({\n ...stateDeltaRef.current,\n ...accumulator.getStateDelta(),\n });\n setAgentInfo(accumulator.getAgentInfo());\n setLongRunningToolIds(accumulator.getLongRunningToolIds());\n setArtifactDelta({\n ...artifactDeltaRef.current,\n ...accumulator.getArtifactDelta(),\n });\n setToolConfirmations(accumulator.getToolConfirmations());\n setAuthRequests(accumulator.getAuthRequests());\n setEscalated(accumulator.isEscalated());\n {\n const newMeta = accumulator.getMessageMetadata();\n if (newMeta.size > 0) {\n setMessageMetadata(\n new Map([...messageMetadataRef.current, ...newMeta]),\n );\n }\n }\n\n const transfer = accumulator.getLastTransferToAgent();\n if (transfer && transfer !== lastTransferToAgentRef.current) {\n lastTransferToAgentRef.current = transfer;\n onAgentTransfer?.(transfer);\n }\n\n // Fire custom event callback for events with customMetadata\n if (event.customMetadata && onCustomEvent) {\n for (const [key, value] of Object.entries(event.customMetadata)) {\n onCustomEvent(key, value);\n }\n }\n\n if (event.errorCode || event.errorMessage) {\n onError?.(event.errorMessage ?? event.errorCode);\n }\n }\n } catch (error) {\n if (\n !abortController.signal.aborted &&\n !(error instanceof Error && error.name === \"AbortError\")\n ) {\n throw error;\n }\n } finally {\n if (abortControllerRef.current === abortController) {\n abortControllerRef.current = null;\n }\n }\n },\n [\n aui,\n setMessagesImmediate,\n stream,\n onError,\n onCustomEvent,\n onAgentTransfer,\n ],\n );\n\n const cancel = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n }, []);\n\n return {\n messages,\n stateDelta,\n agentInfo,\n longRunningToolIds,\n artifactDelta,\n toolConfirmations,\n authRequests,\n escalated,\n messageMetadata,\n sendMessage,\n cancel,\n setMessages: setMessagesImmediate,\n replaceMessages,\n };\n};\n\n/** @internal — exported for unit tests. */\nexport const messageToEvent = (msg: AdkMessage): AdkEvent => {\n if (msg.type === \"human\") {\n return {\n id: msg.id ?? uuidv4(),\n author: \"user\",\n content: { role: \"user\", parts: contentToParts(msg.content) },\n };\n }\n\n if (msg.type === \"tool\") {\n let response: unknown;\n try {\n response = JSON.parse(msg.content);\n } catch {\n response = msg.content;\n }\n return {\n id: msg.id ?? uuidv4(),\n content: {\n role: \"user\",\n parts: [\n {\n functionResponse: {\n name: msg.name,\n id: msg.tool_call_id,\n response,\n },\n },\n ],\n },\n };\n }\n\n const result: AdkEvent = { id: msg.id ?? uuidv4() };\n if (msg.author != null) result.author = msg.author;\n result.content = {\n role: \"model\",\n parts: [\n ...contentToParts(msg.content),\n ...(msg.tool_calls?.map((tc) => ({\n functionCall: { name: tc.name, id: tc.id, args: { ...tc.args } },\n })) ?? []),\n ],\n };\n return result;\n};\n"],"mappings":";;;;;;AA2BA,MAAa,kBAAkB,EAC7B,QACA,oBAC2B;CAC3B,MAAM,CAAC,UAAU,gBAAgB,SAAuB,CAAC,CAAC;CAC1D,MAAM,CAAC,YAAY,iBAAiB,SAAkC,CAAC,CAAC;CACxE,MAAM,CAAC,WAAW,gBAAgB,SAG/B,CAAC,CAAC;CACL,MAAM,CAAC,oBAAoB,yBAAyB,SAAmB,CAAC,CAAC;CACzE,MAAM,CAAC,eAAe,oBAAoB,SACxC,CAAC,CACH;CACA,MAAM,CAAC,mBAAmB,wBAAwB,SAEhD,CAAC,CAAC;CACJ,MAAM,CAAC,cAAc,mBAAmB,SAA2B,CAAC,CAAC;CACrE,MAAM,CAAC,WAAW,gBAAgB,SAAS,KAAK;CAChD,MAAM,CAAC,iBAAiB,sBAAsB,yBAE5C,IAAI,IAAI,CAAC;CACX,MAAM,yBAAyB,OAA2B,KAAA,CAAS;CACnE,MAAM,cAAc,OAAO,QAAQ;CACnC,YAAY,UAAU;CACtB,MAAM,gBAAgB,OAAO,UAAU;CACvC,cAAc,UAAU;CACxB,MAAM,mBAAmB,OAAO,aAAa;CAC7C,iBAAiB,UAAU;CAC3B,MAAM,qBAAqB,OAAO,eAAe;CACjD,mBAAmB,UAAU;CAE7B,MAAM,uBAAuB,aAAa,SAAuB;EAC/D,YAAY,UAAU;EACtB,aAAa,IAAI;CACnB,GAAG,CAAC,CAAC;CAML,MAAM,kBAAkB,aACrB,SAAuB;EACtB,qBAAqB,IAAI;EACzB,sBAAsB,CAAC,CAAC;EACxB,qBAAqB,CAAC,CAAC;EACvB,gBAAgB,CAAC,CAAC;EAClB,aAAa,KAAK;EAClB,mCAAmB,IAAI,IAAI,CAAC;CAC9B,GACA,CAAC,oBAAoB,CACvB;CAEA,MAAM,qBAAqB,OAA+B,IAAI;CAE9D,MAAM,EAAE,SAAS,eAAe,oBAAoB,cAC5C,iBAAiB,CAAC,GACxB,CAAC,aAAa,CAChB;CAEA,MAAM,MAAM,OAAO;CAgGnB,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,aAzGkB,YAClB,OAAO,aAA2B,WAAiC;GACjE,MAAM,oBAAoB,YAAY,KAAK,MACzC,EAAE,KAAK,IAAI;IAAE,GAAG;IAAG,IAAIA,GAAO;GAAE,CAClC;GAEA,MAAM,cAAc,IAAI,oBAAoB,YAAY,OAAO;GAC/D,KAAK,MAAM,OAAO,mBAChB,YAAY,aAAa,eAAe,GAAG,CAAC;GAE9C,qBAAqB,YAAY,YAAY,CAAC;GAE9C,MAAM,kBAAkB,IAAI,gBAAgB;GAC5C,mBAAmB,UAAU;GAE7B,IAAI;IACF,MAAM,WAAW,MAAM,OAAO,mBAAmB;KAC/C,GAAG;KACH,aAAa,gBAAgB;KAC7B,YAAY,YAAY;MACtB,OAAO,MAAM,IAAI,eAAe,EAAE,WAAW;KAC/C;IACF,CAAC;IAED,WAAW,MAAM,SAAS,UAAU;KAElC,qBADwB,YAAY,aAAa,KACd,CAAC;KACpC,cAAc;MACZ,GAAG,cAAc;MACjB,GAAG,YAAY,cAAc;KAC/B,CAAC;KACD,aAAa,YAAY,aAAa,CAAC;KACvC,sBAAsB,YAAY,sBAAsB,CAAC;KACzD,iBAAiB;MACf,GAAG,iBAAiB;MACpB,GAAG,YAAY,iBAAiB;KAClC,CAAC;KACD,qBAAqB,YAAY,qBAAqB,CAAC;KACvD,gBAAgB,YAAY,gBAAgB,CAAC;KAC7C,aAAa,YAAY,YAAY,CAAC;KACtC;MACE,MAAM,UAAU,YAAY,mBAAmB;MAC/C,IAAI,QAAQ,OAAO,GACjB,mBACE,IAAI,IAAI,CAAC,GAAG,mBAAmB,SAAS,GAAG,OAAO,CAAC,CACrD;KAEJ;KAEA,MAAM,WAAW,YAAY,uBAAuB;KACpD,IAAI,YAAY,aAAa,uBAAuB,SAAS;MAC3D,uBAAuB,UAAU;MACjC,kBAAkB,QAAQ;KAC5B;KAGA,IAAI,MAAM,kBAAkB,eAC1B,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,cAAc,GAC5D,cAAc,KAAK,KAAK;KAI5B,IAAI,MAAM,aAAa,MAAM,cAC3B,UAAU,MAAM,gBAAgB,MAAM,SAAS;IAEnD;GACF,SAAS,OAAO;IACd,IACE,CAAC,gBAAgB,OAAO,WACxB,EAAE,iBAAiB,SAAS,MAAM,SAAS,eAE3C,MAAM;GAEV,UAAU;IACR,IAAI,mBAAmB,YAAY,iBACjC,mBAAmB,UAAU;GAEjC;EACF,GACA;GACE;GACA;GACA;GACA;GACA;GACA;EACF,CAmBU;EACV,QAjBa,kBAAkB;GAC/B,IAAI,mBAAmB,SACrB,mBAAmB,QAAQ,MAAM;EAErC,GAAG,CAAC,CAaG;EACL,aAAa;EACb;CACF;AACF;;AAGA,MAAa,kBAAkB,QAA8B;CAC3D,IAAI,IAAI,SAAS,SACf,OAAO;EACL,IAAI,IAAI,MAAMA,GAAO;EACrB,QAAQ;EACR,SAAS;GAAE,MAAM;GAAQ,OAAO,eAAe,IAAI,OAAO;EAAE;CAC9D;CAGF,IAAI,IAAI,SAAS,QAAQ;EACvB,IAAI;EACJ,IAAI;GACF,WAAW,KAAK,MAAM,IAAI,OAAO;EACnC,QAAQ;GACN,WAAW,IAAI;EACjB;EACA,OAAO;GACL,IAAI,IAAI,MAAMA,GAAO;GACrB,SAAS;IACP,MAAM;IACN,OAAO,CACL,EACE,kBAAkB;KAChB,MAAM,IAAI;KACV,IAAI,IAAI;KACR;IACF,EACF,CACF;GACF;EACF;CACF;CAEA,MAAM,SAAmB,EAAE,IAAI,IAAI,MAAMA,GAAO,EAAE;CAClD,IAAI,IAAI,UAAU,MAAM,OAAO,SAAS,IAAI;CAC5C,OAAO,UAAU;EACf,MAAM;EACN,OAAO,CACL,GAAG,eAAe,IAAI,OAAO,GAC7B,GAAI,IAAI,YAAY,KAAK,QAAQ,EAC/B,cAAc;GAAE,MAAM,GAAG;GAAM,IAAI,GAAG;GAAI,MAAM,EAAE,GAAG,GAAG,KAAK;EAAE,EACjE,EAAE,KAAK,CAAC,CACV;CACF;CACA,OAAO;AACT"}
@@ -1,4 +1,3 @@
1
- /// <reference types="@assistant-ui/core/store" />
2
1
  import { AdkMessage, AdkStreamCallback, OnAdkAgentTransferCallback, OnAdkCustomEventCallback, OnAdkErrorCallback } from "./types.js";
3
2
  import { AttachmentAdapter, DictationAdapter, FeedbackAdapter, RemoteThreadListAdapter, SpeechSynthesisAdapter } from "@assistant-ui/core";
4
3
  import { AssistantCloud } from "assistant-cloud";
@@ -1 +1 @@
1
- {"version":3,"file":"useAdkRuntime.d.ts","names":[],"sources":["../src/useAdkRuntime.ts"],"mappings":";;;;;KA2IY,oBAAA;EACV,MAAA,EAAQ,iBAAA;EACR,0BAAA;EACA,0BAAA;EACA,eAAA,IACE,QAAA,UACA,cAAA,EAAgB,UAAA,OACb,OAAA;EACL,IAAA,IAAQ,QAAA,aAAqB,OAAA;IAAU,QAAA,EAAU,UAAA;EAAA;EACjD,MAAA,SAAe,OAAA;IAAU,UAAA;EAAA;EACzB,MAAA,IAAU,QAAA,aAAqB,OAAA;EAC/B,QAAA;IAEM,WAAA,GAAc,iBAAA;IACd,MAAA,GAAS,sBAAA;IACT,SAAA,GAAY,gBAAA;IACZ,QAAA,GAAW,eAAA;EAAA;EAGjB,aAAA;IAEM,OAAA,GAAU,kBAAA;IACV,aAAA,GAAgB,wBAAA;IAChB,eAAA,GAAkB,0BAAA;EAAA;EAGxB,KAAA,GAAQ,cAAA;EAxBR;;;;EA6BA,cAAA,GAAiB,uBAAA;AAAA;AAAA,cAkPN,aAAA;EAAiB,KAAA;EAAA,cAAA;EAAA,MAAA;EAAA,MAAA,EAAA,QAAA;EAAA,GAAA;AAAA,GAM3B,oBAAA,kCAAoB,gBAAA"}
1
+ {"version":3,"file":"useAdkRuntime.d.ts","names":[],"sources":["../src/useAdkRuntime.ts"],"mappings":";;;;;KAyIY,oBAAA;EACV,MAAA,EAAQ,iBAAA;EACR,0BAAA;EACA,0BAAA;EACA,eAAA,IACE,QAAA,UACA,cAAA,EAAgB,UAAA,OACb,OAAA;EACL,IAAA,IAAQ,QAAA,aAAqB,OAAA;IAAU,QAAA,EAAU,UAAA;EAAA;EACjD,MAAA,SAAe,OAAA;IAAU,UAAA;EAAA;EACzB,MAAA,IAAU,QAAA,aAAqB,OAAA;EAC/B,QAAA;IAEM,WAAA,GAAc,iBAAA;IACd,MAAA,GAAS,sBAAA;IACT,SAAA,GAAY,gBAAA;IACZ,QAAA,GAAW,eAAA;EAAA;EAGjB,aAAA;IAEM,OAAA,GAAU,kBAAA;IACV,aAAA,GAAgB,wBAAA;IAChB,eAAA,GAAkB,0BAAA;EAAA;EAGxB,KAAA,GAAQ,cAAA;EAxBR;;;;EA6BA,cAAA,GAAiB,uBAAA;AAAA;AAAA,cA8MN,aAAA;EAAiB,KAAA;EAAA,cAAA;EAAA,MAAA;EAAA,MAAA,EAAA,QAAA;EAAA,GAAA;AAAA,GAM3B,oBAAA,kCAAoB,gBAAA"}
@@ -5,7 +5,7 @@ import { v4 } from "uuid";
5
5
  import { useAui } from "@assistant-ui/store";
6
6
  import { useEffect, useRef, useState } from "react";
7
7
  import { getExternalStoreMessages } from "@assistant-ui/core";
8
- import { useCloudThreadListAdapter, useExternalMessageConverter, useExternalStoreRuntime, useRemoteThreadListRuntime, useToolInvocations } from "@assistant-ui/core/react";
8
+ import { useCloudThreadListAdapter, useExternalMessageConverter, useExternalStoreRuntime, useRemoteThreadListRuntime } from "@assistant-ui/core/react";
9
9
  //#region src/useAdkRuntime.ts
10
10
  /** @internal — exported for unit tests. */
11
11
  const getMessageContent = (msg) => {
@@ -95,30 +95,11 @@ const useAdkRuntimeImpl = ({ autoCancelPendingToolCalls, adapters: { attachments
95
95
  });
96
96
  const threadMessagesRef = useRef(threadMessages);
97
97
  threadMessagesRef.current = threadMessages;
98
- const [runtimeRef] = useState(() => ({ get current() {
99
- return runtime;
100
- } }));
101
- const toolInvocations = useToolInvocations({
102
- state: {
103
- messages: threadMessages,
104
- isRunning: effectiveIsRunning
105
- },
106
- getTools: () => runtimeRef.current.thread.getModelContext().tools,
107
- onResult: (command) => {
108
- if (command.type === "add-tool-result") handleSendMessage([{
109
- id: v4(),
110
- type: "tool",
111
- name: command.toolName,
112
- tool_call_id: command.toolCallId,
113
- content: JSON.stringify(command.result),
114
- status: command.isError ? "error" : "success"
115
- }], {});
116
- },
117
- setToolStatuses
118
- });
119
98
  const runtime = useExternalStoreRuntime({
120
99
  isRunning: effectiveIsRunning,
121
100
  messages: threadMessages,
101
+ unstable_enableToolInvocations: true,
102
+ setToolStatuses,
122
103
  adapters: {
123
104
  attachments,
124
105
  dictation,
@@ -138,7 +119,6 @@ const useAdkRuntimeImpl = ({ autoCancelPendingToolCalls, adapters: { attachments
138
119
  send: handleSendMessage
139
120
  },
140
121
  onNew: async (msg) => {
141
- await toolInvocations.abort();
142
122
  return handleSendMessage([...autoCancelPendingToolCalls !== false ? getPendingCancellations(messages, longRunningToolIds) : [], {
143
123
  id: v4(),
144
124
  type: "human",
@@ -146,7 +126,6 @@ const useAdkRuntimeImpl = ({ autoCancelPendingToolCalls, adapters: { attachments
146
126
  }], { runConfig: msg.runConfig });
147
127
  },
148
128
  onEdit: getCheckpointId ? async (msg) => {
149
- await toolInvocations.abort();
150
129
  const truncated = truncateAdkMessages(threadMessagesRef.current, msg.parentId);
151
130
  replaceMessages(truncated);
152
131
  const externalId = aui.threadListItem().getState().externalId;
@@ -161,7 +140,6 @@ const useAdkRuntimeImpl = ({ autoCancelPendingToolCalls, adapters: { attachments
161
140
  });
162
141
  } : void 0,
163
142
  onReload: getCheckpointId ? async (parentId, config) => {
164
- await toolInvocations.abort();
165
143
  const truncated = truncateAdkMessages(threadMessagesRef.current, parentId);
166
144
  replaceMessages(truncated);
167
145
  const externalId = aui.threadListItem().getState().externalId;
@@ -182,10 +160,8 @@ const useAdkRuntimeImpl = ({ autoCancelPendingToolCalls, adapters: { attachments
182
160
  status: isError ? "error" : "success"
183
161
  }], {});
184
162
  },
185
- onResumeToolCall: (options) => toolInvocations.resume(options.toolCallId, options.payload),
186
163
  onCancel: unstable_allowCancellation ? async () => {
187
164
  cancel();
188
- await toolInvocations.abort();
189
165
  } : void 0
190
166
  });
191
167
  {
@@ -1 +1 @@
1
- {"version":3,"file":"useAdkRuntime.js","names":["_exhaustiveCheck","uuidv4"],"sources":["../src/useAdkRuntime.ts"],"sourcesContent":["/// <reference types=\"@assistant-ui/core/store\" />\nimport { useEffect, useRef, useState } from \"react\";\nimport {\n getExternalStoreMessages,\n type AttachmentAdapter,\n type DictationAdapter,\n type FeedbackAdapter,\n type SpeechSynthesisAdapter,\n type AppendMessage,\n type ThreadMessage,\n} from \"@assistant-ui/core\";\nimport {\n type ToolExecutionStatus,\n useCloudThreadListAdapter,\n useRemoteThreadListRuntime,\n useExternalMessageConverter,\n useExternalStoreRuntime,\n useToolInvocations,\n} from \"@assistant-ui/core/react\";\nimport { useAui } from \"@assistant-ui/store\";\nimport type { AssistantCloud } from \"assistant-cloud\";\nimport type { RemoteThreadListAdapter } from \"@assistant-ui/core\";\nimport type {\n AdkMessage,\n AdkSendMessageConfig,\n AdkStreamCallback,\n OnAdkErrorCallback,\n OnAdkCustomEventCallback,\n OnAdkAgentTransferCallback,\n} from \"./types\";\nimport { useAdkMessages } from \"./useAdkMessages\";\nimport { convertAdkMessage } from \"./convertAdkMessages\";\nimport { symbolAdkRuntimeExtras, type AdkRuntimeExtras } from \"./hooks\";\nimport { v4 as uuidv4 } from \"uuid\";\n\n/** @internal — exported for unit tests. */\nexport const getMessageContent = (msg: AppendMessage) => {\n const allContent = [\n ...msg.content,\n ...(msg.attachments?.flatMap((a) => a.content) ?? []),\n ];\n const content = allContent.map((part) => {\n const type = part.type;\n switch (type) {\n case \"text\":\n return { type: \"text\" as const, text: part.text };\n case \"image\":\n return { type: \"image_url\" as const, url: part.image };\n case \"file\":\n return {\n type: \"file\" as const,\n mimeType: part.mimeType,\n data: part.data,\n ...(part.filename != null && { filename: part.filename }),\n };\n\n case \"tool-call\":\n throw new Error(\"Tool call appends are not supported.\");\n\n default: {\n const _exhaustiveCheck:\n | \"reasoning\"\n | \"source\"\n | \"audio\"\n | \"data\"\n | \"generative-ui\" = type;\n throw new Error(\n `Unsupported append message part type: ${_exhaustiveCheck}`,\n );\n }\n }\n });\n\n if (content.length === 1 && content[0]?.type === \"text\") {\n return content[0].text ?? \"\";\n }\n\n return content;\n};\n\n/** @internal — exported for unit tests. */\nexport const getPendingToolCalls = (messages: AdkMessage[]) => {\n const pending = new Map<string, { id: string; name: string }>();\n for (const msg of messages) {\n if (msg.type === \"ai\" && msg.tool_calls) {\n for (const tc of msg.tool_calls) {\n pending.set(tc.id, tc);\n }\n }\n if (msg.type === \"tool\") {\n pending.delete(msg.tool_call_id);\n }\n }\n return [...pending.values()];\n};\n\n/**\n * @internal — exported for unit tests.\n *\n * Returns `{cancelled: true}` tool responses for pending tool calls when the\n * user sends a new turn, EXCEPT for HITL interrupts marked via\n * `long_running_tool_ids` (`adk_request_input`, `adk_request_confirmation`,\n * `adk_request_credential`). Those must be answered through a dedicated tool\n * UI + submit helper, not auto-cancelled.\n */\nexport const getPendingCancellations = (\n messages: AdkMessage[],\n longRunningToolIds: readonly string[],\n): Array<AdkMessage & { type: \"tool\" }> => {\n const longRunningSet = new Set(longRunningToolIds);\n return getPendingToolCalls(messages)\n .filter((t) => !longRunningSet.has(t.id))\n .map(\n (t) =>\n ({\n id: uuidv4(),\n type: \"tool\",\n name: t.name,\n tool_call_id: t.id,\n content: JSON.stringify({ cancelled: true }),\n status: \"error\",\n }) satisfies AdkMessage & { type: \"tool\" },\n );\n};\n\nconst truncateAdkMessages = (\n threadMessages: readonly ThreadMessage[],\n parentId: string | null,\n): AdkMessage[] => {\n if (parentId === null) return [];\n const parentIndex = threadMessages.findIndex((m) => m.id === parentId);\n if (parentIndex === -1) return [];\n const truncated: AdkMessage[] = [];\n for (let i = 0; i <= parentIndex && i < threadMessages.length; i++) {\n truncated.push(...getExternalStoreMessages<AdkMessage>(threadMessages[i]!));\n }\n return truncated;\n};\n\nexport type UseAdkRuntimeOptions = {\n stream: AdkStreamCallback;\n autoCancelPendingToolCalls?: boolean | undefined;\n unstable_allowCancellation?: boolean | undefined;\n getCheckpointId?: (\n threadId: string,\n parentMessages: AdkMessage[],\n ) => Promise<string | null>;\n load?: (threadId: string) => Promise<{ messages: AdkMessage[] }>;\n create?: () => Promise<{ externalId: string }>;\n delete?: (threadId: string) => Promise<void>;\n adapters?:\n | {\n attachments?: AttachmentAdapter;\n speech?: SpeechSynthesisAdapter;\n dictation?: DictationAdapter;\n feedback?: FeedbackAdapter;\n }\n | undefined;\n eventHandlers?:\n | {\n onError?: OnAdkErrorCallback;\n onCustomEvent?: OnAdkCustomEventCallback;\n onAgentTransfer?: OnAdkAgentTransferCallback;\n }\n | undefined;\n cloud?: AssistantCloud | undefined;\n /**\n * A `RemoteThreadListAdapter` to use instead of the cloud adapter.\n * Use with `createAdkSessionAdapter` for ADK session-backed persistence.\n */\n sessionAdapter?: RemoteThreadListAdapter | undefined;\n};\n\nconst useAdkRuntimeImpl = ({\n autoCancelPendingToolCalls,\n adapters: { attachments, dictation, feedback, speech } = {},\n unstable_allowCancellation,\n stream,\n load,\n getCheckpointId,\n eventHandlers,\n}: UseAdkRuntimeOptions) => {\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const aui = useAui();\n const {\n messages,\n stateDelta,\n agentInfo,\n longRunningToolIds,\n artifactDelta,\n toolConfirmations,\n authRequests,\n escalated,\n messageMetadata,\n sendMessage,\n cancel,\n replaceMessages,\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n } = useAdkMessages({\n stream,\n ...(eventHandlers && { eventHandlers }),\n });\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const [isRunning, setIsRunning] = useState(false);\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const [toolStatuses, setToolStatuses] = useState<\n Record<string, ToolExecutionStatus>\n >({});\n const hasExecutingTools = Object.values(toolStatuses).some(\n (s) => s?.type === \"executing\",\n );\n const effectiveIsRunning = isRunning || hasExecutingTools;\n\n const handleSendMessage = async (\n msgs: AdkMessage[],\n config: AdkSendMessageConfig,\n ) => {\n try {\n setIsRunning(true);\n await sendMessage(msgs, config);\n } finally {\n setIsRunning(false);\n }\n };\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const threadMessages = useExternalMessageConverter({\n callback: convertAdkMessage,\n messages,\n isRunning: effectiveIsRunning,\n });\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const threadMessagesRef = useRef(threadMessages);\n threadMessagesRef.current = threadMessages;\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const [runtimeRef] = useState(() => ({\n get current() {\n return runtime;\n },\n }));\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const toolInvocations = useToolInvocations({\n state: { messages: threadMessages, isRunning: effectiveIsRunning },\n getTools: () => runtimeRef.current.thread.getModelContext().tools,\n onResult: (command) => {\n if (command.type === \"add-tool-result\") {\n void handleSendMessage(\n [\n {\n id: uuidv4(),\n type: \"tool\",\n name: command.toolName,\n tool_call_id: command.toolCallId,\n content: JSON.stringify(command.result),\n status: command.isError ? \"error\" : \"success\",\n },\n ],\n {},\n );\n }\n },\n setToolStatuses,\n });\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const runtime = useExternalStoreRuntime({\n isRunning: effectiveIsRunning,\n messages: threadMessages,\n adapters: { attachments, dictation, feedback, speech },\n extras: {\n [symbolAdkRuntimeExtras]: true,\n agentInfo,\n stateDelta,\n artifactDelta,\n longRunningToolIds,\n toolConfirmations,\n authRequests,\n escalated,\n messageMetadata,\n send: handleSendMessage,\n } satisfies AdkRuntimeExtras,\n onNew: async (msg) => {\n await toolInvocations.abort();\n\n const cancellations =\n autoCancelPendingToolCalls !== false\n ? getPendingCancellations(messages, longRunningToolIds)\n : [];\n\n return handleSendMessage(\n [\n ...cancellations,\n {\n id: uuidv4(),\n type: \"human\",\n content: getMessageContent(msg),\n },\n ],\n { runConfig: msg.runConfig },\n );\n },\n onEdit: getCheckpointId\n ? async (msg) => {\n await toolInvocations.abort();\n const truncated = truncateAdkMessages(\n threadMessagesRef.current,\n msg.parentId,\n );\n replaceMessages(truncated);\n const externalId = aui.threadListItem().getState().externalId;\n const checkpointId = externalId\n ? await getCheckpointId(externalId, truncated)\n : null;\n return handleSendMessage(\n [\n {\n id: uuidv4(),\n type: \"human\",\n content: getMessageContent(msg),\n },\n ],\n {\n runConfig: msg.runConfig,\n ...(checkpointId && { checkpointId }),\n },\n );\n }\n : undefined,\n onReload: getCheckpointId\n ? async (parentId, config) => {\n await toolInvocations.abort();\n const truncated = truncateAdkMessages(\n threadMessagesRef.current,\n parentId,\n );\n replaceMessages(truncated);\n const externalId = aui.threadListItem().getState().externalId;\n const checkpointId = externalId\n ? await getCheckpointId(externalId, truncated)\n : null;\n return handleSendMessage([], {\n runConfig: config.runConfig,\n ...(checkpointId && { checkpointId }),\n });\n }\n : undefined,\n onAddToolResult: async ({\n toolCallId,\n toolName,\n result,\n isError,\n artifact,\n }) => {\n await handleSendMessage(\n [\n {\n id: uuidv4(),\n type: \"tool\",\n name: toolName,\n tool_call_id: toolCallId,\n content: JSON.stringify(result),\n artifact,\n status: isError ? \"error\" : \"success\",\n },\n ],\n {},\n );\n },\n onResumeToolCall: (options) =>\n toolInvocations.resume(options.toolCallId, options.payload),\n onCancel: unstable_allowCancellation\n ? async () => {\n cancel();\n await toolInvocations.abort();\n }\n : undefined,\n });\n\n {\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const loadRef = useRef(load);\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n useEffect(() => {\n loadRef.current = load;\n });\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n useEffect(() => {\n const loadFn = loadRef.current;\n if (!loadFn) return;\n\n const externalId = aui.threadListItem().getState().externalId;\n if (externalId == null) return;\n\n loadFn(externalId).then(\n ({ messages: msgs }) => {\n replaceMessages(msgs);\n },\n (e) => {\n console.warn(\"Failed to load ADK session:\", e);\n },\n );\n }, [aui, replaceMessages]);\n }\n\n return runtime;\n};\n\nexport const useAdkRuntime = ({\n cloud,\n sessionAdapter,\n create,\n delete: deleteFn,\n ...options\n}: UseAdkRuntimeOptions) => {\n const aui = useAui();\n const cloudAdapter = useCloudThreadListAdapter({\n cloud,\n create: async () => {\n if (create) return create();\n if (aui.threadListItem.source) return aui.threadListItem().initialize();\n return { externalId: undefined };\n },\n delete: deleteFn,\n });\n\n const adapter = sessionAdapter ?? cloudAdapter;\n\n return useRemoteThreadListRuntime({\n runtimeHook: function RuntimeHook() {\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n return useAdkRuntimeImpl(options);\n },\n adapter,\n allowNesting: true,\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"useAdkRuntime.js","names":["_exhaustiveCheck","uuidv4"],"sources":["../src/useAdkRuntime.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport {\n getExternalStoreMessages,\n type AttachmentAdapter,\n type DictationAdapter,\n type FeedbackAdapter,\n type SpeechSynthesisAdapter,\n type AppendMessage,\n type ThreadMessage,\n type ToolExecutionStatus,\n} from \"@assistant-ui/core\";\nimport {\n useCloudThreadListAdapter,\n useRemoteThreadListRuntime,\n useExternalMessageConverter,\n useExternalStoreRuntime,\n} from \"@assistant-ui/core/react\";\nimport { useAui } from \"@assistant-ui/store\";\nimport type { AssistantCloud } from \"assistant-cloud\";\nimport type { RemoteThreadListAdapter } from \"@assistant-ui/core\";\nimport type {\n AdkMessage,\n AdkSendMessageConfig,\n AdkStreamCallback,\n OnAdkErrorCallback,\n OnAdkCustomEventCallback,\n OnAdkAgentTransferCallback,\n} from \"./types\";\nimport { useAdkMessages } from \"./useAdkMessages\";\nimport { convertAdkMessage } from \"./convertAdkMessages\";\nimport { symbolAdkRuntimeExtras, type AdkRuntimeExtras } from \"./hooks\";\nimport { v4 as uuidv4 } from \"uuid\";\n\n/** @internal — exported for unit tests. */\nexport const getMessageContent = (msg: AppendMessage) => {\n const allContent = [\n ...msg.content,\n ...(msg.attachments?.flatMap((a) => a.content) ?? []),\n ];\n const content = allContent.map((part) => {\n const type = part.type;\n switch (type) {\n case \"text\":\n return { type: \"text\" as const, text: part.text };\n case \"image\":\n return { type: \"image_url\" as const, url: part.image };\n case \"file\":\n return {\n type: \"file\" as const,\n mimeType: part.mimeType,\n data: part.data,\n ...(part.filename != null && { filename: part.filename }),\n };\n\n case \"tool-call\":\n throw new Error(\"Tool call appends are not supported.\");\n\n default: {\n const _exhaustiveCheck:\n | \"reasoning\"\n | \"source\"\n | \"audio\"\n | \"data\"\n | \"generative-ui\" = type;\n throw new Error(\n `Unsupported append message part type: ${_exhaustiveCheck}`,\n );\n }\n }\n });\n\n if (content.length === 1 && content[0]?.type === \"text\") {\n return content[0].text ?? \"\";\n }\n\n return content;\n};\n\n/** @internal — exported for unit tests. */\nexport const getPendingToolCalls = (messages: AdkMessage[]) => {\n const pending = new Map<string, { id: string; name: string }>();\n for (const msg of messages) {\n if (msg.type === \"ai\" && msg.tool_calls) {\n for (const tc of msg.tool_calls) {\n pending.set(tc.id, tc);\n }\n }\n if (msg.type === \"tool\") {\n pending.delete(msg.tool_call_id);\n }\n }\n return [...pending.values()];\n};\n\n/**\n * @internal — exported for unit tests.\n *\n * Returns `{cancelled: true}` tool responses for pending tool calls when the\n * user sends a new turn, EXCEPT for HITL interrupts marked via\n * `long_running_tool_ids` (`adk_request_input`, `adk_request_confirmation`,\n * `adk_request_credential`). Those must be answered through a dedicated tool\n * UI + submit helper, not auto-cancelled.\n */\nexport const getPendingCancellations = (\n messages: AdkMessage[],\n longRunningToolIds: readonly string[],\n): Array<AdkMessage & { type: \"tool\" }> => {\n const longRunningSet = new Set(longRunningToolIds);\n return getPendingToolCalls(messages)\n .filter((t) => !longRunningSet.has(t.id))\n .map(\n (t) =>\n ({\n id: uuidv4(),\n type: \"tool\",\n name: t.name,\n tool_call_id: t.id,\n content: JSON.stringify({ cancelled: true }),\n status: \"error\",\n }) satisfies AdkMessage & { type: \"tool\" },\n );\n};\n\nconst truncateAdkMessages = (\n threadMessages: readonly ThreadMessage[],\n parentId: string | null,\n): AdkMessage[] => {\n if (parentId === null) return [];\n const parentIndex = threadMessages.findIndex((m) => m.id === parentId);\n if (parentIndex === -1) return [];\n const truncated: AdkMessage[] = [];\n for (let i = 0; i <= parentIndex && i < threadMessages.length; i++) {\n truncated.push(...getExternalStoreMessages<AdkMessage>(threadMessages[i]!));\n }\n return truncated;\n};\n\nexport type UseAdkRuntimeOptions = {\n stream: AdkStreamCallback;\n autoCancelPendingToolCalls?: boolean | undefined;\n unstable_allowCancellation?: boolean | undefined;\n getCheckpointId?: (\n threadId: string,\n parentMessages: AdkMessage[],\n ) => Promise<string | null>;\n load?: (threadId: string) => Promise<{ messages: AdkMessage[] }>;\n create?: () => Promise<{ externalId: string }>;\n delete?: (threadId: string) => Promise<void>;\n adapters?:\n | {\n attachments?: AttachmentAdapter;\n speech?: SpeechSynthesisAdapter;\n dictation?: DictationAdapter;\n feedback?: FeedbackAdapter;\n }\n | undefined;\n eventHandlers?:\n | {\n onError?: OnAdkErrorCallback;\n onCustomEvent?: OnAdkCustomEventCallback;\n onAgentTransfer?: OnAdkAgentTransferCallback;\n }\n | undefined;\n cloud?: AssistantCloud | undefined;\n /**\n * A `RemoteThreadListAdapter` to use instead of the cloud adapter.\n * Use with `createAdkSessionAdapter` for ADK session-backed persistence.\n */\n sessionAdapter?: RemoteThreadListAdapter | undefined;\n};\n\nconst useAdkRuntimeImpl = ({\n autoCancelPendingToolCalls,\n adapters: { attachments, dictation, feedback, speech } = {},\n unstable_allowCancellation,\n stream,\n load,\n getCheckpointId,\n eventHandlers,\n}: UseAdkRuntimeOptions) => {\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const aui = useAui();\n const {\n messages,\n stateDelta,\n agentInfo,\n longRunningToolIds,\n artifactDelta,\n toolConfirmations,\n authRequests,\n escalated,\n messageMetadata,\n sendMessage,\n cancel,\n replaceMessages,\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n } = useAdkMessages({\n stream,\n ...(eventHandlers && { eventHandlers }),\n });\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const [isRunning, setIsRunning] = useState(false);\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const [toolStatuses, setToolStatuses] = useState<\n Record<string, ToolExecutionStatus>\n >({});\n const hasExecutingTools = Object.values(toolStatuses).some(\n (s) => s?.type === \"executing\",\n );\n const effectiveIsRunning = isRunning || hasExecutingTools;\n\n const handleSendMessage = async (\n msgs: AdkMessage[],\n config: AdkSendMessageConfig,\n ) => {\n try {\n setIsRunning(true);\n await sendMessage(msgs, config);\n } finally {\n setIsRunning(false);\n }\n };\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const threadMessages = useExternalMessageConverter({\n callback: convertAdkMessage,\n messages,\n isRunning: effectiveIsRunning,\n });\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const threadMessagesRef = useRef(threadMessages);\n threadMessagesRef.current = threadMessages;\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const runtime = useExternalStoreRuntime({\n isRunning: effectiveIsRunning,\n messages: threadMessages,\n unstable_enableToolInvocations: true,\n setToolStatuses,\n adapters: { attachments, dictation, feedback, speech },\n extras: {\n [symbolAdkRuntimeExtras]: true,\n agentInfo,\n stateDelta,\n artifactDelta,\n longRunningToolIds,\n toolConfirmations,\n authRequests,\n escalated,\n messageMetadata,\n send: handleSendMessage,\n } satisfies AdkRuntimeExtras,\n onNew: async (msg) => {\n const cancellations =\n autoCancelPendingToolCalls !== false\n ? getPendingCancellations(messages, longRunningToolIds)\n : [];\n\n return handleSendMessage(\n [\n ...cancellations,\n {\n id: uuidv4(),\n type: \"human\",\n content: getMessageContent(msg),\n },\n ],\n { runConfig: msg.runConfig },\n );\n },\n onEdit: getCheckpointId\n ? async (msg) => {\n const truncated = truncateAdkMessages(\n threadMessagesRef.current,\n msg.parentId,\n );\n replaceMessages(truncated);\n const externalId = aui.threadListItem().getState().externalId;\n const checkpointId = externalId\n ? await getCheckpointId(externalId, truncated)\n : null;\n return handleSendMessage(\n [\n {\n id: uuidv4(),\n type: \"human\",\n content: getMessageContent(msg),\n },\n ],\n {\n runConfig: msg.runConfig,\n ...(checkpointId && { checkpointId }),\n },\n );\n }\n : undefined,\n onReload: getCheckpointId\n ? async (parentId, config) => {\n const truncated = truncateAdkMessages(\n threadMessagesRef.current,\n parentId,\n );\n replaceMessages(truncated);\n const externalId = aui.threadListItem().getState().externalId;\n const checkpointId = externalId\n ? await getCheckpointId(externalId, truncated)\n : null;\n return handleSendMessage([], {\n runConfig: config.runConfig,\n ...(checkpointId && { checkpointId }),\n });\n }\n : undefined,\n onAddToolResult: async ({\n toolCallId,\n toolName,\n result,\n isError,\n artifact,\n }) => {\n await handleSendMessage(\n [\n {\n id: uuidv4(),\n type: \"tool\",\n name: toolName,\n tool_call_id: toolCallId,\n content: JSON.stringify(result),\n artifact,\n status: isError ? \"error\" : \"success\",\n },\n ],\n {},\n );\n },\n onCancel: unstable_allowCancellation\n ? async () => {\n cancel();\n }\n : undefined,\n });\n\n {\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const loadRef = useRef(load);\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n useEffect(() => {\n loadRef.current = load;\n });\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n useEffect(() => {\n const loadFn = loadRef.current;\n if (!loadFn) return;\n\n const externalId = aui.threadListItem().getState().externalId;\n if (externalId == null) return;\n\n loadFn(externalId).then(\n ({ messages: msgs }) => {\n replaceMessages(msgs);\n },\n (e) => {\n console.warn(\"Failed to load ADK session:\", e);\n },\n );\n }, [aui, replaceMessages]);\n }\n\n return runtime;\n};\n\nexport const useAdkRuntime = ({\n cloud,\n sessionAdapter,\n create,\n delete: deleteFn,\n ...options\n}: UseAdkRuntimeOptions) => {\n const aui = useAui();\n const cloudAdapter = useCloudThreadListAdapter({\n cloud,\n create: async () => {\n if (create) return create();\n if (aui.threadListItem.source) return aui.threadListItem().initialize();\n return { externalId: undefined };\n },\n delete: deleteFn,\n });\n\n const adapter = sessionAdapter ?? cloudAdapter;\n\n return useRemoteThreadListRuntime({\n runtimeHook: function RuntimeHook() {\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n return useAdkRuntimeImpl(options);\n },\n adapter,\n allowNesting: true,\n });\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/react-google-adk",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "description": "Google ADK adapter for assistant-ui",
5
5
  "keywords": [
6
6
  "google-adk",
@@ -1,6 +1,6 @@
1
1
  import { describe, it, expect } from "vitest";
2
2
  import { AdkEventAccumulator } from "./AdkEventAccumulator";
3
- import type { AdkEvent, AdkMessage } from "./types";
3
+ import type { AdkEvent, AdkMessage, AdkMessageContentPart } from "./types";
4
4
 
5
5
  const makeEvent = (overrides: Partial<AdkEvent> = {}): AdkEvent => ({
6
6
  id: "evt-1",
@@ -568,10 +568,9 @@ describe("AdkEventAccumulator - HITL requires-action", () => {
568
568
  );
569
569
  expect(aiMsg).toBeDefined();
570
570
  expect(aiMsg!.tool_calls).toHaveLength(1);
571
+ const parts = aiMsg!.content as AdkMessageContentPart[];
571
572
  expect(
572
- aiMsg!.content.some(
573
- (c) => c.type === "text" && c.text.includes("Let me ask"),
574
- ),
573
+ parts.some((c) => c.type === "text" && c.text.includes("Let me ask")),
575
574
  ).toBe(true);
576
575
  expect(aiMsg!.status).toBeUndefined();
577
576
  });
@@ -599,7 +598,8 @@ describe("AdkEventAccumulator - HITL requires-action", () => {
599
598
  );
600
599
 
601
600
  const aiMsg = msgs[0] as AdkMessage & { type: "ai" };
602
- expect(aiMsg.content.some((c) => c.type === "text")).toBe(true);
601
+ const parts = aiMsg.content as AdkMessageContentPart[];
602
+ expect(parts.some((c) => c.type === "text")).toBe(true);
603
603
  expect(aiMsg.tool_calls).toHaveLength(1);
604
604
  expect(aiMsg.tool_calls![0]!.id).toBe("mixed-tc-1");
605
605
  expect(aiMsg.status).toBeUndefined();
@@ -84,8 +84,8 @@ describe("createAdkSessionAdapter - list", () => {
84
84
  });
85
85
  await adapter.list();
86
86
 
87
- const init = mockFetch.mock.calls[0]![1];
88
- expect((init?.headers as Record<string, string>).Authorization).toBe(
87
+ const init = mockFetch.mock.calls[0]![1]!;
88
+ expect((init.headers as Record<string, string>).Authorization).toBe(
89
89
  "Bearer tok",
90
90
  );
91
91
  });
@@ -101,8 +101,8 @@ describe("createAdkSessionAdapter - list", () => {
101
101
  });
102
102
  await adapter.list();
103
103
 
104
- const init = mockFetch.mock.calls[0]![1];
105
- expect((init?.headers as Record<string, string>)["X-Dynamic"]).toBe("val");
104
+ const init = mockFetch.mock.calls[0]![1]!;
105
+ expect((init.headers as Record<string, string>)["X-Dynamic"]).toBe("val");
106
106
  });
107
107
  });
108
108
 
@@ -212,7 +212,7 @@ describe("createAdkSessionAdapter - no-op methods", () => {
212
212
  describe("createAdkSessionAdapter - generateTitle", () => {
213
213
  it("returns an empty ReadableStream", async () => {
214
214
  const { adapter } = createAdkSessionAdapter(baseOptions);
215
- const result = await adapter.generateTitle("s1");
215
+ const result = await adapter.generateTitle("s1", []);
216
216
  expect(result).toBeInstanceOf(ReadableStream);
217
217
  });
218
218
  });
@@ -332,8 +332,8 @@ describe("createAdkSessionAdapter - load", () => {
332
332
  });
333
333
  await load("s1");
334
334
 
335
- const init = mockFetch.mock.calls[0]![1];
336
- expect((init?.headers as Record<string, string>).Authorization).toBe(
335
+ const init = mockFetch.mock.calls[0]![1]!;
336
+ expect((init.headers as Record<string, string>).Authorization).toBe(
337
337
  "Bearer tok",
338
338
  );
339
339
  });
@@ -5,7 +5,7 @@ import type { AdkMessage } from "./types";
5
5
  describe("convertAdkMessage - human messages", () => {
6
6
  it("converts a human message with string content to user role", () => {
7
7
  const msg: AdkMessage = { id: "m1", type: "human", content: "Hello" };
8
- const result = convertAdkMessage(msg);
8
+ const result = convertAdkMessage(msg, {});
9
9
  expect(result).toMatchObject({
10
10
  role: "user",
11
11
  id: "m1",
@@ -19,7 +19,7 @@ describe("convertAdkMessage - human messages", () => {
19
19
  type: "human",
20
20
  content: [{ type: "text", text: "Hello" }],
21
21
  };
22
- const result = convertAdkMessage(msg);
22
+ const result = convertAdkMessage(msg, {});
23
23
  expect(result).toMatchObject({
24
24
  role: "user",
25
25
  content: [{ type: "text", text: "Hello" }],
@@ -34,7 +34,7 @@ describe("convertAdkMessage - ai messages", () => {
34
34
  type: "ai",
35
35
  content: [{ type: "text", text: "Hi there" }],
36
36
  };
37
- const result = convertAdkMessage(msg);
37
+ const result = convertAdkMessage(msg, {});
38
38
  expect(result).toMatchObject({
39
39
  role: "assistant",
40
40
  id: "m1",
@@ -48,7 +48,7 @@ describe("convertAdkMessage - ai messages", () => {
48
48
  type: "ai",
49
49
  content: [{ type: "reasoning", text: "Let me think..." }],
50
50
  };
51
- const result = convertAdkMessage(msg);
51
+ const result = convertAdkMessage(msg, {});
52
52
  expect(result).toMatchObject({
53
53
  content: [{ type: "reasoning", text: "Let me think..." }],
54
54
  });
@@ -60,7 +60,7 @@ describe("convertAdkMessage - ai messages", () => {
60
60
  type: "ai",
61
61
  content: [{ type: "image", mimeType: "image/png", data: "abc123" }],
62
62
  };
63
- const result = convertAdkMessage(msg);
63
+ const result = convertAdkMessage(msg, {});
64
64
  expect(result).toMatchObject({
65
65
  content: [{ type: "image", image: "data:image/png;base64,abc123" }],
66
66
  });
@@ -72,7 +72,7 @@ describe("convertAdkMessage - ai messages", () => {
72
72
  type: "ai",
73
73
  content: [{ type: "image_url", url: "https://example.com/img.png" }],
74
74
  };
75
- const result = convertAdkMessage(msg);
75
+ const result = convertAdkMessage(msg, {});
76
76
  expect(result).toMatchObject({
77
77
  content: [{ type: "image", image: "https://example.com/img.png" }],
78
78
  });
@@ -91,7 +91,7 @@ describe("convertAdkMessage - ai messages", () => {
91
91
  },
92
92
  ],
93
93
  };
94
- const result = convertAdkMessage(msg);
94
+ const result = convertAdkMessage(msg, {});
95
95
  expect(result).toMatchObject({
96
96
  content: [
97
97
  {
@@ -116,7 +116,7 @@ describe("convertAdkMessage - ai messages", () => {
116
116
  },
117
117
  ],
118
118
  };
119
- const result = convertAdkMessage(msg);
119
+ const result = convertAdkMessage(msg, {});
120
120
  expect(result).toMatchObject({
121
121
  content: [
122
122
  {
@@ -137,7 +137,7 @@ describe("convertAdkMessage - ai messages", () => {
137
137
  type: "ai",
138
138
  content: [{ type: "code", code: "print(1)", language: "python" }],
139
139
  };
140
- const result = convertAdkMessage(msg);
140
+ const result = convertAdkMessage(msg, {});
141
141
  expect(result).toMatchObject({
142
142
  content: [
143
143
  {
@@ -155,7 +155,7 @@ describe("convertAdkMessage - ai messages", () => {
155
155
  type: "ai",
156
156
  content: [{ type: "code_result", output: "1", outcome: "OUTCOME_OK" }],
157
157
  };
158
- const result = convertAdkMessage(msg);
158
+ const result = convertAdkMessage(msg, {});
159
159
  expect(result).toMatchObject({
160
160
  content: [
161
161
  {
@@ -174,7 +174,7 @@ describe("convertAdkMessage - ai messages", () => {
174
174
  content: [],
175
175
  tool_calls: [{ id: "tc-1", name: "search", args: { q: "test" } }],
176
176
  };
177
- const result = convertAdkMessage(msg);
177
+ const result = convertAdkMessage(msg, {});
178
178
  expect(result).toMatchObject({
179
179
  content: [
180
180
  {
@@ -194,7 +194,7 @@ describe("convertAdkMessage - ai messages", () => {
194
194
  content: [{ type: "text", text: "done" }],
195
195
  status: { type: "complete", reason: "stop" },
196
196
  };
197
- const result = convertAdkMessage(msg);
197
+ const result = convertAdkMessage(msg, {});
198
198
  expect(result).toMatchObject({
199
199
  status: { type: "complete", reason: "stop" },
200
200
  });
@@ -208,7 +208,7 @@ describe("convertAdkMessage - ai messages", () => {
208
208
  author: "search_agent",
209
209
  branch: "root.search_agent",
210
210
  };
211
- const result = convertAdkMessage(msg);
211
+ const result = convertAdkMessage(msg, {});
212
212
  expect(result).toMatchObject({
213
213
  metadata: {
214
214
  custom: { author: "search_agent", branch: "root.search_agent" },
@@ -222,7 +222,7 @@ describe("convertAdkMessage - ai messages", () => {
222
222
  type: "ai",
223
223
  content: [{ type: "text", text: "hi" }],
224
224
  };
225
- const result = convertAdkMessage(msg);
225
+ const result = convertAdkMessage(msg, {});
226
226
  expect(result).not.toHaveProperty("metadata");
227
227
  });
228
228
  });
@@ -237,7 +237,7 @@ describe("convertAdkMessage - tool messages", () => {
237
237
  content: '{"results":[]}',
238
238
  status: "success",
239
239
  };
240
- const result = convertAdkMessage(msg);
240
+ const result = convertAdkMessage(msg, {});
241
241
  expect(result).toMatchObject({
242
242
  role: "tool",
243
243
  toolCallId: "tc-1",
@@ -256,7 +256,7 @@ describe("convertAdkMessage - tool messages", () => {
256
256
  content: "Failed",
257
257
  status: "error",
258
258
  };
259
- const result = convertAdkMessage(msg);
259
+ const result = convertAdkMessage(msg, {});
260
260
  expect(result).toMatchObject({ isError: true });
261
261
  });
262
262
  });
package/src/hooks.ts CHANGED
@@ -1,5 +1,3 @@
1
- /// <reference types="@assistant-ui/core/store" />
2
-
3
1
  import { useAui, useAuiState } from "@assistant-ui/store";
4
2
  import { v4 as uuidv4 } from "uuid";
5
3
  import type { ReadonlyJSONValue } from "assistant-stream/utils";
package/src/index.ts CHANGED
@@ -1,12 +1,6 @@
1
- export {
2
- useAdkRuntime,
3
- type UseAdkRuntimeOptions,
4
- } from "./useAdkRuntime";
1
+ export { useAdkRuntime, type UseAdkRuntimeOptions } from "./useAdkRuntime";
5
2
 
6
- export {
7
- useAdkMessages,
8
- type UseAdkMessagesOptions,
9
- } from "./useAdkMessages";
3
+ export { useAdkMessages, type UseAdkMessagesOptions } from "./useAdkMessages";
10
4
 
11
5
  export { convertAdkMessage } from "./convertAdkMessages";
12
6
 
@@ -37,10 +31,7 @@ export { toAdkStructuredEvents } from "./structuredEvents";
37
31
 
38
32
  export { AdkEventAccumulator } from "./AdkEventAccumulator";
39
33
 
40
- export {
41
- createAdkStream,
42
- type CreateAdkStreamOptions,
43
- } from "./AdkClient";
34
+ export { createAdkStream, type CreateAdkStreamOptions } from "./AdkClient";
44
35
 
45
36
  export {
46
37
  createAdkSessionAdapter,
@@ -1,4 +1,3 @@
1
- /// <reference types="@assistant-ui/core/store" />
2
1
  import { useState, useCallback, useRef, useMemo } from "react";
3
2
  import { v4 as uuidv4 } from "uuid";
4
3
  import { useAui } from "@assistant-ui/store";
@@ -1,4 +1,3 @@
1
- /// <reference types="@assistant-ui/core/store" />
2
1
  import { useEffect, useRef, useState } from "react";
3
2
  import {
4
3
  getExternalStoreMessages,
@@ -8,14 +7,13 @@ import {
8
7
  type SpeechSynthesisAdapter,
9
8
  type AppendMessage,
10
9
  type ThreadMessage,
10
+ type ToolExecutionStatus,
11
11
  } from "@assistant-ui/core";
12
12
  import {
13
- type ToolExecutionStatus,
14
13
  useCloudThreadListAdapter,
15
14
  useRemoteThreadListRuntime,
16
15
  useExternalMessageConverter,
17
16
  useExternalStoreRuntime,
18
- useToolInvocations,
19
17
  } from "@assistant-ui/core/react";
20
18
  import { useAui } from "@assistant-ui/store";
21
19
  import type { AssistantCloud } from "assistant-cloud";
@@ -235,41 +233,12 @@ const useAdkRuntimeImpl = ({
235
233
  const threadMessagesRef = useRef(threadMessages);
236
234
  threadMessagesRef.current = threadMessages;
237
235
 
238
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
239
- const [runtimeRef] = useState(() => ({
240
- get current() {
241
- return runtime;
242
- },
243
- }));
244
-
245
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
246
- const toolInvocations = useToolInvocations({
247
- state: { messages: threadMessages, isRunning: effectiveIsRunning },
248
- getTools: () => runtimeRef.current.thread.getModelContext().tools,
249
- onResult: (command) => {
250
- if (command.type === "add-tool-result") {
251
- void handleSendMessage(
252
- [
253
- {
254
- id: uuidv4(),
255
- type: "tool",
256
- name: command.toolName,
257
- tool_call_id: command.toolCallId,
258
- content: JSON.stringify(command.result),
259
- status: command.isError ? "error" : "success",
260
- },
261
- ],
262
- {},
263
- );
264
- }
265
- },
266
- setToolStatuses,
267
- });
268
-
269
236
  // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
270
237
  const runtime = useExternalStoreRuntime({
271
238
  isRunning: effectiveIsRunning,
272
239
  messages: threadMessages,
240
+ unstable_enableToolInvocations: true,
241
+ setToolStatuses,
273
242
  adapters: { attachments, dictation, feedback, speech },
274
243
  extras: {
275
244
  [symbolAdkRuntimeExtras]: true,
@@ -284,8 +253,6 @@ const useAdkRuntimeImpl = ({
284
253
  send: handleSendMessage,
285
254
  } satisfies AdkRuntimeExtras,
286
255
  onNew: async (msg) => {
287
- await toolInvocations.abort();
288
-
289
256
  const cancellations =
290
257
  autoCancelPendingToolCalls !== false
291
258
  ? getPendingCancellations(messages, longRunningToolIds)
@@ -305,7 +272,6 @@ const useAdkRuntimeImpl = ({
305
272
  },
306
273
  onEdit: getCheckpointId
307
274
  ? async (msg) => {
308
- await toolInvocations.abort();
309
275
  const truncated = truncateAdkMessages(
310
276
  threadMessagesRef.current,
311
277
  msg.parentId,
@@ -332,7 +298,6 @@ const useAdkRuntimeImpl = ({
332
298
  : undefined,
333
299
  onReload: getCheckpointId
334
300
  ? async (parentId, config) => {
335
- await toolInvocations.abort();
336
301
  const truncated = truncateAdkMessages(
337
302
  threadMessagesRef.current,
338
303
  parentId,
@@ -370,12 +335,9 @@ const useAdkRuntimeImpl = ({
370
335
  {},
371
336
  );
372
337
  },
373
- onResumeToolCall: (options) =>
374
- toolInvocations.resume(options.toolCallId, options.payload),
375
338
  onCancel: unstable_allowCancellation
376
339
  ? async () => {
377
340
  cancel();
378
- await toolInvocations.abort();
379
341
  }
380
342
  : undefined,
381
343
  });