@convai/web-sdk 1.8.0-beta.6 → 1.8.0-beta.8
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/README.md +303 -1
- package/dist/core/ConvaiClient.d.ts +59 -2
- package/dist/core/ConvaiClient.d.ts.map +1 -1
- package/dist/core/ConvaiClient.js +457 -6
- package/dist/core/ConvaiClient.js.map +1 -1
- package/dist/core/MessageHandler.d.ts +11 -0
- package/dist/core/MessageHandler.d.ts.map +1 -1
- package/dist/core/MessageHandler.js +325 -30
- package/dist/core/MessageHandler.js.map +1 -1
- package/dist/core/SSESession.js +2 -2
- package/dist/core/SSESession.js.map +1 -1
- package/dist/core/connectRequest.d.ts +38 -3
- package/dist/core/connectRequest.d.ts.map +1 -1
- package/dist/core/connectRequest.js +57 -11
- package/dist/core/connectRequest.js.map +1 -1
- package/dist/core/index.d.ts +5 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +8 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/logicalTurn.d.ts +4 -1
- package/dist/core/logicalTurn.d.ts.map +1 -1
- package/dist/core/logicalTurn.js +35 -4
- package/dist/core/logicalTurn.js.map +1 -1
- package/dist/core/modelOutput.d.ts +40 -0
- package/dist/core/modelOutput.d.ts.map +1 -0
- package/dist/core/modelOutput.js +187 -0
- package/dist/core/modelOutput.js.map +1 -0
- package/dist/core/publishedChat.d.ts +9 -0
- package/dist/core/publishedChat.d.ts.map +1 -0
- package/dist/core/publishedChat.js +13 -0
- package/dist/core/publishedChat.js.map +1 -0
- package/dist/core/types.d.ts +225 -25
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/embed/ConvaiChatElement.d.ts +103 -0
- package/dist/embed/ConvaiChatElement.d.ts.map +1 -0
- package/dist/embed/ConvaiChatElement.js +679 -0
- package/dist/embed/ConvaiChatElement.js.map +1 -0
- package/dist/embed/browser.d.ts +3 -0
- package/dist/embed/browser.d.ts.map +1 -0
- package/dist/embed/browser.js +5 -0
- package/dist/embed/browser.js.map +1 -0
- package/dist/embed/chat-embed-v1.js +200 -0
- package/dist/embed/chat-embed-v1.js.map +7 -0
- package/dist/embed/index.d.ts +9 -0
- package/dist/embed/index.d.ts.map +1 -0
- package/dist/embed/index.js +9 -0
- package/dist/embed/index.js.map +1 -0
- package/dist/embed/publicationApi.d.ts +23 -0
- package/dist/embed/publicationApi.d.ts.map +1 -0
- package/dist/embed/publicationApi.js +141 -0
- package/dist/embed/publicationApi.js.map +1 -0
- package/dist/react/components/ConvaiWidget.d.ts +11 -1
- package/dist/react/components/ConvaiWidget.d.ts.map +1 -1
- package/dist/react/components/ConvaiWidget.js +67 -11
- package/dist/react/components/ConvaiWidget.js.map +1 -1
- package/dist/react/components/rtc-widget/components/MarkdownRenderer.d.ts +7 -0
- package/dist/react/components/rtc-widget/components/MarkdownRenderer.d.ts.map +1 -1
- package/dist/react/components/rtc-widget/components/MarkdownRenderer.js +111 -17
- package/dist/react/components/rtc-widget/components/MarkdownRenderer.js.map +1 -1
- package/dist/react/components/rtc-widget/components/UserMessage.js +1 -1
- package/dist/react/components/rtc-widget/components/UserMessage.js.map +1 -1
- package/dist/react/components/rtc-widget/components/conviComponents/SettingsTray.d.ts +1 -1
- package/dist/react/components/rtc-widget/components/conviComponents/SettingsTray.d.ts.map +1 -1
- package/dist/react/components/rtc-widget/components/conviComponents/SettingsTray.js +2 -2
- package/dist/react/components/rtc-widget/components/conviComponents/SettingsTray.js.map +1 -1
- package/dist/react/hooks/useConvaiClient.d.ts +2 -0
- package/dist/react/hooks/useConvaiClient.d.ts.map +1 -1
- package/dist/react/hooks/useConvaiClient.js +8 -0
- package/dist/react/hooks/useConvaiClient.js.map +1 -1
- package/dist/react/index.d.ts +4 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +8 -1
- package/dist/react/index.js.map +1 -1
- package/dist/utils/inlineMarkdown.d.ts +22 -0
- package/dist/utils/inlineMarkdown.d.ts.map +1 -1
- package/dist/utils/inlineMarkdown.js +84 -7
- package/dist/utils/inlineMarkdown.js.map +1 -1
- package/dist/vanilla/ConvaiWidget.d.ts.map +1 -1
- package/dist/vanilla/ConvaiWidget.js +290 -43
- package/dist/vanilla/ConvaiWidget.js.map +1 -1
- package/dist/vanilla/WidgetEventSubscriptions.d.ts +15 -0
- package/dist/vanilla/WidgetEventSubscriptions.d.ts.map +1 -0
- package/dist/vanilla/WidgetEventSubscriptions.js +37 -0
- package/dist/vanilla/WidgetEventSubscriptions.js.map +1 -0
- package/dist/vanilla/index.d.ts +3 -1
- package/dist/vanilla/index.d.ts.map +1 -1
- package/dist/vanilla/index.js +3 -1
- package/dist/vanilla/index.js.map +1 -1
- package/dist/vanilla/styles.d.ts.map +1 -1
- package/dist/vanilla/styles.js +12 -0
- package/dist/vanilla/styles.js.map +1 -1
- package/dist/vanilla/types.d.ts +8 -1
- package/dist/vanilla/types.d.ts.map +1 -1
- package/dist/vanilla/types.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +48 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SettingsTray.js","sourceRoot":"","sources":["../../../../../../src/react/components/rtc-widget/components/conviComponents/SettingsTray.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from \"react\";\nimport { AnimatePresence } from \"framer-motion\";\nimport { LiaRedoAltSolid } from \"react-icons/lia\";\nimport { IoVideocam, IoVideocamOff } from \"react-icons/io5\";\nimport { MdScreenShare, MdStopScreenShare } from \"react-icons/md\";\nimport { aeroTheme } from \"../../styles/theme\";\nimport { iosTransitions } from \"../../styles/framerConfig\";\nimport {\n SettingsTray as StyledSettingsTray,\n SettingsOption,\n} from \"../../styles/styledComponents\";\n\ninterface SettingsTrayProps {\n isOpen: boolean;\n isVideoVisible?: boolean;\n isScreenShareActive?: boolean;\n onReset: () => void;\n onDisconnect?: () => void;\n onToggleVideo?: () => void;\n onToggleScreenShare?: () => void;\n}\n\nexport const SettingsTray = ({\n isOpen,\n isVideoVisible,\n isScreenShareActive,\n onReset,\n onDisconnect,\n onToggleVideo,\n onToggleScreenShare,\n}: SettingsTrayProps) => {\n if (!isOpen) return null;\n\n return (\n <AnimatePresence>\n <StyledSettingsTray\n data-settings-tray\n initial={{ opacity: 0, y: -10, scale: 0.95 }}\n animate={{ opacity: 1, y: 0, scale: 1 }}\n exit={{ opacity: 0, y: -10, scale: 0.95 }}\n transition={iosTransitions.fadePop}\n style={{\n position: \"absolute\",\n top: \"60px\",\n right: \"16px\",\n zIndex: 9999,\n }}\n onClick={(e: React.MouseEvent) => e.stopPropagation()}\n >\n {/* Horizontal Settings Row */}\n <div\n style={{\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: \"center\",\n padding: \"8px\",\n gap: \"4px\",\n }}\n >\n <SettingsOption\n onClick={onReset}\n whileHover={{ scale: 1.02 }}\n whileTap={{ scale: 0.98 }}\n transition={iosTransitions.snappy}\n style={{\n cursor: \"pointer\",\n flexDirection: \"column\",\n gap: \"4px\",\n padding: \"8px 12px\",\n }}\n aria-label=\"Reset\"\n title=\"Reset\"\n >\n <LiaRedoAltSolid size={18} />\n <span style={{ fontSize: \"10px\", fontWeight: 500 }}>Reset</span>\n </SettingsOption>\n\n {/* Video Toggle Button */}\n {onToggleVideo && (\n <SettingsOption\n onClick={(e: React.MouseEvent) => {\n e.stopPropagation();\n onToggleVideo();\n }}\n whileHover={{ scale: 1.02 }}\n whileTap={{ scale: 0.98 }}\n transition={iosTransitions.snappy}\n style={{\n cursor: \"pointer\",\n flexDirection: \"column\",\n gap: \"4px\",\n padding: \"8px 12px\",\n backgroundColor: isVideoVisible\n ? \"rgba(16, 185, 129, 0.15)\"\n : \"transparent\",\n color: isVideoVisible\n ? \"#10b981\"\n : aeroTheme.colors.text.primary,\n }}\n aria-label={isVideoVisible ? \"Hide Video\" : \"Show Video\"}\n title={isVideoVisible ? \"Hide Video\" : \"Show Video\"}\n >\n {isVideoVisible ? <IoVideocam size={18} /> : <IoVideocamOff size={18} />}\n <span style={{ fontSize: \"10px\", fontWeight: 500 }}>Video</span>\n </SettingsOption>\n )}\n\n {/* Screen Share Toggle Button */}\n {onToggleScreenShare && (\n <SettingsOption\n onClick={(e: React.MouseEvent) => {\n e.stopPropagation();\n onToggleScreenShare();\n }}\n whileHover={{ scale: 1.02 }}\n whileTap={{ scale: 0.98 }}\n transition={iosTransitions.snappy}\n style={{\n cursor: \"pointer\",\n flexDirection: \"column\",\n gap: \"4px\",\n padding: \"8px 12px\",\n backgroundColor: isScreenShareActive\n ? \"rgba(16, 185, 129, 0.15)\"\n : \"transparent\",\n color: isScreenShareActive\n ? \"#10b981\"\n : aeroTheme.colors.text.primary,\n }}\n aria-label={isScreenShareActive ? \"Stop Sharing\" : \"Share Screen\"}\n title={isScreenShareActive ? \"Stop Sharing\" : \"Share Screen\"}\n >\n {isScreenShareActive ? <MdStopScreenShare size={18} /> : <MdScreenShare size={18} />}\n <span style={{ fontSize: \"10px\", fontWeight: 500 }}>Screen</span>\n </SettingsOption>\n )}\n\n {/* Disconnect Button */}\n {onDisconnect && (\n <SettingsOption\n onClick={(e: React.MouseEvent) => {\n e.stopPropagation();\n onDisconnect();\n }}\n whileHover={{ scale: 1.02 }}\n whileTap={{ scale: 0.98 }}\n transition={iosTransitions.snappy}\n style={{\n cursor: \"pointer\",\n flexDirection: \"column\",\n gap: \"4px\",\n padding: \"8px 12px\",\n backgroundColor: \"rgba(239, 68, 68, 0.1)\",\n color: \"#ef4444\",\n }}\n aria-label=\"Disconnect\"\n title=\"Disconnect\"\n >\n {/* Placeholder for icon - user will add their own */}\n <span style={{ fontSize: \"18px\" }}>⏻</span>\n <span style={{ fontSize: \"10px\", fontWeight: 500 }}>Disconnect</span>\n </SettingsOption>\n )}\n </div>\n </StyledSettingsTray>\n </AnimatePresence>\n );\n};\n\n"]}
|
|
1
|
+
{"version":3,"file":"SettingsTray.js","sourceRoot":"","sources":["../../../../../../src/react/components/rtc-widget/components/conviComponents/SettingsTray.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from \"react\";\nimport { AnimatePresence } from \"framer-motion\";\nimport { LiaRedoAltSolid } from \"react-icons/lia\";\nimport { IoVideocam, IoVideocamOff } from \"react-icons/io5\";\nimport { MdScreenShare, MdStopScreenShare } from \"react-icons/md\";\nimport { aeroTheme } from \"../../styles/theme\";\nimport { iosTransitions } from \"../../styles/framerConfig\";\nimport {\n SettingsTray as StyledSettingsTray,\n SettingsOption,\n} from \"../../styles/styledComponents\";\n\ninterface SettingsTrayProps {\n isOpen: boolean;\n isVideoVisible?: boolean;\n isScreenShareActive?: boolean;\n onReset?: () => void;\n onDisconnect?: () => void;\n onToggleVideo?: () => void;\n onToggleScreenShare?: () => void;\n}\n\nexport const SettingsTray = ({\n isOpen,\n isVideoVisible,\n isScreenShareActive,\n onReset,\n onDisconnect,\n onToggleVideo,\n onToggleScreenShare,\n}: SettingsTrayProps) => {\n if (!isOpen) return null;\n\n return (\n <AnimatePresence>\n <StyledSettingsTray\n data-settings-tray\n initial={{ opacity: 0, y: -10, scale: 0.95 }}\n animate={{ opacity: 1, y: 0, scale: 1 }}\n exit={{ opacity: 0, y: -10, scale: 0.95 }}\n transition={iosTransitions.fadePop}\n style={{\n position: \"absolute\",\n top: \"60px\",\n right: \"16px\",\n zIndex: 9999,\n }}\n onClick={(e: React.MouseEvent) => e.stopPropagation()}\n >\n {/* Horizontal Settings Row */}\n <div\n style={{\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: \"center\",\n padding: \"8px\",\n gap: \"4px\",\n }}\n >\n {onReset && (\n <SettingsOption\n onClick={onReset}\n whileHover={{ scale: 1.02 }}\n whileTap={{ scale: 0.98 }}\n transition={iosTransitions.snappy}\n style={{\n cursor: \"pointer\",\n flexDirection: \"column\",\n gap: \"4px\",\n padding: \"8px 12px\",\n }}\n aria-label=\"Reset\"\n title=\"Reset\"\n >\n <LiaRedoAltSolid size={18} />\n <span style={{ fontSize: \"10px\", fontWeight: 500 }}>Reset</span>\n </SettingsOption>\n )}\n\n {/* Video Toggle Button */}\n {onToggleVideo && (\n <SettingsOption\n onClick={(e: React.MouseEvent) => {\n e.stopPropagation();\n onToggleVideo();\n }}\n whileHover={{ scale: 1.02 }}\n whileTap={{ scale: 0.98 }}\n transition={iosTransitions.snappy}\n style={{\n cursor: \"pointer\",\n flexDirection: \"column\",\n gap: \"4px\",\n padding: \"8px 12px\",\n backgroundColor: isVideoVisible\n ? \"rgba(16, 185, 129, 0.15)\"\n : \"transparent\",\n color: isVideoVisible\n ? \"#10b981\"\n : aeroTheme.colors.text.primary,\n }}\n aria-label={isVideoVisible ? \"Hide Video\" : \"Show Video\"}\n title={isVideoVisible ? \"Hide Video\" : \"Show Video\"}\n >\n {isVideoVisible ? <IoVideocam size={18} /> : <IoVideocamOff size={18} />}\n <span style={{ fontSize: \"10px\", fontWeight: 500 }}>Video</span>\n </SettingsOption>\n )}\n\n {/* Screen Share Toggle Button */}\n {onToggleScreenShare && (\n <SettingsOption\n onClick={(e: React.MouseEvent) => {\n e.stopPropagation();\n onToggleScreenShare();\n }}\n whileHover={{ scale: 1.02 }}\n whileTap={{ scale: 0.98 }}\n transition={iosTransitions.snappy}\n style={{\n cursor: \"pointer\",\n flexDirection: \"column\",\n gap: \"4px\",\n padding: \"8px 12px\",\n backgroundColor: isScreenShareActive\n ? \"rgba(16, 185, 129, 0.15)\"\n : \"transparent\",\n color: isScreenShareActive\n ? \"#10b981\"\n : aeroTheme.colors.text.primary,\n }}\n aria-label={isScreenShareActive ? \"Stop Sharing\" : \"Share Screen\"}\n title={isScreenShareActive ? \"Stop Sharing\" : \"Share Screen\"}\n >\n {isScreenShareActive ? <MdStopScreenShare size={18} /> : <MdScreenShare size={18} />}\n <span style={{ fontSize: \"10px\", fontWeight: 500 }}>Screen</span>\n </SettingsOption>\n )}\n\n {/* Disconnect Button */}\n {onDisconnect && (\n <SettingsOption\n onClick={(e: React.MouseEvent) => {\n e.stopPropagation();\n onDisconnect();\n }}\n whileHover={{ scale: 1.02 }}\n whileTap={{ scale: 0.98 }}\n transition={iosTransitions.snappy}\n style={{\n cursor: \"pointer\",\n flexDirection: \"column\",\n gap: \"4px\",\n padding: \"8px 12px\",\n backgroundColor: \"rgba(239, 68, 68, 0.1)\",\n color: \"#ef4444\",\n }}\n aria-label=\"Disconnect\"\n title=\"Disconnect\"\n >\n {/* Placeholder for icon - user will add their own */}\n <span style={{ fontSize: \"18px\" }}>⏻</span>\n <span style={{ fontSize: \"10px\", fontWeight: 500 }}>Disconnect</span>\n </SettingsOption>\n )}\n </div>\n </StyledSettingsTray>\n </AnimatePresence>\n );\n};\n"]}
|
|
@@ -26,6 +26,8 @@ import type { ConvaiConfig, IConvaiClient, ChatMessage } from "../../core/types.
|
|
|
26
26
|
* ```
|
|
27
27
|
*/
|
|
28
28
|
export declare const useConvaiClient: (config?: ConvaiConfig) => IConvaiClient & {
|
|
29
|
+
/** This hook always supplies the publication connector, unlike generic adapters. */
|
|
30
|
+
connectWithPublicationGrant: NonNullable<IConvaiClient["connectWithPublicationGrant"]>;
|
|
29
31
|
activity: string;
|
|
30
32
|
chatMessages: ChatMessage[];
|
|
31
33
|
isAudioMuted: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useConvaiClient.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useConvaiClient.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,WAAW,
|
|
1
|
+
{"version":3,"file":"useConvaiClient.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useConvaiClient.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,WAAW,EAEZ,MAAM,kBAAkB,CAAC;AAE1B;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,eAAe,GAC1B,SAAS,YAAY,KACpB,aAAa,GAAG;IACjB,oFAAoF;IACpF,2BAA2B,EAAE,WAAW,CACtC,aAAa,CAAC,6BAA6B,CAAC,CAC7C,CAAC;IACF,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,YAAY,EAAE,OAAO,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC;IACxB,mBAAmB,EAAE,OAAO,CAAC;CAuP9B,CAAC"}
|
|
@@ -161,15 +161,20 @@ export const useConvaiClient = (config) => {
|
|
|
161
161
|
const reconnect = useCallback(async () => {
|
|
162
162
|
await client.reconnect();
|
|
163
163
|
}, [client]);
|
|
164
|
+
const connectWithPublicationGrant = useCallback(async (launchToken, options) => {
|
|
165
|
+
await client.connectWithPublicationGrant(launchToken, options);
|
|
166
|
+
}, [client]);
|
|
164
167
|
// Return client interface with React-friendly additions
|
|
165
168
|
return {
|
|
166
169
|
state,
|
|
167
170
|
connectionType: client.connectionType,
|
|
171
|
+
isPublishedChatSession: client.isPublishedChatSession,
|
|
168
172
|
...(client.apiKey && { apiKey: client.apiKey }),
|
|
169
173
|
...(client.authToken && { authToken: client.authToken }),
|
|
170
174
|
characterId: client.characterId,
|
|
171
175
|
characterVersion: client.characterVersion,
|
|
172
176
|
characterReference: client.characterReference,
|
|
177
|
+
requestTraceId: client.requestTraceId,
|
|
173
178
|
connect,
|
|
174
179
|
connectWithConnectionData: client.connectWithConnectionData.bind(client),
|
|
175
180
|
joinRoom: client.joinRoom.bind(client),
|
|
@@ -180,11 +185,14 @@ export const useConvaiClient = (config) => {
|
|
|
180
185
|
roomSession: client.roomSession,
|
|
181
186
|
characters: client.characters,
|
|
182
187
|
activeMembershipId: client.activeMembershipId,
|
|
188
|
+
connectWithPublicationGrant,
|
|
183
189
|
disconnect: client.disconnect.bind(client),
|
|
184
190
|
reconnect,
|
|
185
191
|
resetSession: client.resetSession.bind(client),
|
|
186
192
|
room: client.room,
|
|
187
193
|
sendUserTextMessage: client.sendUserTextMessage.bind(client),
|
|
194
|
+
sendActionResult: client.sendActionResult.bind(client),
|
|
195
|
+
sendActionResultAndWait: client.sendActionResultAndWait.bind(client),
|
|
188
196
|
sendTriggerMessage: client.sendTriggerMessage.bind(client),
|
|
189
197
|
sendInterruptMessage: client.sendInterruptMessage.bind(client),
|
|
190
198
|
resetIdleTimer: client.resetIdleTimer.bind(client),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useConvaiClient.js","sourceRoot":"","sources":["../../../src/react/hooks/useConvaiClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAO9D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,MAAqB,EAOrB,EAAE;IACF,0EAA0E;IAC1E,0DAA0D;IAC1D,6DAA6D;IAC7D,MAAM,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;IAE9D,6BAA6B;IAC7B,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAS,MAAM,CAAC,CAAC;IACzD,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAC9C,MAAM,CAAC,YAAY,CACpB,CAAC;IACF,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CACxD,MAAM,CAAC,iBAAiB,CACzB,CAAC;IACF,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAC7D,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAU,MAAM,CAAC,UAAU,CAAC,CAAC;IAEzE,uCAAuC;IACvC,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAC9C,MAAM,CAAC,aAAa,CAAC,YAAY,CAClC,CAAC;IACF,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAClD,MAAM,CAAC,aAAa,CAAC,cAAc,CACpC,CAAC;IACF,MAAM,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,GAAG,QAAQ,CAC5D,MAAM,CAAC,mBAAmB,CAAC,mBAAmB,CAC/C,CAAC;IAEF,2BAA2B;IAC3B,MAAM,CAAC,YAAY,CAAC,GAAG,QAAQ,CAA2B,MAAM,CAAC,CAAC;IAElE,wBAAwB;IACxB,SAAS,CAAC,GAAG,EAAE;QACb,wBAAwB;QACxB,MAAM,gBAAgB,GAAG,MAAM,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC,QAAQ,EAAE,EAAE;YAC7D,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAEnB,yFAAyF;YACzF,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;gBAC1B,WAAW,CAAC,cAAc,CAAC,CAAC;YAC9B,CAAC;iBAAM,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;gBACjC,WAAW,CAAC,eAAe,CAAC,CAAC;YAC/B,CAAC;iBAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;gBAC/B,WAAW,CAAC,UAAU,CAAC,CAAC;YAC1B,CAAC;iBAAM,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;gBAChC,WAAW,CAAC,WAAW,CAAC,CAAC;YAC3B,CAAC;iBAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;gBAC/B,WAAW,CAAC,UAAU,CAAC,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACN,WAAW,CAAC,WAAW,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,2BAA2B;QAC3B,MAAM,mBAAmB,GAAG,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,CAAC,QAAQ,EAAE,EAAE;YACnE,eAAe,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,qCAAqC;QACrC,MAAM,sBAAsB,GAAG,MAAM,CAAC,EAAE,CACtC,yBAAyB,EACzB,CAAC,aAAa,EAAE,EAAE;YAChB,oBAAoB,CAAC,aAAa,CAAC,CAAC;QACtC,CAAC,CACF,CAAC;QAEF,2BAA2B;QAC3B,MAAM,aAAa,GAAG,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,CAAC,QAAQ,EAAE,EAAE;YAC7D,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,qBAAqB;QACrB,MAAM,aAAa,GAAG,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE;YAC/C,aAAa,CAAC,IAAI,CAAC,CAAC;YACpB,WAAW,CAAC,WAAW,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;QAEH,mBAAmB;QACnB,MAAM,YAAY,GAAG,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;YAC7C,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;QAEH,sBAAsB;QACtB,MAAM,eAAe,GAAG,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE;YACnD,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvB,WAAW,CAAC,cAAc,CAAC,CAAC;YAC5B,eAAe,CAAC,EAAE,CAAC,CAAC;YACpB,qCAAqC;YACrC,eAAe,CAAC,IAAI,CAAC,CAAC;YACtB,iBAAiB,CAAC,KAAK,CAAC,CAAC;YACzB,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;QAEH,yEAAyE;QACzE,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAClD,SAAS,CAAC,QAAQ,GAAG,IAAI,CAAC;QAC1B,SAAS,CAAC,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC;QACpC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QAErC,MAAM,kBAAkB,GAAG,MAAM,CAAC,EAAE,CAClC,eAAe,EACf,CAAC,KAAuB,EAAE,EAAE;YAC1B,SAAS,CAAC,SAAS,GAAG,IAAI,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACjD,CAAC,CACF,CAAC;QAEF,2CAA2C;QAC3C,MAAM,sBAAsB,GAAG,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE;YAC1D,SAAS,CAAC,SAAS,GAAG,IAAI,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,uCAAuC;QACvC,MAAM,eAAe,GAAG,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,kBAAkB,EAAE,CAAC,UAAe,EAAE,EAAE;YACtF,IAAI,UAAU,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;gBAC1C,eAAe,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,uCAAuC;QACvC,MAAM,eAAe,GAAG,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,kBAAkB,EAAE,CAAC,UAAe,EAAE,EAAE;YACtF,IAAI,UAAU,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;gBAC5C,iBAAiB,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,8CAA8C;QAC9C,MAAM,qBAAqB,GAAG,MAAM,CAAC,mBAAmB,CAAC,EAAE,CAAC,wBAAwB,EAAE,CAAC,gBAAqB,EAAE,EAAE;YAC9G,IAAI,gBAAgB,CAAC,mBAAmB,KAAK,SAAS,EAAE,CAAC;gBACvD,sBAAsB,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,+BAA+B;QAC/B,OAAO,GAAG,EAAE;YACV,gBAAgB,EAAE,CAAC;YACnB,mBAAmB,EAAE,CAAC;YACtB,sBAAsB,EAAE,CAAC;YACzB,aAAa,EAAE,CAAC;YAChB,aAAa,EAAE,CAAC;YAChB,YAAY,EAAE,CAAC;YACf,eAAe,EAAE,CAAC;YAClB,kBAAkB,EAAE,CAAC;YACrB,sBAAsB,EAAE,CAAC;YACzB,eAAe,EAAE,CAAC;YAClB,eAAe,EAAE,CAAC;YAClB,qBAAqB,EAAE,CAAC;YACxB,SAAS,CAAC,SAAS,GAAG,IAAI,CAAC;YAC3B,SAAS,CAAC,MAAM,EAAE,CAAC;QACrB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,8DAA8D;IAC9D,MAAM,OAAO,GAAG,WAAW,CACzB,KAAK,EAAE,cAA6B,EAAE,EAAE;QACtC,MAAM,WAAW,GAAG,cAAc,IAAI,YAAY,CAAC;QAEnD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,6EAA6E,CAC9E,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACpC,CAAC,EACD,CAAC,MAAM,EAAE,YAAY,CAAC,CACvB,CAAC;IAEF,oCAAoC;IACpC,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACvC,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;IAC3B,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,wDAAwD;IACxD,OAAO;QACL,KAAK;QACL,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QAC/C,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;QACxD,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;QACzC,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;QAC7C,OAAO;QACP,yBAAyB,EAAE,MAAM,CAAC,yBAAyB,CAAC,IAAI,CAAC,MAAM,CAAC;QACxE,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QACtC,aAAa,EAAE,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;QAChD,kBAAkB,EAAE,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC;QAC1D,oBAAoB,EAAE,MAAM,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC;QAC9D,qBAAqB,EAAE,MAAM,CAAC,qBAAqB,CAAC,IAAI,CAAC,MAAM,CAAC;QAChE,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;QAC7C,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;QAC1C,SAAS;QACT,YAAY,EAAE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC;QAC9C,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,mBAAmB,EAAE,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC;QAC5D,kBAAkB,EAAE,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC;QAC1D,oBAAoB,EAAE,MAAM,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC;QAC9D,cAAc,EAAE,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC;QAClD,kBAAkB,EAAE,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC;QAC1D,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC;QACxD,aAAa,EAAE,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;QAChD,aAAa,EAAE,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;QAChD,YAAY,EAAE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC;QAC9C,aAAa,EAAE,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;QAChD,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC;QACxD,mBAAmB,EAAE,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC;QAC5D,QAAQ;QACR,YAAY;QACZ,iBAAiB;QACjB,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;QAC7C,UAAU;QACV,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,mBAAmB,EAAE,MAAM,CAAC,mBAAmB;QAC/C,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,qBAAqB,EAAE,MAAM,CAAC,qBAAqB;QACnD,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;QAC3C,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC;QACxC,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC;QACxC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;QAC1C,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;QAC1B,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;QAC5B,0BAA0B;QAC1B,YAAY;QACZ,cAAc;QACd,mBAAmB;KACpB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { useState, useEffect, useCallback } from \"react\";\nimport { ConvaiClient as CoreConvaiClient } from \"../../core\";\nimport type {\n ConvaiConfig,\n IConvaiClient,\n ChatMessage,\n} from \"../../core/types\";\n\n/**\n * React hook wrapper for ConvaiClient\n * Main hook for managing Convai client connection and functionality.\n *\n * Provides a complete interface for connecting to Convai's AI-powered voice assistants,\n * managing real-time audio/video conversations, and handling various message types.\n *\n * @param config - Optional configuration to store for later connection\n * @returns {ConvaiClient & { activity: string; chatMessages: ChatMessage[] }} Complete client interface with connection state, methods, and message history\n *\n * @example\n * ```tsx\n * function App() {\n * const convaiClient = useConvaiClient({\n * apiKey: 'your-api-key',\n * characterId: 'your-character-id',\n * endUserId: 'user-uuid', // Optional: enables memory & analytics\n * enableVideo: true,\n * });\n *\n * return (\n * <ConvaiWidget convaiClient={convaiClient} />\n * );\n * }\n * ```\n */\nexport const useConvaiClient = (\n config?: ConvaiConfig,\n): IConvaiClient & {\n activity: string;\n chatMessages: ChatMessage[];\n isAudioMuted: boolean;\n isVideoEnabled: boolean;\n isScreenShareActive: boolean;\n} => {\n // Create client instance once. The config is handed to the client as well\n // as kept in the hook, so config-derived surfaces such as\n // `characterVersions` are usable before the first connect().\n const [client] = useState(() => new CoreConvaiClient(config));\n\n // React state for UI updates\n const [state, setState] = useState(client.state);\n const [activity, setActivity] = useState<string>(\"Idle\");\n const [chatMessages, setChatMessages] = useState<ChatMessage[]>(\n client.chatMessages,\n );\n const [userTranscription, setUserTranscription] = useState<string>(\n client.userTranscription,\n );\n const [isSpeaking, setIsSpeaking] = useState<boolean>(false);\n const [isBotReady, setIsBotReady] = useState<boolean>(client.isBotReady);\n \n // Reactive states for control managers\n const [isAudioMuted, setIsAudioMuted] = useState<boolean>(\n client.audioControls.isAudioMuted\n );\n const [isVideoEnabled, setIsVideoEnabled] = useState<boolean>(\n client.videoControls.isVideoEnabled\n );\n const [isScreenShareActive, setIsScreenShareActive] = useState<boolean>(\n client.screenShareControls.isScreenShareActive\n );\n\n // Store config if provided\n const [storedConfig] = useState<ConvaiConfig | undefined>(config);\n\n // Setup event listeners\n useEffect(() => {\n // State change listener\n const unsubStateChange = client.on(\"stateChange\", (newState) => {\n setState(newState);\n\n // Update activity based on state (priority: speaking > listening > thinking > connected)\n if (!newState.isConnected) {\n setActivity(\"Disconnected\");\n } else if (newState.isConnecting) {\n setActivity(\"Connecting...\");\n } else if (newState.isSpeaking) {\n setActivity(\"Speaking\");\n } else if (newState.isListening) {\n setActivity(\"Listening\");\n } else if (newState.isThinking) {\n setActivity(\"Thinking\");\n } else {\n setActivity(\"Connected\");\n }\n });\n\n // Messages change listener\n const unsubMessagesChange = client.on(\"messagesChange\", (messages) => {\n setChatMessages([...messages]);\n });\n\n // User transcription change listener\n const unsubUserTranscription = client.on(\n \"userTranscriptionChange\",\n (transcription) => {\n setUserTranscription(transcription);\n },\n );\n\n // Speaking change listener\n const unsubSpeaking = client.on(\"speakingChange\", (speaking) => {\n setIsSpeaking(speaking);\n });\n\n // Bot ready listener\n const unsubBotReady = client.on(\"botReady\", () => {\n setIsBotReady(true);\n setActivity(\"Connected\");\n });\n\n // Connect listener\n const unsubConnect = client.on(\"connect\", () => {\n setState(client.state);\n });\n\n // Disconnect listener\n const unsubDisconnect = client.on(\"disconnect\", () => {\n setIsBotReady(false);\n setState(client.state);\n setActivity(\"Disconnected\");\n setChatMessages([]);\n // Reset control states on disconnect\n setIsAudioMuted(true);\n setIsVideoEnabled(false);\n setIsScreenShareActive(false);\n });\n\n // WebSocket transport: play bot audio track via a hidden <audio> element\n const wsAudioEl = document.createElement(\"audio\");\n wsAudioEl.autoplay = true;\n wsAudioEl.dataset.convaiWs = \"true\";\n document.body.appendChild(wsAudioEl);\n\n const unsubBotAudioTrack = client.on(\n \"botAudioTrack\",\n (track: MediaStreamTrack) => {\n wsAudioEl.srcObject = new MediaStream([track]);\n },\n );\n\n // Disconnect listener also clears WS audio\n const unsubDisconnectWsAudio = client.on(\"disconnect\", () => {\n wsAudioEl.srcObject = null;\n });\n\n // Audio controls state change listener\n const unsubAudioState = client.audioControls.on(\"audioStateChange\", (audioState: any) => {\n if (audioState.isAudioMuted !== undefined) {\n setIsAudioMuted(audioState.isAudioMuted);\n }\n });\n\n // Video controls state change listener\n const unsubVideoState = client.videoControls.on(\"videoStateChange\", (videoState: any) => {\n if (videoState.isVideoEnabled !== undefined) {\n setIsVideoEnabled(videoState.isVideoEnabled);\n }\n });\n\n // Screen share controls state change listener\n const unsubScreenShareState = client.screenShareControls.on(\"screenShareStateChange\", (screenShareState: any) => {\n if (screenShareState.isScreenShareActive !== undefined) {\n setIsScreenShareActive(screenShareState.isScreenShareActive);\n }\n });\n\n // Cleanup listeners on unmount\n return () => {\n unsubStateChange();\n unsubMessagesChange();\n unsubUserTranscription();\n unsubSpeaking();\n unsubBotReady();\n unsubConnect();\n unsubDisconnect();\n unsubBotAudioTrack();\n unsubDisconnectWsAudio();\n unsubAudioState();\n unsubVideoState();\n unsubScreenShareState();\n wsAudioEl.srcObject = null;\n wsAudioEl.remove();\n };\n }, [client]);\n\n // Create enhanced connect function that can use stored config\n const connect = useCallback(\n async (configOverride?: ConvaiConfig) => {\n const finalConfig = configOverride || storedConfig;\n\n if (!finalConfig) {\n throw new Error(\n \"No configuration provided. Pass config to useConvaiClient() or to connect()\",\n );\n }\n\n await client.connect(finalConfig);\n },\n [client, storedConfig],\n );\n\n // Create reconnect function wrapper\n const reconnect = useCallback(async () => {\n await client.reconnect();\n }, [client]);\n\n // Return client interface with React-friendly additions\n return {\n state,\n connectionType: client.connectionType,\n ...(client.apiKey && { apiKey: client.apiKey }),\n ...(client.authToken && { authToken: client.authToken }),\n characterId: client.characterId,\n characterVersion: client.characterVersion,\n characterReference: client.characterReference,\n connect,\n connectWithConnectionData: client.connectWithConnectionData.bind(client),\n joinRoom: client.joinRoom.bind(client),\n appendMessage: client.appendMessage.bind(client),\n toggleUsageUpdates: client.toggleUsageUpdates.bind(client),\n setInteractionTarget: client.setInteractionTarget.bind(client),\n updateCharacterRoster: client.updateCharacterRoster.bind(client),\n roomSession: client.roomSession,\n characters: client.characters,\n activeMembershipId: client.activeMembershipId,\n disconnect: client.disconnect.bind(client),\n reconnect,\n resetSession: client.resetSession.bind(client),\n room: client.room,\n sendUserTextMessage: client.sendUserTextMessage.bind(client),\n sendTriggerMessage: client.sendTriggerMessage.bind(client),\n sendInterruptMessage: client.sendInterruptMessage.bind(client),\n resetIdleTimer: client.resetIdleTimer.bind(client),\n updateTemplateKeys: client.updateTemplateKeys.bind(client),\n updateDynamicInfo: client.updateDynamicInfo.bind(client),\n updateContext: client.updateContext.bind(client),\n updateEmotion: client.updateEmotion.bind(client),\n visionStatus: client.visionStatus.bind(client),\n visionTrigger: client.visionTrigger.bind(client),\n respondModeUpdate: client.respondModeUpdate.bind(client),\n updateSceneMetadata: client.updateSceneMetadata.bind(client),\n activity,\n chatMessages,\n userTranscription,\n characterSessionId: client.characterSessionId,\n isBotReady,\n audioControls: client.audioControls,\n videoControls: client.videoControls,\n screenShareControls: client.screenShareControls,\n blendshapeQueue: client.blendshapeQueue,\n conversationSessionId: client.conversationSessionId,\n memoryManager: client.memoryManager,\n characterVersions: client.characterVersions,\n toggleTts: client.toggleTts.bind(client),\n toggleStt: client.toggleStt.bind(client),\n uploadFile: client.uploadFile.bind(client),\n on: client.on.bind(client),\n off: client.off.bind(client),\n // Reactive control states\n isAudioMuted,\n isVideoEnabled,\n isScreenShareActive,\n };\n};\n"]}
|
|
1
|
+
{"version":3,"file":"useConvaiClient.js","sourceRoot":"","sources":["../../../src/react/hooks/useConvaiClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAQ9D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,MAAqB,EAWrB,EAAE;IACF,0EAA0E;IAC1E,0DAA0D;IAC1D,6DAA6D;IAC7D,MAAM,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;IAE9D,6BAA6B;IAC7B,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAS,MAAM,CAAC,CAAC;IACzD,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAC9C,MAAM,CAAC,YAAY,CACpB,CAAC;IACF,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CACxD,MAAM,CAAC,iBAAiB,CACzB,CAAC;IACF,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAC7D,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAU,MAAM,CAAC,UAAU,CAAC,CAAC;IAEzE,uCAAuC;IACvC,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAC9C,MAAM,CAAC,aAAa,CAAC,YAAY,CAClC,CAAC;IACF,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAClD,MAAM,CAAC,aAAa,CAAC,cAAc,CACpC,CAAC;IACF,MAAM,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,GAAG,QAAQ,CAC5D,MAAM,CAAC,mBAAmB,CAAC,mBAAmB,CAC/C,CAAC;IAEF,2BAA2B;IAC3B,MAAM,CAAC,YAAY,CAAC,GAAG,QAAQ,CAA2B,MAAM,CAAC,CAAC;IAElE,wBAAwB;IACxB,SAAS,CAAC,GAAG,EAAE;QACb,wBAAwB;QACxB,MAAM,gBAAgB,GAAG,MAAM,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC,QAAQ,EAAE,EAAE;YAC7D,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAEnB,yFAAyF;YACzF,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;gBAC1B,WAAW,CAAC,cAAc,CAAC,CAAC;YAC9B,CAAC;iBAAM,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;gBACjC,WAAW,CAAC,eAAe,CAAC,CAAC;YAC/B,CAAC;iBAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;gBAC/B,WAAW,CAAC,UAAU,CAAC,CAAC;YAC1B,CAAC;iBAAM,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;gBAChC,WAAW,CAAC,WAAW,CAAC,CAAC;YAC3B,CAAC;iBAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;gBAC/B,WAAW,CAAC,UAAU,CAAC,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACN,WAAW,CAAC,WAAW,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,2BAA2B;QAC3B,MAAM,mBAAmB,GAAG,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,CAAC,QAAQ,EAAE,EAAE;YACnE,eAAe,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,qCAAqC;QACrC,MAAM,sBAAsB,GAAG,MAAM,CAAC,EAAE,CACtC,yBAAyB,EACzB,CAAC,aAAa,EAAE,EAAE;YAChB,oBAAoB,CAAC,aAAa,CAAC,CAAC;QACtC,CAAC,CACF,CAAC;QAEF,2BAA2B;QAC3B,MAAM,aAAa,GAAG,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,CAAC,QAAQ,EAAE,EAAE;YAC7D,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,qBAAqB;QACrB,MAAM,aAAa,GAAG,MAAM,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE;YAC/C,aAAa,CAAC,IAAI,CAAC,CAAC;YACpB,WAAW,CAAC,WAAW,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;QAEH,mBAAmB;QACnB,MAAM,YAAY,GAAG,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;YAC7C,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;QAEH,sBAAsB;QACtB,MAAM,eAAe,GAAG,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE;YACnD,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvB,WAAW,CAAC,cAAc,CAAC,CAAC;YAC5B,eAAe,CAAC,EAAE,CAAC,CAAC;YACpB,qCAAqC;YACrC,eAAe,CAAC,IAAI,CAAC,CAAC;YACtB,iBAAiB,CAAC,KAAK,CAAC,CAAC;YACzB,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;QAEH,yEAAyE;QACzE,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAClD,SAAS,CAAC,QAAQ,GAAG,IAAI,CAAC;QAC1B,SAAS,CAAC,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC;QACpC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QAErC,MAAM,kBAAkB,GAAG,MAAM,CAAC,EAAE,CAClC,eAAe,EACf,CAAC,KAAuB,EAAE,EAAE;YAC1B,SAAS,CAAC,SAAS,GAAG,IAAI,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACjD,CAAC,CACF,CAAC;QAEF,2CAA2C;QAC3C,MAAM,sBAAsB,GAAG,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE;YAC1D,SAAS,CAAC,SAAS,GAAG,IAAI,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,uCAAuC;QACvC,MAAM,eAAe,GAAG,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,kBAAkB,EAAE,CAAC,UAAe,EAAE,EAAE;YACtF,IAAI,UAAU,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;gBAC1C,eAAe,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,uCAAuC;QACvC,MAAM,eAAe,GAAG,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,kBAAkB,EAAE,CAAC,UAAe,EAAE,EAAE;YACtF,IAAI,UAAU,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;gBAC5C,iBAAiB,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,8CAA8C;QAC9C,MAAM,qBAAqB,GAAG,MAAM,CAAC,mBAAmB,CAAC,EAAE,CAAC,wBAAwB,EAAE,CAAC,gBAAqB,EAAE,EAAE;YAC9G,IAAI,gBAAgB,CAAC,mBAAmB,KAAK,SAAS,EAAE,CAAC;gBACvD,sBAAsB,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,+BAA+B;QAC/B,OAAO,GAAG,EAAE;YACV,gBAAgB,EAAE,CAAC;YACnB,mBAAmB,EAAE,CAAC;YACtB,sBAAsB,EAAE,CAAC;YACzB,aAAa,EAAE,CAAC;YAChB,aAAa,EAAE,CAAC;YAChB,YAAY,EAAE,CAAC;YACf,eAAe,EAAE,CAAC;YAClB,kBAAkB,EAAE,CAAC;YACrB,sBAAsB,EAAE,CAAC;YACzB,eAAe,EAAE,CAAC;YAClB,eAAe,EAAE,CAAC;YAClB,qBAAqB,EAAE,CAAC;YACxB,SAAS,CAAC,SAAS,GAAG,IAAI,CAAC;YAC3B,SAAS,CAAC,MAAM,EAAE,CAAC;QACrB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,8DAA8D;IAC9D,MAAM,OAAO,GAAG,WAAW,CACzB,KAAK,EAAE,cAA6B,EAAE,EAAE;QACtC,MAAM,WAAW,GAAG,cAAc,IAAI,YAAY,CAAC;QAEnD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,6EAA6E,CAC9E,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACpC,CAAC,EACD,CAAC,MAAM,EAAE,YAAY,CAAC,CACvB,CAAC;IAEF,oCAAoC;IACpC,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACvC,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;IAC3B,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,MAAM,2BAA2B,GAAG,WAAW,CAC7C,KAAK,EACH,WAAmB,EACnB,OAAqC,EACrC,EAAE;QACF,MAAM,MAAM,CAAC,2BAA2B,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACjE,CAAC,EACD,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,wDAAwD;IACxD,OAAO;QACL,KAAK;QACL,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,sBAAsB,EAAE,MAAM,CAAC,sBAAsB;QACrD,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QAC/C,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;QACxD,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;QACzC,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;QAC7C,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,OAAO;QACP,yBAAyB,EAAE,MAAM,CAAC,yBAAyB,CAAC,IAAI,CAAC,MAAM,CAAC;QACxE,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QACtC,aAAa,EAAE,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;QAChD,kBAAkB,EAAE,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC;QAC1D,oBAAoB,EAAE,MAAM,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC;QAC9D,qBAAqB,EAAE,MAAM,CAAC,qBAAqB,CAAC,IAAI,CAAC,MAAM,CAAC;QAChE,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;QAC7C,2BAA2B;QAC3B,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;QAC1C,SAAS;QACT,YAAY,EAAE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC;QAC9C,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,mBAAmB,EAAE,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC;QAC5D,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC;QACtD,uBAAuB,EAAE,MAAM,CAAC,uBAAuB,CAAC,IAAI,CAAC,MAAM,CAAC;QACpE,kBAAkB,EAAE,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC;QAC1D,oBAAoB,EAAE,MAAM,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC;QAC9D,cAAc,EAAE,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC;QAClD,kBAAkB,EAAE,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC;QAC1D,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC;QACxD,aAAa,EAAE,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;QAChD,aAAa,EAAE,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;QAChD,YAAY,EAAE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC;QAC9C,aAAa,EAAE,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;QAChD,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC;QACxD,mBAAmB,EAAE,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC;QAC5D,QAAQ;QACR,YAAY;QACZ,iBAAiB;QACjB,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;QAC7C,UAAU;QACV,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,mBAAmB,EAAE,MAAM,CAAC,mBAAmB;QAC/C,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,qBAAqB,EAAE,MAAM,CAAC,qBAAqB;QACnD,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;QAC3C,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC;QACxC,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC;QACxC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;QAC1C,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;QAC1B,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;QAC5B,0BAA0B;QAC1B,YAAY;QACZ,cAAc;QACd,mBAAmB;KACpB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { useState, useEffect, useCallback } from \"react\";\nimport { ConvaiClient as CoreConvaiClient } from \"../../core\";\nimport type {\n ConvaiConfig,\n IConvaiClient,\n ChatMessage,\n PublishedChatConnectOptions,\n} from \"../../core/types\";\n\n/**\n * React hook wrapper for ConvaiClient\n * Main hook for managing Convai client connection and functionality.\n *\n * Provides a complete interface for connecting to Convai's AI-powered voice assistants,\n * managing real-time audio/video conversations, and handling various message types.\n *\n * @param config - Optional configuration to store for later connection\n * @returns {ConvaiClient & { activity: string; chatMessages: ChatMessage[] }} Complete client interface with connection state, methods, and message history\n *\n * @example\n * ```tsx\n * function App() {\n * const convaiClient = useConvaiClient({\n * apiKey: 'your-api-key',\n * characterId: 'your-character-id',\n * endUserId: 'user-uuid', // Optional: enables memory & analytics\n * enableVideo: true,\n * });\n *\n * return (\n * <ConvaiWidget convaiClient={convaiClient} />\n * );\n * }\n * ```\n */\nexport const useConvaiClient = (\n config?: ConvaiConfig,\n): IConvaiClient & {\n /** This hook always supplies the publication connector, unlike generic adapters. */\n connectWithPublicationGrant: NonNullable<\n IConvaiClient[\"connectWithPublicationGrant\"]\n >;\n activity: string;\n chatMessages: ChatMessage[];\n isAudioMuted: boolean;\n isVideoEnabled: boolean;\n isScreenShareActive: boolean;\n} => {\n // Create client instance once. The config is handed to the client as well\n // as kept in the hook, so config-derived surfaces such as\n // `characterVersions` are usable before the first connect().\n const [client] = useState(() => new CoreConvaiClient(config));\n\n // React state for UI updates\n const [state, setState] = useState(client.state);\n const [activity, setActivity] = useState<string>(\"Idle\");\n const [chatMessages, setChatMessages] = useState<ChatMessage[]>(\n client.chatMessages,\n );\n const [userTranscription, setUserTranscription] = useState<string>(\n client.userTranscription,\n );\n const [isSpeaking, setIsSpeaking] = useState<boolean>(false);\n const [isBotReady, setIsBotReady] = useState<boolean>(client.isBotReady);\n \n // Reactive states for control managers\n const [isAudioMuted, setIsAudioMuted] = useState<boolean>(\n client.audioControls.isAudioMuted\n );\n const [isVideoEnabled, setIsVideoEnabled] = useState<boolean>(\n client.videoControls.isVideoEnabled\n );\n const [isScreenShareActive, setIsScreenShareActive] = useState<boolean>(\n client.screenShareControls.isScreenShareActive\n );\n\n // Store config if provided\n const [storedConfig] = useState<ConvaiConfig | undefined>(config);\n\n // Setup event listeners\n useEffect(() => {\n // State change listener\n const unsubStateChange = client.on(\"stateChange\", (newState) => {\n setState(newState);\n\n // Update activity based on state (priority: speaking > listening > thinking > connected)\n if (!newState.isConnected) {\n setActivity(\"Disconnected\");\n } else if (newState.isConnecting) {\n setActivity(\"Connecting...\");\n } else if (newState.isSpeaking) {\n setActivity(\"Speaking\");\n } else if (newState.isListening) {\n setActivity(\"Listening\");\n } else if (newState.isThinking) {\n setActivity(\"Thinking\");\n } else {\n setActivity(\"Connected\");\n }\n });\n\n // Messages change listener\n const unsubMessagesChange = client.on(\"messagesChange\", (messages) => {\n setChatMessages([...messages]);\n });\n\n // User transcription change listener\n const unsubUserTranscription = client.on(\n \"userTranscriptionChange\",\n (transcription) => {\n setUserTranscription(transcription);\n },\n );\n\n // Speaking change listener\n const unsubSpeaking = client.on(\"speakingChange\", (speaking) => {\n setIsSpeaking(speaking);\n });\n\n // Bot ready listener\n const unsubBotReady = client.on(\"botReady\", () => {\n setIsBotReady(true);\n setActivity(\"Connected\");\n });\n\n // Connect listener\n const unsubConnect = client.on(\"connect\", () => {\n setState(client.state);\n });\n\n // Disconnect listener\n const unsubDisconnect = client.on(\"disconnect\", () => {\n setIsBotReady(false);\n setState(client.state);\n setActivity(\"Disconnected\");\n setChatMessages([]);\n // Reset control states on disconnect\n setIsAudioMuted(true);\n setIsVideoEnabled(false);\n setIsScreenShareActive(false);\n });\n\n // WebSocket transport: play bot audio track via a hidden <audio> element\n const wsAudioEl = document.createElement(\"audio\");\n wsAudioEl.autoplay = true;\n wsAudioEl.dataset.convaiWs = \"true\";\n document.body.appendChild(wsAudioEl);\n\n const unsubBotAudioTrack = client.on(\n \"botAudioTrack\",\n (track: MediaStreamTrack) => {\n wsAudioEl.srcObject = new MediaStream([track]);\n },\n );\n\n // Disconnect listener also clears WS audio\n const unsubDisconnectWsAudio = client.on(\"disconnect\", () => {\n wsAudioEl.srcObject = null;\n });\n\n // Audio controls state change listener\n const unsubAudioState = client.audioControls.on(\"audioStateChange\", (audioState: any) => {\n if (audioState.isAudioMuted !== undefined) {\n setIsAudioMuted(audioState.isAudioMuted);\n }\n });\n\n // Video controls state change listener\n const unsubVideoState = client.videoControls.on(\"videoStateChange\", (videoState: any) => {\n if (videoState.isVideoEnabled !== undefined) {\n setIsVideoEnabled(videoState.isVideoEnabled);\n }\n });\n\n // Screen share controls state change listener\n const unsubScreenShareState = client.screenShareControls.on(\"screenShareStateChange\", (screenShareState: any) => {\n if (screenShareState.isScreenShareActive !== undefined) {\n setIsScreenShareActive(screenShareState.isScreenShareActive);\n }\n });\n\n // Cleanup listeners on unmount\n return () => {\n unsubStateChange();\n unsubMessagesChange();\n unsubUserTranscription();\n unsubSpeaking();\n unsubBotReady();\n unsubConnect();\n unsubDisconnect();\n unsubBotAudioTrack();\n unsubDisconnectWsAudio();\n unsubAudioState();\n unsubVideoState();\n unsubScreenShareState();\n wsAudioEl.srcObject = null;\n wsAudioEl.remove();\n };\n }, [client]);\n\n // Create enhanced connect function that can use stored config\n const connect = useCallback(\n async (configOverride?: ConvaiConfig) => {\n const finalConfig = configOverride || storedConfig;\n\n if (!finalConfig) {\n throw new Error(\n \"No configuration provided. Pass config to useConvaiClient() or to connect()\",\n );\n }\n\n await client.connect(finalConfig);\n },\n [client, storedConfig],\n );\n\n // Create reconnect function wrapper\n const reconnect = useCallback(async () => {\n await client.reconnect();\n }, [client]);\n\n const connectWithPublicationGrant = useCallback(\n async (\n launchToken: string,\n options?: PublishedChatConnectOptions,\n ) => {\n await client.connectWithPublicationGrant(launchToken, options);\n },\n [client],\n );\n\n // Return client interface with React-friendly additions\n return {\n state,\n connectionType: client.connectionType,\n isPublishedChatSession: client.isPublishedChatSession,\n ...(client.apiKey && { apiKey: client.apiKey }),\n ...(client.authToken && { authToken: client.authToken }),\n characterId: client.characterId,\n characterVersion: client.characterVersion,\n characterReference: client.characterReference,\n requestTraceId: client.requestTraceId,\n connect,\n connectWithConnectionData: client.connectWithConnectionData.bind(client),\n joinRoom: client.joinRoom.bind(client),\n appendMessage: client.appendMessage.bind(client),\n toggleUsageUpdates: client.toggleUsageUpdates.bind(client),\n setInteractionTarget: client.setInteractionTarget.bind(client),\n updateCharacterRoster: client.updateCharacterRoster.bind(client),\n roomSession: client.roomSession,\n characters: client.characters,\n activeMembershipId: client.activeMembershipId,\n connectWithPublicationGrant,\n disconnect: client.disconnect.bind(client),\n reconnect,\n resetSession: client.resetSession.bind(client),\n room: client.room,\n sendUserTextMessage: client.sendUserTextMessage.bind(client),\n sendActionResult: client.sendActionResult.bind(client),\n sendActionResultAndWait: client.sendActionResultAndWait.bind(client),\n sendTriggerMessage: client.sendTriggerMessage.bind(client),\n sendInterruptMessage: client.sendInterruptMessage.bind(client),\n resetIdleTimer: client.resetIdleTimer.bind(client),\n updateTemplateKeys: client.updateTemplateKeys.bind(client),\n updateDynamicInfo: client.updateDynamicInfo.bind(client),\n updateContext: client.updateContext.bind(client),\n updateEmotion: client.updateEmotion.bind(client),\n visionStatus: client.visionStatus.bind(client),\n visionTrigger: client.visionTrigger.bind(client),\n respondModeUpdate: client.respondModeUpdate.bind(client),\n updateSceneMetadata: client.updateSceneMetadata.bind(client),\n activity,\n chatMessages,\n userTranscription,\n characterSessionId: client.characterSessionId,\n isBotReady,\n audioControls: client.audioControls,\n videoControls: client.videoControls,\n screenShareControls: client.screenShareControls,\n blendshapeQueue: client.blendshapeQueue,\n conversationSessionId: client.conversationSessionId,\n memoryManager: client.memoryManager,\n characterVersions: client.characterVersions,\n toggleTts: client.toggleTts.bind(client),\n toggleStt: client.toggleStt.bind(client),\n uploadFile: client.uploadFile.bind(client),\n on: client.on.bind(client),\n off: client.off.bind(client),\n // Reactive control states\n isAudioMuted,\n isVideoEnabled,\n isScreenShareActive,\n };\n};\n"]}
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
export { useConvaiClient } from './hooks/useConvaiClient.js';
|
|
2
2
|
export { ConvaiWidget } from './components/ConvaiWidget.js';
|
|
3
|
+
export { MarkdownRenderer } from './components/rtc-widget/components/MarkdownRenderer.js';
|
|
4
|
+
export { parseInlineMarkdown, mediaKindForUrl, isSafeHref, compactUrl } from '../utils/inlineMarkdown.js';
|
|
5
|
+
export type { InlineNode, MediaKind } from '../utils/inlineMarkdown.js';
|
|
3
6
|
export * from './hooks/index.js';
|
|
4
7
|
export * from '../core/types.js';
|
|
5
8
|
export { getDisconnectReasonMessage } from '../core/types.js';
|
|
6
|
-
export { ConvaiClient } from '../core/index.js';
|
|
9
|
+
export { ActionResultAckError, ConvaiClient } from '../core/index.js';
|
|
7
10
|
export { RoomAudioRenderer as AudioRenderer, RoomContext as AudioContext } from '@livekit/components-react';
|
|
8
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG1D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG1D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAMzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qDAAqD,CAAC;AAGvF,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACvG,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGrE,cAAc,SAAS,CAAC;AAGxB,cAAc,eAAe,CAAC;AAG9B,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAG3D,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG7D,OAAO,EAAE,iBAAiB,IAAI,aAAa,EAAE,WAAW,IAAI,YAAY,EAAE,MAAM,2BAA2B,CAAC"}
|
package/dist/react/index.js
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
export { useConvaiClient } from './hooks/useConvaiClient.js';
|
|
3
3
|
// Components
|
|
4
4
|
export { ConvaiWidget } from './components/ConvaiWidget.js';
|
|
5
|
+
// Bubble renderer, for a custom chat UI that is not ConvaiWidget. Pass
|
|
6
|
+
// `media={false}` on the user's own bubble: previews are a bot-side
|
|
7
|
+
// affordance, and rendering them on a line the user typed lets any pasted URL
|
|
8
|
+
// pull remote media into the transcript.
|
|
9
|
+
export { MarkdownRenderer } from './components/rtc-widget/components/MarkdownRenderer.js';
|
|
10
|
+
// The tokenizer behind it, for building a renderer from scratch.
|
|
11
|
+
export { parseInlineMarkdown, mediaKindForUrl, isSafeHref, compactUrl } from '../utils/inlineMarkdown.js';
|
|
5
12
|
// Additional hooks (for advanced usage)
|
|
6
13
|
export * from './hooks/index.js';
|
|
7
14
|
// Re-export core types for convenience
|
|
@@ -9,7 +16,7 @@ export * from '../core/types.js';
|
|
|
9
16
|
// Re-export helper functions explicitly
|
|
10
17
|
export { getDisconnectReasonMessage } from '../core/types.js';
|
|
11
18
|
// Re-export core client for advanced usage
|
|
12
|
-
export { ConvaiClient } from '../core/index.js';
|
|
19
|
+
export { ActionResultAckError, ConvaiClient } from '../core/index.js';
|
|
13
20
|
// Re-export LiveKit components for convenience (backward compatible)
|
|
14
21
|
export { RoomAudioRenderer as AudioRenderer, RoomContext as AudioContext } from '@livekit/components-react';
|
|
15
22
|
//# sourceMappingURL=index.js.map
|
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,aAAa;AACb,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,wCAAwC;AACxC,cAAc,SAAS,CAAC;AAExB,uCAAuC;AACvC,cAAc,eAAe,CAAC;AAE9B,wCAAwC;AACxC,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAE3D,2CAA2C;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,aAAa;AACb,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,uEAAuE;AACvE,oEAAoE;AACpE,8EAA8E;AAC9E,yCAAyC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qDAAqD,CAAC;AAEvF,iEAAiE;AACjE,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGvG,wCAAwC;AACxC,cAAc,SAAS,CAAC;AAExB,uCAAuC;AACvC,cAAc,eAAe,CAAC;AAE9B,wCAAwC;AACxC,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAE3D,2CAA2C;AAC3C,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE7D,qEAAqE;AACrE,OAAO,EAAE,iBAAiB,IAAI,aAAa,EAAE,WAAW,IAAI,YAAY,EAAE,MAAM,2BAA2B,CAAC","sourcesContent":["// Main hook (backward compatible)\nexport { useConvaiClient } from './hooks/useConvaiClient';\n\n// Components\nexport { ConvaiWidget } from './components/ConvaiWidget';\n\n// Bubble renderer, for a custom chat UI that is not ConvaiWidget. Pass\n// `media={false}` on the user's own bubble: previews are a bot-side\n// affordance, and rendering them on a line the user typed lets any pasted URL\n// pull remote media into the transcript.\nexport { MarkdownRenderer } from './components/rtc-widget/components/MarkdownRenderer';\n\n// The tokenizer behind it, for building a renderer from scratch.\nexport { parseInlineMarkdown, mediaKindForUrl, isSafeHref, compactUrl } from '../utils/inlineMarkdown';\nexport type { InlineNode, MediaKind } from '../utils/inlineMarkdown';\n\n// Additional hooks (for advanced usage)\nexport * from './hooks';\n\n// Re-export core types for convenience\nexport * from '../core/types';\n\n// Re-export helper functions explicitly\nexport { getDisconnectReasonMessage } from '../core/types';\n\n// Re-export core client for advanced usage\nexport { ActionResultAckError, ConvaiClient } from '../core';\n\n// Re-export LiveKit components for convenience (backward compatible)\nexport { RoomAudioRenderer as AudioRenderer, RoomContext as AudioContext } from '@livekit/components-react';\n"]}
|
|
@@ -31,8 +31,30 @@ export type InlineNode = {
|
|
|
31
31
|
kind: "image";
|
|
32
32
|
src: string;
|
|
33
33
|
alt: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A `[label](target)` whose scheme is not on the allowlist. It carries the
|
|
37
|
+
* label so a renderer can show the words the character wrote instead of raw
|
|
38
|
+
* markdown, and the target so it can be surfaced on hover — but a renderer
|
|
39
|
+
* must never put `href` on an anchor. That is the whole point of the node.
|
|
40
|
+
*/
|
|
41
|
+
| {
|
|
42
|
+
kind: "blocked";
|
|
43
|
+
href: string;
|
|
44
|
+
label: string;
|
|
34
45
|
};
|
|
35
46
|
/** Classify a URL by its path extension; null for anything not previewable. */
|
|
36
47
|
export declare function mediaKindForUrl(url: string): MediaKind | null;
|
|
48
|
+
/**
|
|
49
|
+
* A bare URL is its own label, and a long one wraps over several lines before
|
|
50
|
+
* the message even starts — in a 400px panel that swamps the bubble. Compact it
|
|
51
|
+
* the way a browser address bar does: keep what identifies the target, elide
|
|
52
|
+
* the middle. `https://a.example.com/x/y/z/file.mp4` → `a.example.com/…/file.mp4`
|
|
53
|
+
*
|
|
54
|
+
* Presentation only: the href is always the full URL.
|
|
55
|
+
*/
|
|
56
|
+
export declare function compactUrl(url: string, max?: number): string;
|
|
57
|
+
/** True when `url` uses a scheme safe to expose as an anchor href. */
|
|
58
|
+
export declare function isSafeHref(url: string): boolean;
|
|
37
59
|
export declare function parseInlineMarkdown(line: string): InlineNode[];
|
|
38
60
|
//# sourceMappingURL=inlineMarkdown.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inlineMarkdown.d.ts","sourceRoot":"","sources":["../../src/utils/inlineMarkdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1C,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAA;CAAE,GACtE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"inlineMarkdown.d.ts","sourceRoot":"","sources":["../../src/utils/inlineMarkdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1C,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAA;CAAE,GACtE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE;AAC7C;;;;;GAKG;GACD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAKrD,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAU7D;AAoBD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,SAAK,GAAG,MAAM,CAkBxD;AAED,sEAAsE;AACtE,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAG/C;AAqDD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,EAAE,CA4C9D"}
|
|
@@ -29,12 +29,78 @@ export function mediaKindForUrl(url) {
|
|
|
29
29
|
return "video";
|
|
30
30
|
return null;
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Schemes a renderer may turn into an anchor.
|
|
34
|
+
*
|
|
35
|
+
* The list is an allowlist, never a denylist, because the server does NOT
|
|
36
|
+
* sanitise schemes — core-service echoes `[x](javascript:alert(1))` back
|
|
37
|
+
* verbatim (verified against dev4, 2026-09-10). The character's output is
|
|
38
|
+
* attacker-influenced text, so this is the only thing standing between a
|
|
39
|
+
* prompt-injected `javascript:` href and script execution in the host page.
|
|
40
|
+
* Anything not listed here stays literal text.
|
|
41
|
+
*/
|
|
42
|
+
const SAFE_SCHEMES = ["http", "https", "ftp", "ftps", "mailto", "tel", "sms"];
|
|
43
|
+
/** Schemes with an authority; the rest (mailto/tel/sms) are opaque. */
|
|
44
|
+
const NETWORK_SCHEMES = ["http", "https", "ftp", "ftps"];
|
|
45
|
+
const schemeAlt = SAFE_SCHEMES.join("|");
|
|
46
|
+
const networkAlt = NETWORK_SCHEMES.join("|");
|
|
47
|
+
/**
|
|
48
|
+
* A bare URL is its own label, and a long one wraps over several lines before
|
|
49
|
+
* the message even starts — in a 400px panel that swamps the bubble. Compact it
|
|
50
|
+
* the way a browser address bar does: keep what identifies the target, elide
|
|
51
|
+
* the middle. `https://a.example.com/x/y/z/file.mp4` → `a.example.com/…/file.mp4`
|
|
52
|
+
*
|
|
53
|
+
* Presentation only: the href is always the full URL.
|
|
54
|
+
*/
|
|
55
|
+
export function compactUrl(url, max = 44) {
|
|
56
|
+
if (url.length <= max)
|
|
57
|
+
return url;
|
|
58
|
+
let host;
|
|
59
|
+
let pathname;
|
|
60
|
+
try {
|
|
61
|
+
({ host, pathname } = new URL(url));
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return `${url.slice(0, max - 1)}…`;
|
|
65
|
+
}
|
|
66
|
+
const file = pathname.split("/").filter(Boolean).pop();
|
|
67
|
+
if (!file)
|
|
68
|
+
return host.length <= max ? host : `${host.slice(0, max - 1)}…`;
|
|
69
|
+
const compact = `${host}/…/${file}`;
|
|
70
|
+
if (compact.length <= max)
|
|
71
|
+
return compact;
|
|
72
|
+
// A long host would otherwise eat the budget and clip the filename down to
|
|
73
|
+
// its extension. The filename identifies what the link actually is, so drop
|
|
74
|
+
// the host instead of shortening it.
|
|
75
|
+
if (file.length <= max)
|
|
76
|
+
return file;
|
|
77
|
+
return `…${file.slice(-(max - 1))}`;
|
|
78
|
+
}
|
|
79
|
+
/** True when `url` uses a scheme safe to expose as an anchor href. */
|
|
80
|
+
export function isSafeHref(url) {
|
|
81
|
+
const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(url)?.[1];
|
|
82
|
+
return scheme !== undefined && SAFE_SCHEMES.includes(scheme.toLowerCase());
|
|
83
|
+
}
|
|
32
84
|
// Alternatives are tried in this order at every position:
|
|
33
|
-
// 1.  / [text](url) with an
|
|
34
|
-
// 2.
|
|
35
|
-
// 3.
|
|
85
|
+
// 1.  / [text](url), with an optional CommonMark "title"
|
|
86
|
+
// 2. <url> autolink, angle brackets consumed
|
|
87
|
+
// 3. bare URL, unless it is the target of a link still streaming in
|
|
88
|
+
// 4. **bold** / __bold__ / *em* / _em_
|
|
36
89
|
// Matching URLs before emphasis is what keeps `_` inside a URL literal.
|
|
37
|
-
|
|
90
|
+
// Alternative 1 accepts ANY scheme so an unsafe one can be recognised and
|
|
91
|
+
// re-emitted as literal text; without that, `[x](javascript:…)` would fall
|
|
92
|
+
// through to the emphasis rules and get partially mangled.
|
|
93
|
+
const TOKEN = new RegExp([
|
|
94
|
+
// The target allows one level of balanced parens, so `javascript:alert(1)`
|
|
95
|
+
// and `…/a_(b).pdf` are consumed whole. Without it the inner `)` ended the
|
|
96
|
+
// match and the outer one was left stranded in the text.
|
|
97
|
+
`(!?)\\[([^\\]]*)\\]\\(\\s*((?:[^\\s()]|\\([^()]*\\))+)(?:\\s+"[^"]*")?\\s*\\)`,
|
|
98
|
+
`<((?:${schemeAlt}):[^\\s<>]+)>`,
|
|
99
|
+
`(?<!\\]\\()((?:${networkAlt}):\\/\\/[^\\s<>"'\`]+|(?:mailto|tel|sms):[^\\s<>"'\`]+)`,
|
|
100
|
+
`(\\*\\*|__)(.*?)\\6`,
|
|
101
|
+
`\\*([^*]+)\\*`,
|
|
102
|
+
`_([^_]+)_`,
|
|
103
|
+
].join("|"), "gi");
|
|
38
104
|
const TRAILING_PUNCTUATION = ".,;:!?'\"";
|
|
39
105
|
/**
|
|
40
106
|
* Sentence punctuation after a bare URL belongs to the sentence, and an
|
|
@@ -76,12 +142,23 @@ export function parseInlineMarkdown(line) {
|
|
|
76
142
|
let match;
|
|
77
143
|
while ((match = TOKEN.exec(line)) !== null) {
|
|
78
144
|
pushText(line.slice(lastIndex, match.index));
|
|
79
|
-
const [, bang, label, linkUrl, bareUrl, , boldText, starEm, underscoreEm] = match;
|
|
145
|
+
const [, bang, label, linkUrl, autoUrl, bareUrl, , boldText, starEm, underscoreEm] = match;
|
|
80
146
|
if (linkUrl !== undefined) {
|
|
81
|
-
if (
|
|
147
|
+
if (!isSafeHref(linkUrl)) {
|
|
148
|
+
// Not an anchor, ever. It keeps the label so the bubble reads as the
|
|
149
|
+
// character wrote it rather than showing raw markdown, and the target
|
|
150
|
+
// so a renderer can reveal it on hover.
|
|
151
|
+
nodes.push({ kind: "blocked", href: linkUrl, label: bang ? label || linkUrl : label });
|
|
152
|
+
}
|
|
153
|
+
else if (bang) {
|
|
82
154
|
nodes.push({ kind: "image", src: linkUrl, alt: label });
|
|
83
|
-
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
84
157
|
nodes.push({ kind: "link", href: linkUrl, label, media: mediaKindForUrl(linkUrl) });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
else if (autoUrl !== undefined) {
|
|
161
|
+
nodes.push({ kind: "link", href: autoUrl, label: autoUrl, media: mediaKindForUrl(autoUrl) });
|
|
85
162
|
}
|
|
86
163
|
else if (bareUrl !== undefined) {
|
|
87
164
|
const [href, rest] = splitTrailingPunctuation(bareUrl);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inlineMarkdown.js","sourceRoot":"","sources":["../../src/utils/inlineMarkdown.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Inline markdown tokenizer shared by the React and vanilla chat bubbles.\n *\n * Core-service can hand the client bot text with links preserved\n * (`preserve_links_in_output` on /connect): `[text](url)`, `` and\n * bare `http(s)://` URLs arrive verbatim, everything else is still flattened\n * server-side. This turns one line of that text into nodes a renderer can\n * map onto DOM or JSX.\n *\n * Only `http:` and `https:` become links or images. Anything else — including\n * `javascript:` — stays literal text, regardless of what the server sent.\n * A link whose closing paren has not streamed in yet is left as text too, so\n * a bubble does not flicker between shapes mid-response.\n */\n\nexport type MediaKind = \"image\" | \"video\";\n\nexport type InlineNode =\n | { kind: \"text\"; text: string }\n | { kind: \"strong\"; text: string }\n | { kind: \"em\"; text: string }\n | { kind: \"link\"; href: string; label: string; media: MediaKind | null }\n | { kind: \"image\"; src: string; alt: string };\n\nconst IMAGE_EXT = /\\.(png|jpe?g|gif|webp|avif)$/i;\nconst VIDEO_EXT = /\\.(mp4|webm|mov|ogg)$/i;\n\n/** Classify a URL by its path extension; null for anything not previewable. */\nexport function mediaKindForUrl(url: string): MediaKind | null {\n let pathname: string;\n try {\n pathname = new URL(url).pathname;\n } catch {\n return null;\n }\n if (IMAGE_EXT.test(pathname)) return \"image\";\n if (VIDEO_EXT.test(pathname)) return \"video\";\n return null;\n}\n\n// Alternatives are tried in this order at every position:\n// 1.  / [text](url) with an http(s) URL\n// 2. bare http(s) URL, unless it is the target of a link still streaming in\n// 3. **bold** / __bold__ / *em* / _em_\n// Matching URLs before emphasis is what keeps `_` inside a URL literal.\nconst TOKEN =\n /(!?)\\[([^\\]]*)\\]\\((https?:\\/\\/[^\\s)]+)\\)|(?<!\\]\\()(https?:\\/\\/[^\\s<>\"'`]+)|(\\*\\*|__)(.*?)\\5|\\*([^*]+)\\*|_([^_]+)_/g;\n\nconst TRAILING_PUNCTUATION = \".,;:!?'\\\"\";\n\n/**\n * Sentence punctuation after a bare URL belongs to the sentence, and an\n * unbalanced `)` belongs to the surrounding parenthetical.\n */\nfunction splitTrailingPunctuation(raw: string): [string, string] {\n let url = raw;\n while (url.length > 0) {\n const last = url[url.length - 1];\n if (TRAILING_PUNCTUATION.includes(last)) {\n url = url.slice(0, -1);\n continue;\n }\n if (last === \")\") {\n const opens = (url.match(/\\(/g) ?? []).length;\n const closes = (url.match(/\\)/g) ?? []).length;\n if (closes > opens) {\n url = url.slice(0, -1);\n continue;\n }\n }\n break;\n }\n return [url, raw.slice(url.length)];\n}\n\nexport function parseInlineMarkdown(line: string): InlineNode[] {\n const nodes: InlineNode[] = [];\n const pushText = (text: string) => {\n if (!text) return;\n const last = nodes[nodes.length - 1];\n if (last?.kind === \"text\") last.text += text;\n else nodes.push({ kind: \"text\", text });\n };\n\n let lastIndex = 0;\n TOKEN.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = TOKEN.exec(line)) !== null) {\n pushText(line.slice(lastIndex, match.index));\n const [, bang, label, linkUrl, bareUrl, , boldText, starEm, underscoreEm] = match;\n\n if (linkUrl !== undefined) {\n if (bang) nodes.push({ kind: \"image\", src: linkUrl, alt: label });\n else nodes.push({ kind: \"link\", href: linkUrl, label, media: mediaKindForUrl(linkUrl) });\n } else if (bareUrl !== undefined) {\n const [href, rest] = splitTrailingPunctuation(bareUrl);\n if (href) nodes.push({ kind: \"link\", href, label: href, media: mediaKindForUrl(href) });\n pushText(rest);\n } else if (boldText !== undefined) {\n nodes.push({ kind: \"strong\", text: boldText });\n } else if (starEm !== undefined) {\n nodes.push({ kind: \"em\", text: starEm });\n } else if (underscoreEm !== undefined) {\n nodes.push({ kind: \"em\", text: underscoreEm });\n }\n lastIndex = match.index + match[0].length;\n }\n pushText(line.slice(lastIndex));\n return nodes;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"inlineMarkdown.js","sourceRoot":"","sources":["../../src/utils/inlineMarkdown.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Inline markdown tokenizer shared by the React and vanilla chat bubbles.\n *\n * Core-service can hand the client bot text with links preserved\n * (`preserve_links_in_output` on /connect): `[text](url)`, `` and\n * bare `http(s)://` URLs arrive verbatim, everything else is still flattened\n * server-side. This turns one line of that text into nodes a renderer can\n * map onto DOM or JSX.\n *\n * Only `http:` and `https:` become links or images. Anything else — including\n * `javascript:` — stays literal text, regardless of what the server sent.\n * A link whose closing paren has not streamed in yet is left as text too, so\n * a bubble does not flicker between shapes mid-response.\n */\n\nexport type MediaKind = \"image\" | \"video\";\n\nexport type InlineNode =\n | { kind: \"text\"; text: string }\n | { kind: \"strong\"; text: string }\n | { kind: \"em\"; text: string }\n | { kind: \"link\"; href: string; label: string; media: MediaKind | null }\n | { kind: \"image\"; src: string; alt: string }\n /**\n * A `[label](target)` whose scheme is not on the allowlist. It carries the\n * label so a renderer can show the words the character wrote instead of raw\n * markdown, and the target so it can be surfaced on hover — but a renderer\n * must never put `href` on an anchor. That is the whole point of the node.\n */\n | { kind: \"blocked\"; href: string; label: string };\n\nconst IMAGE_EXT = /\\.(png|jpe?g|gif|webp|avif)$/i;\nconst VIDEO_EXT = /\\.(mp4|webm|mov|ogg)$/i;\n\n/** Classify a URL by its path extension; null for anything not previewable. */\nexport function mediaKindForUrl(url: string): MediaKind | null {\n let pathname: string;\n try {\n pathname = new URL(url).pathname;\n } catch {\n return null;\n }\n if (IMAGE_EXT.test(pathname)) return \"image\";\n if (VIDEO_EXT.test(pathname)) return \"video\";\n return null;\n}\n\n/**\n * Schemes a renderer may turn into an anchor.\n *\n * The list is an allowlist, never a denylist, because the server does NOT\n * sanitise schemes — core-service echoes `[x](javascript:alert(1))` back\n * verbatim (verified against dev4, 2026-09-10). The character's output is\n * attacker-influenced text, so this is the only thing standing between a\n * prompt-injected `javascript:` href and script execution in the host page.\n * Anything not listed here stays literal text.\n */\nconst SAFE_SCHEMES = [\"http\", \"https\", \"ftp\", \"ftps\", \"mailto\", \"tel\", \"sms\"];\n\n/** Schemes with an authority; the rest (mailto/tel/sms) are opaque. */\nconst NETWORK_SCHEMES = [\"http\", \"https\", \"ftp\", \"ftps\"];\n\nconst schemeAlt = SAFE_SCHEMES.join(\"|\");\nconst networkAlt = NETWORK_SCHEMES.join(\"|\");\n\n/**\n * A bare URL is its own label, and a long one wraps over several lines before\n * the message even starts — in a 400px panel that swamps the bubble. Compact it\n * the way a browser address bar does: keep what identifies the target, elide\n * the middle. `https://a.example.com/x/y/z/file.mp4` → `a.example.com/…/file.mp4`\n *\n * Presentation only: the href is always the full URL.\n */\nexport function compactUrl(url: string, max = 44): string {\n if (url.length <= max) return url;\n let host: string;\n let pathname: string;\n try {\n ({ host, pathname } = new URL(url));\n } catch {\n return `${url.slice(0, max - 1)}…`;\n }\n const file = pathname.split(\"/\").filter(Boolean).pop();\n if (!file) return host.length <= max ? host : `${host.slice(0, max - 1)}…`;\n const compact = `${host}/…/${file}`;\n if (compact.length <= max) return compact;\n // A long host would otherwise eat the budget and clip the filename down to\n // its extension. The filename identifies what the link actually is, so drop\n // the host instead of shortening it.\n if (file.length <= max) return file;\n return `…${file.slice(-(max - 1))}`;\n}\n\n/** True when `url` uses a scheme safe to expose as an anchor href. */\nexport function isSafeHref(url: string): boolean {\n const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(url)?.[1];\n return scheme !== undefined && SAFE_SCHEMES.includes(scheme.toLowerCase());\n}\n\n// Alternatives are tried in this order at every position:\n// 1.  / [text](url), with an optional CommonMark \"title\"\n// 2. <url> autolink, angle brackets consumed\n// 3. bare URL, unless it is the target of a link still streaming in\n// 4. **bold** / __bold__ / *em* / _em_\n// Matching URLs before emphasis is what keeps `_` inside a URL literal.\n// Alternative 1 accepts ANY scheme so an unsafe one can be recognised and\n// re-emitted as literal text; without that, `[x](javascript:…)` would fall\n// through to the emphasis rules and get partially mangled.\nconst TOKEN = new RegExp(\n [\n // The target allows one level of balanced parens, so `javascript:alert(1)`\n // and `…/a_(b).pdf` are consumed whole. Without it the inner `)` ended the\n // match and the outer one was left stranded in the text.\n `(!?)\\\\[([^\\\\]]*)\\\\]\\\\(\\\\s*((?:[^\\\\s()]|\\\\([^()]*\\\\))+)(?:\\\\s+\"[^\"]*\")?\\\\s*\\\\)`,\n `<((?:${schemeAlt}):[^\\\\s<>]+)>`,\n `(?<!\\\\]\\\\()((?:${networkAlt}):\\\\/\\\\/[^\\\\s<>\"'\\`]+|(?:mailto|tel|sms):[^\\\\s<>\"'\\`]+)`,\n `(\\\\*\\\\*|__)(.*?)\\\\6`,\n `\\\\*([^*]+)\\\\*`,\n `_([^_]+)_`,\n ].join(\"|\"),\n \"gi\",\n);\n\nconst TRAILING_PUNCTUATION = \".,;:!?'\\\"\";\n\n/**\n * Sentence punctuation after a bare URL belongs to the sentence, and an\n * unbalanced `)` belongs to the surrounding parenthetical.\n */\nfunction splitTrailingPunctuation(raw: string): [string, string] {\n let url = raw;\n while (url.length > 0) {\n const last = url[url.length - 1];\n if (TRAILING_PUNCTUATION.includes(last)) {\n url = url.slice(0, -1);\n continue;\n }\n if (last === \")\") {\n const opens = (url.match(/\\(/g) ?? []).length;\n const closes = (url.match(/\\)/g) ?? []).length;\n if (closes > opens) {\n url = url.slice(0, -1);\n continue;\n }\n }\n break;\n }\n return [url, raw.slice(url.length)];\n}\n\nexport function parseInlineMarkdown(line: string): InlineNode[] {\n const nodes: InlineNode[] = [];\n const pushText = (text: string) => {\n if (!text) return;\n const last = nodes[nodes.length - 1];\n if (last?.kind === \"text\") last.text += text;\n else nodes.push({ kind: \"text\", text });\n };\n\n let lastIndex = 0;\n TOKEN.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = TOKEN.exec(line)) !== null) {\n pushText(line.slice(lastIndex, match.index));\n const [, bang, label, linkUrl, autoUrl, bareUrl, , boldText, starEm, underscoreEm] = match;\n\n if (linkUrl !== undefined) {\n if (!isSafeHref(linkUrl)) {\n // Not an anchor, ever. It keeps the label so the bubble reads as the\n // character wrote it rather than showing raw markdown, and the target\n // so a renderer can reveal it on hover.\n nodes.push({ kind: \"blocked\", href: linkUrl, label: bang ? label || linkUrl : label });\n } else if (bang) {\n nodes.push({ kind: \"image\", src: linkUrl, alt: label });\n } else {\n nodes.push({ kind: \"link\", href: linkUrl, label, media: mediaKindForUrl(linkUrl) });\n }\n } else if (autoUrl !== undefined) {\n nodes.push({ kind: \"link\", href: autoUrl, label: autoUrl, media: mediaKindForUrl(autoUrl) });\n } else if (bareUrl !== undefined) {\n const [href, rest] = splitTrailingPunctuation(bareUrl);\n if (href) nodes.push({ kind: \"link\", href, label: href, media: mediaKindForUrl(href) });\n pushText(rest);\n } else if (boldText !== undefined) {\n nodes.push({ kind: \"strong\", text: boldText });\n } else if (starEm !== undefined) {\n nodes.push({ kind: \"em\", text: starEm });\n } else if (underscoreEm !== undefined) {\n nodes.push({ kind: \"em\", text: underscoreEm });\n }\n lastIndex = match.index + match[0].length;\n }\n pushText(line.slice(lastIndex));\n return nodes;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConvaiWidget.d.ts","sourceRoot":"","sources":["../../src/vanilla/ConvaiWidget.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"ConvaiWidget.d.ts","sourceRoot":"","sources":["../../src/vanilla/ConvaiWidget.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH,OAAO,KAAK,EACV,oBAAoB,EACpB,aAAa,EAEd,MAAM,SAAS,CAAC;AA4HjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,WAAW,EACtB,OAAO,EAAE,oBAAoB,GAC5B,aAAa,CAk5Ff;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAE/D"}
|