@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 +0 -1
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js.map +1 -1
- package/dist/useAdkMessages.d.ts +0 -1
- package/dist/useAdkMessages.d.ts.map +1 -1
- package/dist/useAdkMessages.js.map +1 -1
- package/dist/useAdkRuntime.d.ts +0 -1
- package/dist/useAdkRuntime.d.ts.map +1 -1
- package/dist/useAdkRuntime.js +3 -27
- package/dist/useAdkRuntime.js.map +1 -1
- package/package.json +1 -1
- package/src/AdkEventAccumulator.test.ts +5 -5
- package/src/AdkSessionAdapter.test.ts +7 -7
- package/src/convertAdkMessages.test.ts +16 -16
- package/src/hooks.ts +0 -2
- package/src/index.ts +3 -12
- package/src/useAdkMessages.ts +0 -1
- package/src/useAdkRuntime.ts +3 -41
package/dist/hooks.d.ts
CHANGED
package/dist/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","names":[],"sources":["../src/hooks.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","names":[],"sources":["../src/hooks.ts"],"mappings":";;;;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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"}
|
package/dist/useAdkMessages.d.ts
CHANGED
|
@@ -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":";;;
|
|
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"}
|
package/dist/useAdkRuntime.d.ts
CHANGED
|
@@ -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":";;;;;
|
|
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"}
|
package/dist/useAdkRuntime.js
CHANGED
|
@@ -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
|
|
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
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
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,
|
package/src/useAdkMessages.ts
CHANGED
package/src/useAdkRuntime.ts
CHANGED
|
@@ -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
|
});
|