@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.
Files changed (99) hide show
  1. package/README.md +303 -1
  2. package/dist/core/ConvaiClient.d.ts +59 -2
  3. package/dist/core/ConvaiClient.d.ts.map +1 -1
  4. package/dist/core/ConvaiClient.js +457 -6
  5. package/dist/core/ConvaiClient.js.map +1 -1
  6. package/dist/core/MessageHandler.d.ts +11 -0
  7. package/dist/core/MessageHandler.d.ts.map +1 -1
  8. package/dist/core/MessageHandler.js +325 -30
  9. package/dist/core/MessageHandler.js.map +1 -1
  10. package/dist/core/SSESession.js +2 -2
  11. package/dist/core/SSESession.js.map +1 -1
  12. package/dist/core/connectRequest.d.ts +38 -3
  13. package/dist/core/connectRequest.d.ts.map +1 -1
  14. package/dist/core/connectRequest.js +57 -11
  15. package/dist/core/connectRequest.js.map +1 -1
  16. package/dist/core/index.d.ts +5 -1
  17. package/dist/core/index.d.ts.map +1 -1
  18. package/dist/core/index.js +8 -1
  19. package/dist/core/index.js.map +1 -1
  20. package/dist/core/logicalTurn.d.ts +4 -1
  21. package/dist/core/logicalTurn.d.ts.map +1 -1
  22. package/dist/core/logicalTurn.js +35 -4
  23. package/dist/core/logicalTurn.js.map +1 -1
  24. package/dist/core/modelOutput.d.ts +40 -0
  25. package/dist/core/modelOutput.d.ts.map +1 -0
  26. package/dist/core/modelOutput.js +187 -0
  27. package/dist/core/modelOutput.js.map +1 -0
  28. package/dist/core/publishedChat.d.ts +9 -0
  29. package/dist/core/publishedChat.d.ts.map +1 -0
  30. package/dist/core/publishedChat.js +13 -0
  31. package/dist/core/publishedChat.js.map +1 -0
  32. package/dist/core/types.d.ts +225 -25
  33. package/dist/core/types.d.ts.map +1 -1
  34. package/dist/core/types.js.map +1 -1
  35. package/dist/embed/ConvaiChatElement.d.ts +103 -0
  36. package/dist/embed/ConvaiChatElement.d.ts.map +1 -0
  37. package/dist/embed/ConvaiChatElement.js +679 -0
  38. package/dist/embed/ConvaiChatElement.js.map +1 -0
  39. package/dist/embed/browser.d.ts +3 -0
  40. package/dist/embed/browser.d.ts.map +1 -0
  41. package/dist/embed/browser.js +5 -0
  42. package/dist/embed/browser.js.map +1 -0
  43. package/dist/embed/chat-embed-v1.js +200 -0
  44. package/dist/embed/chat-embed-v1.js.map +7 -0
  45. package/dist/embed/index.d.ts +9 -0
  46. package/dist/embed/index.d.ts.map +1 -0
  47. package/dist/embed/index.js +9 -0
  48. package/dist/embed/index.js.map +1 -0
  49. package/dist/embed/publicationApi.d.ts +23 -0
  50. package/dist/embed/publicationApi.d.ts.map +1 -0
  51. package/dist/embed/publicationApi.js +141 -0
  52. package/dist/embed/publicationApi.js.map +1 -0
  53. package/dist/react/components/ConvaiWidget.d.ts +11 -1
  54. package/dist/react/components/ConvaiWidget.d.ts.map +1 -1
  55. package/dist/react/components/ConvaiWidget.js +67 -11
  56. package/dist/react/components/ConvaiWidget.js.map +1 -1
  57. package/dist/react/components/rtc-widget/components/MarkdownRenderer.d.ts +7 -0
  58. package/dist/react/components/rtc-widget/components/MarkdownRenderer.d.ts.map +1 -1
  59. package/dist/react/components/rtc-widget/components/MarkdownRenderer.js +111 -17
  60. package/dist/react/components/rtc-widget/components/MarkdownRenderer.js.map +1 -1
  61. package/dist/react/components/rtc-widget/components/UserMessage.js +1 -1
  62. package/dist/react/components/rtc-widget/components/UserMessage.js.map +1 -1
  63. package/dist/react/components/rtc-widget/components/conviComponents/SettingsTray.d.ts +1 -1
  64. package/dist/react/components/rtc-widget/components/conviComponents/SettingsTray.d.ts.map +1 -1
  65. package/dist/react/components/rtc-widget/components/conviComponents/SettingsTray.js +2 -2
  66. package/dist/react/components/rtc-widget/components/conviComponents/SettingsTray.js.map +1 -1
  67. package/dist/react/hooks/useConvaiClient.d.ts +2 -0
  68. package/dist/react/hooks/useConvaiClient.d.ts.map +1 -1
  69. package/dist/react/hooks/useConvaiClient.js +8 -0
  70. package/dist/react/hooks/useConvaiClient.js.map +1 -1
  71. package/dist/react/index.d.ts +4 -1
  72. package/dist/react/index.d.ts.map +1 -1
  73. package/dist/react/index.js +8 -1
  74. package/dist/react/index.js.map +1 -1
  75. package/dist/utils/inlineMarkdown.d.ts +22 -0
  76. package/dist/utils/inlineMarkdown.d.ts.map +1 -1
  77. package/dist/utils/inlineMarkdown.js +84 -7
  78. package/dist/utils/inlineMarkdown.js.map +1 -1
  79. package/dist/vanilla/ConvaiWidget.d.ts.map +1 -1
  80. package/dist/vanilla/ConvaiWidget.js +290 -43
  81. package/dist/vanilla/ConvaiWidget.js.map +1 -1
  82. package/dist/vanilla/WidgetEventSubscriptions.d.ts +15 -0
  83. package/dist/vanilla/WidgetEventSubscriptions.d.ts.map +1 -0
  84. package/dist/vanilla/WidgetEventSubscriptions.js +37 -0
  85. package/dist/vanilla/WidgetEventSubscriptions.js.map +1 -0
  86. package/dist/vanilla/index.d.ts +3 -1
  87. package/dist/vanilla/index.d.ts.map +1 -1
  88. package/dist/vanilla/index.js +3 -1
  89. package/dist/vanilla/index.js.map +1 -1
  90. package/dist/vanilla/styles.d.ts.map +1 -1
  91. package/dist/vanilla/styles.js +12 -0
  92. package/dist/vanilla/styles.js.map +1 -1
  93. package/dist/vanilla/types.d.ts +8 -1
  94. package/dist/vanilla/types.d.ts.map +1 -1
  95. package/dist/vanilla/types.js.map +1 -1
  96. package/dist/version.d.ts +1 -1
  97. package/dist/version.js +1 -1
  98. package/dist/version.js.map +1 -1
  99. 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,EACZ,MAAM,kBAAkB,CAAC;AAE1B;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,eAAe,GAC1B,SAAS,YAAY,KACpB,aAAa,GAAG;IACjB,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;CAwO9B,CAAC"}
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":"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","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":"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","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"]}
@@ -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;AAGzD,cAAc,SAAS,CAAC;AAGxB,cAAc,eAAe,CAAC;AAG9B,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAG3D,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGvC,OAAO,EAAE,iBAAiB,IAAI,aAAa,EAAE,WAAW,IAAI,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"}
@@ -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
@@ -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;AAEvC,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// 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 { 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\n"]}
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;AAKhD,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAU7D;AAqCD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,EAAE,CAkC9D"}
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. ![alt](url) / [text](url) with an http(s) URL
34
- // 2. bare http(s) URL, unless it is the target of a link still streaming in
35
- // 3. **bold** / __bold__ / *em* / _em_
85
+ // 1. ![alt](url) / [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
- const TOKEN = /(!?)\[([^\]]*)\]\((https?:\/\/[^\s)]+)\)|(?<!\]\()(https?:\/\/[^\s<>"'`]+)|(\*\*|__)(.*?)\5|\*([^*]+)\*|_([^_]+)_/g;
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 (bang)
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
- else
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)`, `![alt](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. ![alt](url) / [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)`, `![alt](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. ![alt](url) / [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;AAWH,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,CAymFf;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAE/D"}
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"}