@memori.ai/memori-react 9.0.0-alpha.1 → 9.0.0-alpha.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (956) hide show
  1. package/CHANGELOG.md +642 -0
  2. package/dist/components/AgeVerificationModal/AgeVerificationModal.js +8 -3
  3. package/dist/components/AgeVerificationModal/AgeVerificationModal.js.map +1 -1
  4. package/dist/components/Auth/Auth.js +3 -1
  5. package/dist/components/Auth/Auth.js.map +1 -1
  6. package/dist/components/Avatar/Avatar.js +5 -10
  7. package/dist/components/Avatar/Avatar.js.map +1 -1
  8. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +8 -1
  9. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
  10. package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js +1 -1
  11. package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js.map +1 -1
  12. package/dist/components/Avatar/AvatarView/AvatarComponent/constants.d.ts +2 -0
  13. package/dist/components/Avatar/AvatarView/AvatarComponent/constants.js +14 -5
  14. package/dist/components/Avatar/AvatarView/AvatarComponent/constants.js.map +1 -1
  15. package/dist/components/Chat/Chat.css +108 -20
  16. package/dist/components/Chat/Chat.d.ts +3 -0
  17. package/dist/components/Chat/Chat.js +63 -55
  18. package/dist/components/Chat/Chat.js.map +1 -1
  19. package/dist/components/ChatBubble/ChatBubble.css +42 -14
  20. package/dist/components/ChatBubble/ChatBubble.js +35 -39
  21. package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
  22. package/dist/components/ChatHistoryDrawer/ChatHistory.css +4 -0
  23. package/dist/components/ChatHistoryDrawer/ChatHistory.js +27 -10
  24. package/dist/components/ChatHistoryDrawer/ChatHistory.js.map +1 -1
  25. package/dist/components/ChatInputs/ChatInputs.css +292 -108
  26. package/dist/components/ChatInputs/ChatInputs.d.ts +1 -0
  27. package/dist/components/ChatInputs/ChatInputs.js +2 -2
  28. package/dist/components/ChatInputs/ChatInputs.js.map +1 -1
  29. package/dist/components/ChatTextArea/ChatTextArea.css +30 -6
  30. package/dist/components/CompletionProviderStatus/CompletionProviderStatus.js +6 -3
  31. package/dist/components/CompletionProviderStatus/CompletionProviderStatus.js.map +1 -1
  32. package/dist/components/ContentPreviewModal/ContentPreviewModal.js +3 -1
  33. package/dist/components/ContentPreviewModal/ContentPreviewModal.js.map +1 -1
  34. package/dist/components/DateSelector/DateSelector.d.ts +2 -1
  35. package/dist/components/DateSelector/DateSelector.js +17 -7
  36. package/dist/components/DateSelector/DateSelector.js.map +1 -1
  37. package/dist/components/ExpertsDrawer/ExpertsDrawer.js +3 -1
  38. package/dist/components/ExpertsDrawer/ExpertsDrawer.js.map +1 -1
  39. package/dist/components/FilePreview/FilePreview.js +22 -5
  40. package/dist/components/FilePreview/FilePreview.js.map +1 -1
  41. package/dist/components/Header/ChatConsumptionDropdown.d.ts +3 -1
  42. package/dist/components/Header/ChatConsumptionDropdown.js +4 -3
  43. package/dist/components/Header/ChatConsumptionDropdown.js.map +1 -1
  44. package/dist/components/Header/Header.css +16 -10
  45. package/dist/components/Header/Header.js +103 -22
  46. package/dist/components/Header/Header.js.map +1 -1
  47. package/dist/components/KnownFacts/KnownFacts.js +7 -5
  48. package/dist/components/KnownFacts/KnownFacts.js.map +1 -1
  49. package/dist/components/LoginDrawer/LoginDrawer.css +1 -0
  50. package/dist/components/LoginDrawer/LoginDrawer.js +3 -1
  51. package/dist/components/LoginDrawer/LoginDrawer.js.map +1 -1
  52. package/dist/components/MediaWidget/MediaItemWidget.js +14 -12
  53. package/dist/components/MediaWidget/MediaItemWidget.js.map +1 -1
  54. package/dist/components/MediaWidget/MediaItemWidget.utils.d.ts +3 -2
  55. package/dist/components/MediaWidget/MediaItemWidget.utils.js +28 -6
  56. package/dist/components/MediaWidget/MediaItemWidget.utils.js.map +1 -1
  57. package/dist/components/MediaWidget/MediaPreviewModal.js +6 -7
  58. package/dist/components/MediaWidget/MediaPreviewModal.js.map +1 -1
  59. package/dist/components/MemoriArtifactSystem/components/ArtifactActions/styles.css +5 -5
  60. package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.css +119 -53
  61. package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.d.ts +1 -0
  62. package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js +19 -11
  63. package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js.map +1 -1
  64. package/dist/components/MemoriArtifactSystem/components/ArtifactDrawer/components/TabSwitch.css +4 -0
  65. package/dist/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.js +2 -2
  66. package/dist/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.js.map +1 -1
  67. package/dist/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js +1 -1
  68. package/dist/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js.map +1 -1
  69. package/dist/components/MemoriWidget/MemoriWidget.css +5 -5
  70. package/dist/components/MemoriWidget/MemoriWidget.d.ts +1 -0
  71. package/dist/components/MemoriWidget/MemoriWidget.js +788 -430
  72. package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
  73. package/dist/components/MicrophoneButton/MicrophoneButton.css +50 -18
  74. package/dist/components/MobileSessionPanel/MobileSessionPanel.d.ts +3 -1
  75. package/dist/components/MobileSessionPanel/MobileSessionPanel.js +5 -4
  76. package/dist/components/MobileSessionPanel/MobileSessionPanel.js.map +1 -1
  77. package/dist/components/PoweredBy/PoweredBy.css +4 -3
  78. package/dist/components/SettingsDrawer/SettingsDrawer.js +3 -1
  79. package/dist/components/SettingsDrawer/SettingsDrawer.js.map +1 -1
  80. package/dist/components/ShareButton/ShareButton.js +2 -4
  81. package/dist/components/ShareButton/ShareButton.js.map +1 -1
  82. package/dist/components/StartPanel/StartPanel.js +13 -6
  83. package/dist/components/StartPanel/StartPanel.js.map +1 -1
  84. package/dist/components/UploadButton/UploadButton.js +21 -5
  85. package/dist/components/UploadButton/UploadButton.js.map +1 -1
  86. package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js +126 -60
  87. package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
  88. package/dist/components/UploadButton/UploadImages/UploadImages.js +4 -2
  89. package/dist/components/UploadButton/UploadImages/UploadImages.js.map +1 -1
  90. package/dist/components/WhyThisAnswer/WhyThisAnswer.js +3 -1
  91. package/dist/components/WhyThisAnswer/WhyThisAnswer.js.map +1 -1
  92. package/dist/components/layouts/Chat.js +30 -30
  93. package/dist/components/layouts/Chat.js.map +1 -1
  94. package/dist/components/layouts/FullPage.js +36 -9
  95. package/dist/components/layouts/FullPage.js.map +1 -1
  96. package/dist/components/layouts/HiddenChat.js +12 -237
  97. package/dist/components/layouts/HiddenChat.js.map +1 -1
  98. package/dist/components/layouts/Totem.js +10 -1
  99. package/dist/components/layouts/Totem.js.map +1 -1
  100. package/dist/components/layouts/WebsiteAssistant/WebsiteAssistant.js +29 -2
  101. package/dist/components/layouts/WebsiteAssistant/WebsiteAssistant.js.map +1 -1
  102. package/dist/components/layouts/WebsiteAssistant/website-assistant.css +160 -59
  103. package/dist/components/layouts/ZoomedFullBody.js +36 -9
  104. package/dist/components/layouts/ZoomedFullBody.js.map +1 -1
  105. package/dist/components/layouts/chat.css +152 -63
  106. package/dist/components/layouts/fullpage.css +229 -84
  107. package/dist/components/layouts/hidden-chat.css +149 -34
  108. package/dist/components/layouts/totem.css +151 -50
  109. package/dist/components/layouts/zoomed-full-body.css +332 -33
  110. package/dist/context/widgetSurfaceContext.d.ts +3 -0
  111. package/dist/context/widgetSurfaceContext.js +11 -0
  112. package/dist/context/widgetSurfaceContext.js.map +1 -0
  113. package/dist/helpers/constants.d.ts +3 -0
  114. package/dist/helpers/constants.js +27 -1
  115. package/dist/helpers/constants.js.map +1 -1
  116. package/dist/helpers/credits.d.ts +5 -2
  117. package/dist/helpers/credits.js +5 -1
  118. package/dist/helpers/credits.js.map +1 -1
  119. package/dist/helpers/media.js +18 -3
  120. package/dist/helpers/media.js.map +1 -1
  121. package/dist/helpers/message.d.ts +1 -1
  122. package/dist/helpers/message.js +4 -4
  123. package/dist/helpers/message.js.map +1 -1
  124. package/dist/helpers/nats/getNatsConfig.d.ts +9 -0
  125. package/dist/helpers/nats/getNatsConfig.js +65 -0
  126. package/dist/helpers/nats/getNatsConfig.js.map +1 -0
  127. package/dist/helpers/nats/isSessionExpiredError.d.ts +3 -0
  128. package/dist/helpers/nats/isSessionExpiredError.js +36 -0
  129. package/dist/helpers/nats/isSessionExpiredError.js.map +1 -0
  130. package/dist/helpers/nats/useNats.d.ts +12 -0
  131. package/dist/helpers/nats/useNats.js +75 -0
  132. package/dist/helpers/nats/useNats.js.map +1 -0
  133. package/dist/helpers/nats/useNatsSession.d.ts +28 -0
  134. package/dist/helpers/nats/useNatsSession.js +212 -0
  135. package/dist/helpers/nats/useNatsSession.js.map +1 -0
  136. package/dist/helpers/positionPopover.d.ts +1 -0
  137. package/dist/helpers/positionPopover.js +7 -0
  138. package/dist/helpers/positionPopover.js.map +1 -0
  139. package/dist/helpers/usePressTooltip.d.ts +13 -0
  140. package/dist/helpers/usePressTooltip.js +23 -0
  141. package/dist/helpers/usePressTooltip.js.map +1 -0
  142. package/dist/helpers/utils.d.ts +21 -0
  143. package/dist/helpers/utils.js +75 -4
  144. package/dist/helpers/utils.js.map +1 -1
  145. package/dist/index.js +16 -16
  146. package/dist/index.js.map +1 -1
  147. package/dist/locales/de.json +11 -1
  148. package/dist/locales/en.json +12 -2
  149. package/dist/locales/es.json +11 -1
  150. package/dist/locales/fr.json +11 -1
  151. package/dist/locales/it.json +12 -2
  152. package/dist/styles.css +1 -163
  153. package/dist/types/integration.d.ts +3 -0
  154. package/dist/types/integration.js +16 -0
  155. package/dist/types/integration.js.map +1 -0
  156. package/dist/version.d.ts +1 -1
  157. package/dist/version.js +1 -1
  158. package/dist/version.js.map +1 -1
  159. package/esm/components/AgeVerificationModal/AgeVerificationModal.js +8 -3
  160. package/esm/components/AgeVerificationModal/AgeVerificationModal.js.map +1 -1
  161. package/esm/components/Auth/Auth.js +3 -1
  162. package/esm/components/Auth/Auth.js.map +1 -1
  163. package/esm/components/Avatar/Avatar.js +5 -10
  164. package/esm/components/Avatar/Avatar.js.map +1 -1
  165. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +9 -2
  166. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
  167. package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js +2 -2
  168. package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js.map +1 -1
  169. package/esm/components/Avatar/AvatarView/AvatarComponent/constants.d.ts +2 -0
  170. package/esm/components/Avatar/AvatarView/AvatarComponent/constants.js +13 -4
  171. package/esm/components/Avatar/AvatarView/AvatarComponent/constants.js.map +1 -1
  172. package/esm/components/Chat/Chat.css +108 -20
  173. package/esm/components/Chat/Chat.d.ts +3 -0
  174. package/esm/components/Chat/Chat.js +63 -55
  175. package/esm/components/Chat/Chat.js.map +1 -1
  176. package/esm/components/ChatBubble/ChatBubble.css +42 -14
  177. package/esm/components/ChatBubble/ChatBubble.js +36 -40
  178. package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
  179. package/esm/components/ChatHistoryDrawer/ChatHistory.css +4 -0
  180. package/esm/components/ChatHistoryDrawer/ChatHistory.js +27 -10
  181. package/esm/components/ChatHistoryDrawer/ChatHistory.js.map +1 -1
  182. package/esm/components/ChatInputs/ChatInputs.css +292 -108
  183. package/esm/components/ChatInputs/ChatInputs.d.ts +1 -0
  184. package/esm/components/ChatInputs/ChatInputs.js +2 -2
  185. package/esm/components/ChatInputs/ChatInputs.js.map +1 -1
  186. package/esm/components/ChatTextArea/ChatTextArea.css +30 -6
  187. package/esm/components/CompletionProviderStatus/CompletionProviderStatus.js +6 -3
  188. package/esm/components/CompletionProviderStatus/CompletionProviderStatus.js.map +1 -1
  189. package/esm/components/ContentPreviewModal/ContentPreviewModal.js +3 -1
  190. package/esm/components/ContentPreviewModal/ContentPreviewModal.js.map +1 -1
  191. package/esm/components/DateSelector/DateSelector.d.ts +2 -1
  192. package/esm/components/DateSelector/DateSelector.js +17 -7
  193. package/esm/components/DateSelector/DateSelector.js.map +1 -1
  194. package/esm/components/ExpertsDrawer/ExpertsDrawer.js +3 -1
  195. package/esm/components/ExpertsDrawer/ExpertsDrawer.js.map +1 -1
  196. package/esm/components/FilePreview/FilePreview.js +24 -7
  197. package/esm/components/FilePreview/FilePreview.js.map +1 -1
  198. package/esm/components/Header/ChatConsumptionDropdown.d.ts +3 -1
  199. package/esm/components/Header/ChatConsumptionDropdown.js +5 -4
  200. package/esm/components/Header/ChatConsumptionDropdown.js.map +1 -1
  201. package/esm/components/Header/Header.css +16 -10
  202. package/esm/components/Header/Header.js +104 -23
  203. package/esm/components/Header/Header.js.map +1 -1
  204. package/esm/components/KnownFacts/KnownFacts.js +7 -5
  205. package/esm/components/KnownFacts/KnownFacts.js.map +1 -1
  206. package/esm/components/LoginDrawer/LoginDrawer.css +1 -0
  207. package/esm/components/LoginDrawer/LoginDrawer.js +3 -1
  208. package/esm/components/LoginDrawer/LoginDrawer.js.map +1 -1
  209. package/esm/components/MediaWidget/MediaItemWidget.js +16 -14
  210. package/esm/components/MediaWidget/MediaItemWidget.js.map +1 -1
  211. package/esm/components/MediaWidget/MediaItemWidget.utils.d.ts +3 -2
  212. package/esm/components/MediaWidget/MediaItemWidget.utils.js +27 -6
  213. package/esm/components/MediaWidget/MediaItemWidget.utils.js.map +1 -1
  214. package/esm/components/MediaWidget/MediaPreviewModal.js +6 -7
  215. package/esm/components/MediaWidget/MediaPreviewModal.js.map +1 -1
  216. package/esm/components/MemoriArtifactSystem/components/ArtifactActions/styles.css +5 -5
  217. package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.css +119 -53
  218. package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.d.ts +1 -0
  219. package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js +19 -11
  220. package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.js.map +1 -1
  221. package/esm/components/MemoriArtifactSystem/components/ArtifactDrawer/components/TabSwitch.css +4 -0
  222. package/esm/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.js +2 -2
  223. package/esm/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.js.map +1 -1
  224. package/esm/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js +2 -2
  225. package/esm/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js.map +1 -1
  226. package/esm/components/MemoriWidget/MemoriWidget.css +5 -5
  227. package/esm/components/MemoriWidget/MemoriWidget.d.ts +1 -0
  228. package/esm/components/MemoriWidget/MemoriWidget.js +789 -431
  229. package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
  230. package/esm/components/MicrophoneButton/MicrophoneButton.css +50 -18
  231. package/esm/components/MobileSessionPanel/MobileSessionPanel.d.ts +3 -1
  232. package/esm/components/MobileSessionPanel/MobileSessionPanel.js +5 -4
  233. package/esm/components/MobileSessionPanel/MobileSessionPanel.js.map +1 -1
  234. package/esm/components/PoweredBy/PoweredBy.css +4 -3
  235. package/esm/components/SettingsDrawer/SettingsDrawer.js +3 -1
  236. package/esm/components/SettingsDrawer/SettingsDrawer.js.map +1 -1
  237. package/esm/components/ShareButton/ShareButton.js +2 -4
  238. package/esm/components/ShareButton/ShareButton.js.map +1 -1
  239. package/esm/components/StartPanel/StartPanel.js +13 -6
  240. package/esm/components/StartPanel/StartPanel.js.map +1 -1
  241. package/esm/components/UploadButton/UploadButton.js +21 -5
  242. package/esm/components/UploadButton/UploadButton.js.map +1 -1
  243. package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js +126 -60
  244. package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
  245. package/esm/components/UploadButton/UploadImages/UploadImages.js +4 -2
  246. package/esm/components/UploadButton/UploadImages/UploadImages.js.map +1 -1
  247. package/esm/components/WhyThisAnswer/WhyThisAnswer.js +3 -1
  248. package/esm/components/WhyThisAnswer/WhyThisAnswer.js.map +1 -1
  249. package/esm/components/layouts/Chat.js +30 -30
  250. package/esm/components/layouts/Chat.js.map +1 -1
  251. package/esm/components/layouts/FullPage.js +36 -9
  252. package/esm/components/layouts/FullPage.js.map +1 -1
  253. package/esm/components/layouts/HiddenChat.js +14 -239
  254. package/esm/components/layouts/HiddenChat.js.map +1 -1
  255. package/esm/components/layouts/Totem.js +10 -1
  256. package/esm/components/layouts/Totem.js.map +1 -1
  257. package/esm/components/layouts/WebsiteAssistant/WebsiteAssistant.js +29 -2
  258. package/esm/components/layouts/WebsiteAssistant/WebsiteAssistant.js.map +1 -1
  259. package/esm/components/layouts/WebsiteAssistant/website-assistant.css +160 -59
  260. package/esm/components/layouts/ZoomedFullBody.js +36 -9
  261. package/esm/components/layouts/ZoomedFullBody.js.map +1 -1
  262. package/esm/components/layouts/chat.css +152 -63
  263. package/esm/components/layouts/fullpage.css +229 -84
  264. package/esm/components/layouts/hidden-chat.css +149 -34
  265. package/esm/components/layouts/totem.css +151 -50
  266. package/esm/components/layouts/zoomed-full-body.css +332 -33
  267. package/esm/context/widgetSurfaceContext.d.ts +3 -0
  268. package/esm/context/widgetSurfaceContext.js +7 -0
  269. package/esm/context/widgetSurfaceContext.js.map +1 -0
  270. package/esm/helpers/constants.d.ts +3 -0
  271. package/esm/helpers/constants.js +26 -0
  272. package/esm/helpers/constants.js.map +1 -1
  273. package/esm/helpers/credits.d.ts +5 -2
  274. package/esm/helpers/credits.js +5 -1
  275. package/esm/helpers/credits.js.map +1 -1
  276. package/esm/helpers/media.js +18 -3
  277. package/esm/helpers/media.js.map +1 -1
  278. package/esm/helpers/message.d.ts +1 -1
  279. package/esm/helpers/message.js +2 -2
  280. package/esm/helpers/message.js.map +1 -1
  281. package/esm/helpers/nats/getNatsConfig.d.ts +9 -0
  282. package/esm/helpers/nats/getNatsConfig.js +61 -0
  283. package/esm/helpers/nats/getNatsConfig.js.map +1 -0
  284. package/esm/helpers/nats/isSessionExpiredError.d.ts +3 -0
  285. package/esm/helpers/nats/isSessionExpiredError.js +32 -0
  286. package/esm/helpers/nats/isSessionExpiredError.js.map +1 -0
  287. package/esm/helpers/nats/useNats.d.ts +12 -0
  288. package/esm/helpers/nats/useNats.js +72 -0
  289. package/esm/helpers/nats/useNats.js.map +1 -0
  290. package/esm/helpers/nats/useNatsSession.d.ts +28 -0
  291. package/esm/helpers/nats/useNatsSession.js +208 -0
  292. package/esm/helpers/nats/useNatsSession.js.map +1 -0
  293. package/esm/helpers/positionPopover.d.ts +1 -0
  294. package/esm/helpers/positionPopover.js +4 -0
  295. package/esm/helpers/positionPopover.js.map +1 -0
  296. package/esm/helpers/usePressTooltip.d.ts +13 -0
  297. package/esm/helpers/usePressTooltip.js +20 -0
  298. package/esm/helpers/usePressTooltip.js.map +1 -0
  299. package/esm/helpers/utils.d.ts +21 -0
  300. package/esm/helpers/utils.js +68 -3
  301. package/esm/helpers/utils.js.map +1 -1
  302. package/esm/index.js +17 -17
  303. package/esm/index.js.map +1 -1
  304. package/esm/locales/de.json +11 -1
  305. package/esm/locales/en.json +12 -2
  306. package/esm/locales/es.json +11 -1
  307. package/esm/locales/fr.json +11 -1
  308. package/esm/locales/it.json +12 -2
  309. package/esm/styles.css +1 -163
  310. package/esm/types/integration.d.ts +3 -0
  311. package/esm/types/integration.js +11 -0
  312. package/esm/types/integration.js.map +1 -0
  313. package/esm/version.d.ts +1 -1
  314. package/esm/version.js +1 -1
  315. package/esm/version.js.map +1 -1
  316. package/package.json +13 -6
  317. package/src/__snapshots__/index.test.tsx.snap +0 -50
  318. package/src/components/AgeVerificationModal/AgeVerificationModal.tsx +9 -1
  319. package/src/components/Auth/Auth.tsx +3 -0
  320. package/src/components/Avatar/Avatar.stories.tsx +45 -28
  321. package/src/components/Avatar/Avatar.test.tsx +54 -0
  322. package/src/components/Avatar/Avatar.tsx +8 -12
  323. package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.tsx +12 -5
  324. package/src/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.ts +2 -1
  325. package/src/components/Avatar/AvatarView/AvatarComponent/constants.ts +16 -4
  326. package/src/components/Avatar/__snapshots__/Avatar.test.tsx.snap +164 -0
  327. package/src/components/BlockedMemoriBadge/__snapshots__/BlockedMemoriBadge.test.tsx.snap +10 -10
  328. package/src/components/Chat/Chat.css +108 -20
  329. package/src/components/Chat/Chat.tsx +28 -0
  330. package/src/components/Chat/__snapshots__/Chat.test.tsx.snap +7449 -7369
  331. package/src/components/ChatBubble/ChatBubble.css +42 -14
  332. package/src/components/ChatBubble/ChatBubble.test.tsx +25 -1
  333. package/src/components/ChatBubble/ChatBubble.tsx +64 -39
  334. package/src/components/ChatBubble/__snapshots__/ChatBubble.test.tsx.snap +90 -90
  335. package/src/components/ChatHistoryDrawer/ChatHistory.css +4 -0
  336. package/src/components/ChatHistoryDrawer/ChatHistory.test.tsx +77 -1
  337. package/src/components/ChatHistoryDrawer/ChatHistory.tsx +59 -27
  338. package/src/components/ChatInputs/ChatInputs.css +292 -108
  339. package/src/components/ChatInputs/ChatInputs.tsx +14 -4
  340. package/src/components/ChatTextArea/ChatTextArea.css +30 -6
  341. package/src/components/CompletionProviderStatus/CompletionProviderStatus.tsx +8 -4
  342. package/src/components/CompletionProviderStatus/__snapshots__/CompletionProviderStatus.test.tsx.snap +6 -6
  343. package/src/components/ContentPreviewModal/ContentPreviewModal.tsx +3 -0
  344. package/src/components/DateSelector/DateSelector.stories.tsx +11 -2
  345. package/src/components/DateSelector/DateSelector.tsx +28 -9
  346. package/src/components/ExpertsDrawer/ExpertsDrawer.tsx +3 -0
  347. package/src/components/FeedbackButtons/__snapshots__/FeedbackButtons.test.tsx.snap +2 -2
  348. package/src/components/FilePreview/FilePreview.tsx +28 -7
  349. package/src/components/Header/ChatConsumptionDropdown.tsx +16 -5
  350. package/src/components/Header/Header.css +16 -10
  351. package/src/components/Header/Header.tsx +331 -53
  352. package/src/components/Header/__snapshots__/Header.test.tsx.snap +109 -83
  353. package/src/components/KnownFacts/KnownFacts.tsx +7 -0
  354. package/src/components/LoginDrawer/LoginDrawer.css +1 -0
  355. package/src/components/LoginDrawer/LoginDrawer.tsx +3 -0
  356. package/src/components/MediaWidget/MediaItemWidget.tsx +26 -13
  357. package/src/components/MediaWidget/MediaItemWidget.utils.test.ts +45 -2
  358. package/src/components/MediaWidget/MediaItemWidget.utils.ts +39 -6
  359. package/src/components/MediaWidget/MediaPreviewModal.tsx +9 -7
  360. package/src/components/MemoriArtifactSystem/ArtifactDrawer.stories.tsx +218 -2252
  361. package/src/components/MemoriArtifactSystem/components/ArtifactActions/styles.css +5 -5
  362. package/src/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.css +119 -53
  363. package/src/components/MemoriArtifactSystem/components/ArtifactDrawer/ArtifactDrawer.tsx +35 -16
  364. package/src/components/MemoriArtifactSystem/components/ArtifactDrawer/components/TabSwitch.css +4 -0
  365. package/src/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.tsx +4 -3
  366. package/src/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.tsx +2 -2
  367. package/src/components/MemoriWidget/MemoriWidget.css +5 -5
  368. package/src/components/MemoriWidget/MemoriWidget.tsx +1237 -729
  369. package/src/components/MicrophoneButton/MicrophoneButton.css +50 -18
  370. package/src/components/MobileSessionPanel/MobileSessionPanel.tsx +44 -30
  371. package/src/components/PoweredBy/PoweredBy.css +4 -3
  372. package/src/components/SettingsDrawer/SettingsDrawer.tsx +3 -0
  373. package/src/components/ShareButton/ShareButton.tsx +6 -3
  374. package/src/components/ShareButton/__snapshots__/ShareButton.test.tsx.snap +27 -18
  375. package/src/components/StartPanel/StartPanel.stories.tsx +22 -0
  376. package/src/components/StartPanel/StartPanel.test.tsx +64 -1
  377. package/src/components/StartPanel/StartPanel.tsx +30 -4
  378. package/src/components/StartPanel/__snapshots__/StartPanel.test.tsx.snap +293 -32
  379. package/src/components/UploadButton/UploadButton.tsx +30 -11
  380. package/src/components/UploadButton/UploadDocuments/UploadDocuments.tsx +151 -61
  381. package/src/components/UploadButton/UploadImages/UploadImages.tsx +4 -1
  382. package/src/components/UploadButton/__snapshots__/UploadButton.test.tsx.snap +4 -4
  383. package/src/components/WhyThisAnswer/WhyThisAnswer.tsx +3 -0
  384. package/src/components/layouts/Chat.tsx +157 -145
  385. package/src/components/layouts/FullPage.tsx +92 -25
  386. package/src/components/layouts/HiddenChat.tsx +21 -413
  387. package/src/components/layouts/Totem.tsx +20 -3
  388. package/src/components/layouts/WebsiteAssistant/WebsiteAssistant.tsx +71 -15
  389. package/src/components/layouts/WebsiteAssistant/__snapshots__/WebsiteAssistant.test.tsx.snap +58 -44
  390. package/src/components/layouts/WebsiteAssistant/website-assistant.css +160 -59
  391. package/src/components/layouts/ZoomedFullBody.tsx +95 -27
  392. package/src/components/layouts/__snapshots__/Chat.test.tsx.snap +621 -582
  393. package/src/components/layouts/__snapshots__/FullPage.test.tsx.snap +1252 -1162
  394. package/src/components/layouts/__snapshots__/HiddenChat.test.tsx.snap +551 -437
  395. package/src/components/layouts/__snapshots__/Totem.test.tsx.snap +589 -602
  396. package/src/components/layouts/__snapshots__/ZoomedFullBody.test.tsx.snap +609 -564
  397. package/src/components/layouts/chat.css +152 -63
  398. package/src/components/layouts/fullpage.css +229 -84
  399. package/src/components/layouts/hidden-chat.css +149 -34
  400. package/src/components/layouts/layouts.stories.tsx +135 -15
  401. package/src/components/layouts/totem.css +151 -50
  402. package/src/components/layouts/zoomed-full-body.css +332 -33
  403. package/src/context/widgetSurfaceContext.tsx +14 -0
  404. package/src/helpers/constants.ts +32 -1
  405. package/src/helpers/credits.ts +16 -1
  406. package/src/helpers/media.test.ts +36 -0
  407. package/src/helpers/media.ts +39 -12
  408. package/src/helpers/message.test.ts +28 -1
  409. package/src/helpers/message.ts +4 -4
  410. package/src/helpers/nats/getNatsConfig.ts +145 -0
  411. package/src/helpers/nats/isSessionExpiredError.test.ts +38 -0
  412. package/src/helpers/nats/isSessionExpiredError.ts +51 -0
  413. package/src/helpers/nats/useNats.ts +124 -0
  414. package/src/helpers/nats/useNatsSession.ts +394 -0
  415. package/src/helpers/positionPopover.test.ts +33 -0
  416. package/src/helpers/positionPopover.ts +13 -0
  417. package/src/helpers/usePressTooltip.ts +29 -0
  418. package/src/helpers/utils.test.ts +162 -0
  419. package/src/helpers/utils.ts +108 -3
  420. package/src/index.stories.tsx +32 -0
  421. package/src/index.tsx +1 -5
  422. package/src/locales/de.json +11 -1
  423. package/src/locales/en.json +12 -2
  424. package/src/locales/es.json +11 -1
  425. package/src/locales/fr.json +11 -1
  426. package/src/locales/it.json +12 -2
  427. package/src/styles.css +112 -12
  428. package/src/types/integration.test.ts +32 -0
  429. package/src/types/integration.ts +31 -0
  430. package/src/version.ts +1 -1
  431. package/dist/components/PositionDrawer/PositionDrawer.d.ts +0 -12
  432. package/dist/components/PositionDrawer/PositionDrawer.js +0 -17
  433. package/dist/components/PositionDrawer/PositionDrawer.js.map +0 -1
  434. package/dist/components/icons/AI.d.ts +0 -6
  435. package/dist/components/icons/AI.js +0 -6
  436. package/dist/components/icons/AI.js.map +0 -1
  437. package/dist/components/icons/Alert.d.ts +0 -6
  438. package/dist/components/icons/Alert.js +0 -6
  439. package/dist/components/icons/Alert.js.map +0 -1
  440. package/dist/components/icons/ArrowUp.d.ts +0 -6
  441. package/dist/components/icons/ArrowUp.js +0 -6
  442. package/dist/components/icons/ArrowUp.js.map +0 -1
  443. package/dist/components/icons/Bug.d.ts +0 -6
  444. package/dist/components/icons/Bug.js +0 -6
  445. package/dist/components/icons/Bug.js.map +0 -1
  446. package/dist/components/icons/Chat.d.ts +0 -6
  447. package/dist/components/icons/Chat.js +0 -6
  448. package/dist/components/icons/Chat.js.map +0 -1
  449. package/dist/components/icons/ChevronDown.d.ts +0 -6
  450. package/dist/components/icons/ChevronDown.js +0 -6
  451. package/dist/components/icons/ChevronDown.js.map +0 -1
  452. package/dist/components/icons/ChevronLeft.d.ts +0 -6
  453. package/dist/components/icons/ChevronLeft.js +0 -6
  454. package/dist/components/icons/ChevronLeft.js.map +0 -1
  455. package/dist/components/icons/ChevronRight.d.ts +0 -6
  456. package/dist/components/icons/ChevronRight.js +0 -6
  457. package/dist/components/icons/ChevronRight.js.map +0 -1
  458. package/dist/components/icons/ChevronUp.d.ts +0 -6
  459. package/dist/components/icons/ChevronUp.js +0 -6
  460. package/dist/components/icons/ChevronUp.js.map +0 -1
  461. package/dist/components/icons/Clear.d.ts +0 -6
  462. package/dist/components/icons/Clear.js +0 -6
  463. package/dist/components/icons/Clear.js.map +0 -1
  464. package/dist/components/icons/Close.d.ts +0 -7
  465. package/dist/components/icons/Close.js +0 -6
  466. package/dist/components/icons/Close.js.map +0 -1
  467. package/dist/components/icons/Code.d.ts +0 -6
  468. package/dist/components/icons/Code.js +0 -6
  469. package/dist/components/icons/Code.js.map +0 -1
  470. package/dist/components/icons/Copy.d.ts +0 -6
  471. package/dist/components/icons/Copy.js +0 -6
  472. package/dist/components/icons/Copy.js.map +0 -1
  473. package/dist/components/icons/DeepThought.d.ts +0 -6
  474. package/dist/components/icons/DeepThought.js +0 -6
  475. package/dist/components/icons/DeepThought.js.map +0 -1
  476. package/dist/components/icons/Delete.d.ts +0 -6
  477. package/dist/components/icons/Delete.js +0 -6
  478. package/dist/components/icons/Delete.js.map +0 -1
  479. package/dist/components/icons/Document.d.ts +0 -5
  480. package/dist/components/icons/Document.js +0 -10
  481. package/dist/components/icons/Document.js.map +0 -1
  482. package/dist/components/icons/Download.d.ts +0 -6
  483. package/dist/components/icons/Download.js +0 -6
  484. package/dist/components/icons/Download.js.map +0 -1
  485. package/dist/components/icons/Edit.d.ts +0 -6
  486. package/dist/components/icons/Edit.js +0 -6
  487. package/dist/components/icons/Edit.js.map +0 -1
  488. package/dist/components/icons/Expand.d.ts +0 -6
  489. package/dist/components/icons/Expand.js +0 -6
  490. package/dist/components/icons/Expand.js.map +0 -1
  491. package/dist/components/icons/Eye.d.ts +0 -6
  492. package/dist/components/icons/Eye.js +0 -6
  493. package/dist/components/icons/Eye.js.map +0 -1
  494. package/dist/components/icons/EyeInvisible.d.ts +0 -6
  495. package/dist/components/icons/EyeInvisible.js +0 -6
  496. package/dist/components/icons/EyeInvisible.js.map +0 -1
  497. package/dist/components/icons/Facebook.d.ts +0 -6
  498. package/dist/components/icons/Facebook.js +0 -6
  499. package/dist/components/icons/Facebook.js.map +0 -1
  500. package/dist/components/icons/Feedback.d.ts +0 -6
  501. package/dist/components/icons/Feedback.js +0 -6
  502. package/dist/components/icons/Feedback.js.map +0 -1
  503. package/dist/components/icons/File.d.ts +0 -6
  504. package/dist/components/icons/File.js +0 -6
  505. package/dist/components/icons/File.js.map +0 -1
  506. package/dist/components/icons/FileExcel.d.ts +0 -6
  507. package/dist/components/icons/FileExcel.js +0 -6
  508. package/dist/components/icons/FileExcel.js.map +0 -1
  509. package/dist/components/icons/FilePdf.d.ts +0 -6
  510. package/dist/components/icons/FilePdf.js +0 -6
  511. package/dist/components/icons/FilePdf.js.map +0 -1
  512. package/dist/components/icons/FileWord.d.ts +0 -6
  513. package/dist/components/icons/FileWord.js +0 -6
  514. package/dist/components/icons/FileWord.js.map +0 -1
  515. package/dist/components/icons/Fullscreen.d.ts +0 -6
  516. package/dist/components/icons/Fullscreen.js +0 -6
  517. package/dist/components/icons/Fullscreen.js.map +0 -1
  518. package/dist/components/icons/FullscreenExit.d.ts +0 -6
  519. package/dist/components/icons/FullscreenExit.js +0 -6
  520. package/dist/components/icons/FullscreenExit.js.map +0 -1
  521. package/dist/components/icons/Group.d.ts +0 -6
  522. package/dist/components/icons/Group.js +0 -6
  523. package/dist/components/icons/Group.js.map +0 -1
  524. package/dist/components/icons/History.d.ts +0 -7
  525. package/dist/components/icons/History.js +0 -6
  526. package/dist/components/icons/History.js.map +0 -1
  527. package/dist/components/icons/Image.d.ts +0 -4
  528. package/dist/components/icons/Image.js +0 -9
  529. package/dist/components/icons/Image.js.map +0 -1
  530. package/dist/components/icons/Info.d.ts +0 -6
  531. package/dist/components/icons/Info.js +0 -6
  532. package/dist/components/icons/Info.js.map +0 -1
  533. package/dist/components/icons/Link.d.ts +0 -6
  534. package/dist/components/icons/Link.js +0 -6
  535. package/dist/components/icons/Link.js.map +0 -1
  536. package/dist/components/icons/Linkedin.d.ts +0 -6
  537. package/dist/components/icons/Linkedin.js +0 -6
  538. package/dist/components/icons/Linkedin.js.map +0 -1
  539. package/dist/components/icons/Loading.d.ts +0 -7
  540. package/dist/components/icons/Loading.js +0 -10
  541. package/dist/components/icons/Loading.js.map +0 -1
  542. package/dist/components/icons/Logout.d.ts +0 -6
  543. package/dist/components/icons/Logout.js +0 -6
  544. package/dist/components/icons/Logout.js.map +0 -1
  545. package/dist/components/icons/Mail.d.ts +0 -6
  546. package/dist/components/icons/Mail.js +0 -6
  547. package/dist/components/icons/Mail.js.map +0 -1
  548. package/dist/components/icons/MapMarker.d.ts +0 -6
  549. package/dist/components/icons/MapMarker.js +0 -6
  550. package/dist/components/icons/MapMarker.js.map +0 -1
  551. package/dist/components/icons/MenuHorizontal.d.ts +0 -7
  552. package/dist/components/icons/MenuHorizontal.js +0 -6
  553. package/dist/components/icons/MenuHorizontal.js.map +0 -1
  554. package/dist/components/icons/MenuVertical.d.ts +0 -7
  555. package/dist/components/icons/MenuVertical.js +0 -6
  556. package/dist/components/icons/MenuVertical.js.map +0 -1
  557. package/dist/components/icons/Message.d.ts +0 -6
  558. package/dist/components/icons/Message.js +0 -6
  559. package/dist/components/icons/Message.js.map +0 -1
  560. package/dist/components/icons/Microphone.d.ts +0 -6
  561. package/dist/components/icons/Microphone.js +0 -6
  562. package/dist/components/icons/Microphone.js.map +0 -1
  563. package/dist/components/icons/Minus.d.ts +0 -6
  564. package/dist/components/icons/Minus.js +0 -6
  565. package/dist/components/icons/Minus.js.map +0 -1
  566. package/dist/components/icons/MinusCircle.d.ts +0 -6
  567. package/dist/components/icons/MinusCircle.js +0 -6
  568. package/dist/components/icons/MinusCircle.js.map +0 -1
  569. package/dist/components/icons/PaperClip.d.ts +0 -6
  570. package/dist/components/icons/PaperClip.js +0 -6
  571. package/dist/components/icons/PaperClip.js.map +0 -1
  572. package/dist/components/icons/Picture.d.ts +0 -6
  573. package/dist/components/icons/Picture.js +0 -6
  574. package/dist/components/icons/Picture.js.map +0 -1
  575. package/dist/components/icons/Plus.d.ts +0 -6
  576. package/dist/components/icons/Plus.js +0 -6
  577. package/dist/components/icons/Plus.js.map +0 -1
  578. package/dist/components/icons/Preview.d.ts +0 -4
  579. package/dist/components/icons/Preview.js +0 -9
  580. package/dist/components/icons/Preview.js.map +0 -1
  581. package/dist/components/icons/Print.d.ts +0 -6
  582. package/dist/components/icons/Print.js +0 -6
  583. package/dist/components/icons/Print.js.map +0 -1
  584. package/dist/components/icons/QuestionHelp.d.ts +0 -6
  585. package/dist/components/icons/QuestionHelp.js +0 -6
  586. package/dist/components/icons/QuestionHelp.js.map +0 -1
  587. package/dist/components/icons/Refresh.d.ts +0 -6
  588. package/dist/components/icons/Refresh.js +0 -6
  589. package/dist/components/icons/Refresh.js.map +0 -1
  590. package/dist/components/icons/SelectIcon.d.ts +0 -6
  591. package/dist/components/icons/SelectIcon.js +0 -6
  592. package/dist/components/icons/SelectIcon.js.map +0 -1
  593. package/dist/components/icons/Send.d.ts +0 -6
  594. package/dist/components/icons/Send.js +0 -6
  595. package/dist/components/icons/Send.js.map +0 -1
  596. package/dist/components/icons/Setting.d.ts +0 -6
  597. package/dist/components/icons/Setting.js +0 -6
  598. package/dist/components/icons/Setting.js.map +0 -1
  599. package/dist/components/icons/Share.d.ts +0 -6
  600. package/dist/components/icons/Share.js +0 -6
  601. package/dist/components/icons/Share.js.map +0 -1
  602. package/dist/components/icons/Sound.d.ts +0 -6
  603. package/dist/components/icons/Sound.js +0 -6
  604. package/dist/components/icons/Sound.js.map +0 -1
  605. package/dist/components/icons/SoundDeactivated.d.ts +0 -6
  606. package/dist/components/icons/SoundDeactivated.js +0 -6
  607. package/dist/components/icons/SoundDeactivated.js.map +0 -1
  608. package/dist/components/icons/Telegram.d.ts +0 -6
  609. package/dist/components/icons/Telegram.js +0 -6
  610. package/dist/components/icons/Telegram.js.map +0 -1
  611. package/dist/components/icons/ThumbDown.d.ts +0 -6
  612. package/dist/components/icons/ThumbDown.js +0 -6
  613. package/dist/components/icons/ThumbDown.js.map +0 -1
  614. package/dist/components/icons/ThumbUp.d.ts +0 -6
  615. package/dist/components/icons/ThumbUp.js +0 -6
  616. package/dist/components/icons/ThumbUp.js.map +0 -1
  617. package/dist/components/icons/Translation.d.ts +0 -6
  618. package/dist/components/icons/Translation.js +0 -6
  619. package/dist/components/icons/Translation.js.map +0 -1
  620. package/dist/components/icons/Twitter.d.ts +0 -6
  621. package/dist/components/icons/Twitter.js +0 -6
  622. package/dist/components/icons/Twitter.js.map +0 -1
  623. package/dist/components/icons/Upload.d.ts +0 -4
  624. package/dist/components/icons/Upload.js +0 -9
  625. package/dist/components/icons/Upload.js.map +0 -1
  626. package/dist/components/icons/User.d.ts +0 -6
  627. package/dist/components/icons/User.js +0 -6
  628. package/dist/components/icons/User.js.map +0 -1
  629. package/dist/components/icons/Warning.d.ts +0 -6
  630. package/dist/components/icons/Warning.js +0 -6
  631. package/dist/components/icons/Warning.js.map +0 -1
  632. package/dist/components/icons/WhatsApp.d.ts +0 -6
  633. package/dist/components/icons/WhatsApp.js +0 -6
  634. package/dist/components/icons/WhatsApp.js.map +0 -1
  635. package/dist/components/icons/loading.css +0 -14
  636. package/dist/components/layouts/WebsiteAssistant.d.ts +0 -4
  637. package/dist/components/layouts/WebsiteAssistant.js +0 -38
  638. package/dist/components/layouts/WebsiteAssistant.js.map +0 -1
  639. package/dist/components/layouts/website-assistant.css +0 -676
  640. package/dist/components/ui/Alert.css +0 -93
  641. package/dist/components/ui/Alert.d.ts +0 -18
  642. package/dist/components/ui/Alert.js +0 -42
  643. package/dist/components/ui/Alert.js.map +0 -1
  644. package/dist/components/ui/Button.css +0 -167
  645. package/dist/components/ui/Button.d.ts +0 -27
  646. package/dist/components/ui/Button.js +0 -23
  647. package/dist/components/ui/Button.js.map +0 -1
  648. package/dist/components/ui/Card.css +0 -65
  649. package/dist/components/ui/Card.d.ts +0 -13
  650. package/dist/components/ui/Card.js +0 -14
  651. package/dist/components/ui/Card.js.map +0 -1
  652. package/dist/components/ui/Checkbox.css +0 -116
  653. package/dist/components/ui/Checkbox.d.ts +0 -11
  654. package/dist/components/ui/Checkbox.js +0 -20
  655. package/dist/components/ui/Checkbox.js.map +0 -1
  656. package/dist/components/ui/ConfirmDialog.css +0 -42
  657. package/dist/components/ui/ConfirmDialog.d.ts +0 -11
  658. package/dist/components/ui/ConfirmDialog.js +0 -12
  659. package/dist/components/ui/ConfirmDialog.js.map +0 -1
  660. package/dist/components/ui/Details.css +0 -66
  661. package/dist/components/ui/Drawer.css +0 -270
  662. package/dist/components/ui/Drawer.d.ts +0 -46
  663. package/dist/components/ui/Drawer.js +0 -60
  664. package/dist/components/ui/Drawer.js.map +0 -1
  665. package/dist/components/ui/Dropdown.css +0 -173
  666. package/dist/components/ui/Dropdown.d.ts +0 -11
  667. package/dist/components/ui/Dropdown.js +0 -33
  668. package/dist/components/ui/Dropdown.js.map +0 -1
  669. package/dist/components/ui/Expandable.css +0 -15
  670. package/dist/components/ui/Expandable.d.ts +0 -15
  671. package/dist/components/ui/Expandable.js +0 -59
  672. package/dist/components/ui/Expandable.js.map +0 -1
  673. package/dist/components/ui/Modal.css +0 -98
  674. package/dist/components/ui/Modal.d.ts +0 -16
  675. package/dist/components/ui/Modal.js +0 -24
  676. package/dist/components/ui/Modal.js.map +0 -1
  677. package/dist/components/ui/Select.css +0 -138
  678. package/dist/components/ui/Select.d.ts +0 -17
  679. package/dist/components/ui/Select.js +0 -17
  680. package/dist/components/ui/Select.js.map +0 -1
  681. package/dist/components/ui/Slider.css +0 -192
  682. package/dist/components/ui/Slider.d.ts +0 -12
  683. package/dist/components/ui/Slider.js +0 -78
  684. package/dist/components/ui/Slider.js.map +0 -1
  685. package/dist/components/ui/Spin.css +0 -31
  686. package/dist/components/ui/Spin.d.ts +0 -9
  687. package/dist/components/ui/Spin.js +0 -12
  688. package/dist/components/ui/Spin.js.map +0 -1
  689. package/dist/components/ui/Table.css +0 -132
  690. package/dist/components/ui/Tooltip.css +0 -171
  691. package/dist/components/ui/Tooltip.d.ts +0 -11
  692. package/dist/components/ui/Tooltip.js +0 -90
  693. package/dist/components/ui/Tooltip.js.map +0 -1
  694. package/esm/components/PositionDrawer/PositionDrawer.d.ts +0 -12
  695. package/esm/components/PositionDrawer/PositionDrawer.js +0 -14
  696. package/esm/components/PositionDrawer/PositionDrawer.js.map +0 -1
  697. package/esm/components/icons/AI.d.ts +0 -6
  698. package/esm/components/icons/AI.js +0 -4
  699. package/esm/components/icons/AI.js.map +0 -1
  700. package/esm/components/icons/Alert.d.ts +0 -6
  701. package/esm/components/icons/Alert.js +0 -4
  702. package/esm/components/icons/Alert.js.map +0 -1
  703. package/esm/components/icons/ArrowUp.d.ts +0 -6
  704. package/esm/components/icons/ArrowUp.js +0 -4
  705. package/esm/components/icons/ArrowUp.js.map +0 -1
  706. package/esm/components/icons/Bug.d.ts +0 -6
  707. package/esm/components/icons/Bug.js +0 -4
  708. package/esm/components/icons/Bug.js.map +0 -1
  709. package/esm/components/icons/Chat.d.ts +0 -6
  710. package/esm/components/icons/Chat.js +0 -4
  711. package/esm/components/icons/Chat.js.map +0 -1
  712. package/esm/components/icons/ChevronDown.d.ts +0 -6
  713. package/esm/components/icons/ChevronDown.js +0 -4
  714. package/esm/components/icons/ChevronDown.js.map +0 -1
  715. package/esm/components/icons/ChevronLeft.d.ts +0 -6
  716. package/esm/components/icons/ChevronLeft.js +0 -4
  717. package/esm/components/icons/ChevronLeft.js.map +0 -1
  718. package/esm/components/icons/ChevronRight.d.ts +0 -6
  719. package/esm/components/icons/ChevronRight.js +0 -4
  720. package/esm/components/icons/ChevronRight.js.map +0 -1
  721. package/esm/components/icons/ChevronUp.d.ts +0 -6
  722. package/esm/components/icons/ChevronUp.js +0 -4
  723. package/esm/components/icons/ChevronUp.js.map +0 -1
  724. package/esm/components/icons/Clear.d.ts +0 -6
  725. package/esm/components/icons/Clear.js +0 -4
  726. package/esm/components/icons/Clear.js.map +0 -1
  727. package/esm/components/icons/Close.d.ts +0 -7
  728. package/esm/components/icons/Close.js +0 -4
  729. package/esm/components/icons/Close.js.map +0 -1
  730. package/esm/components/icons/Code.d.ts +0 -6
  731. package/esm/components/icons/Code.js +0 -4
  732. package/esm/components/icons/Code.js.map +0 -1
  733. package/esm/components/icons/Copy.d.ts +0 -6
  734. package/esm/components/icons/Copy.js +0 -4
  735. package/esm/components/icons/Copy.js.map +0 -1
  736. package/esm/components/icons/DeepThought.d.ts +0 -6
  737. package/esm/components/icons/DeepThought.js +0 -4
  738. package/esm/components/icons/DeepThought.js.map +0 -1
  739. package/esm/components/icons/Delete.d.ts +0 -6
  740. package/esm/components/icons/Delete.js +0 -4
  741. package/esm/components/icons/Delete.js.map +0 -1
  742. package/esm/components/icons/Document.d.ts +0 -5
  743. package/esm/components/icons/Document.js +0 -6
  744. package/esm/components/icons/Document.js.map +0 -1
  745. package/esm/components/icons/Download.d.ts +0 -6
  746. package/esm/components/icons/Download.js +0 -4
  747. package/esm/components/icons/Download.js.map +0 -1
  748. package/esm/components/icons/Edit.d.ts +0 -6
  749. package/esm/components/icons/Edit.js +0 -4
  750. package/esm/components/icons/Edit.js.map +0 -1
  751. package/esm/components/icons/Expand.d.ts +0 -6
  752. package/esm/components/icons/Expand.js +0 -4
  753. package/esm/components/icons/Expand.js.map +0 -1
  754. package/esm/components/icons/Eye.d.ts +0 -6
  755. package/esm/components/icons/Eye.js +0 -4
  756. package/esm/components/icons/Eye.js.map +0 -1
  757. package/esm/components/icons/EyeInvisible.d.ts +0 -6
  758. package/esm/components/icons/EyeInvisible.js +0 -4
  759. package/esm/components/icons/EyeInvisible.js.map +0 -1
  760. package/esm/components/icons/Facebook.d.ts +0 -6
  761. package/esm/components/icons/Facebook.js +0 -4
  762. package/esm/components/icons/Facebook.js.map +0 -1
  763. package/esm/components/icons/Feedback.d.ts +0 -6
  764. package/esm/components/icons/Feedback.js +0 -4
  765. package/esm/components/icons/Feedback.js.map +0 -1
  766. package/esm/components/icons/File.d.ts +0 -6
  767. package/esm/components/icons/File.js +0 -4
  768. package/esm/components/icons/File.js.map +0 -1
  769. package/esm/components/icons/FileExcel.d.ts +0 -6
  770. package/esm/components/icons/FileExcel.js +0 -4
  771. package/esm/components/icons/FileExcel.js.map +0 -1
  772. package/esm/components/icons/FilePdf.d.ts +0 -6
  773. package/esm/components/icons/FilePdf.js +0 -4
  774. package/esm/components/icons/FilePdf.js.map +0 -1
  775. package/esm/components/icons/FileWord.d.ts +0 -6
  776. package/esm/components/icons/FileWord.js +0 -4
  777. package/esm/components/icons/FileWord.js.map +0 -1
  778. package/esm/components/icons/Fullscreen.d.ts +0 -6
  779. package/esm/components/icons/Fullscreen.js +0 -4
  780. package/esm/components/icons/Fullscreen.js.map +0 -1
  781. package/esm/components/icons/FullscreenExit.d.ts +0 -6
  782. package/esm/components/icons/FullscreenExit.js +0 -4
  783. package/esm/components/icons/FullscreenExit.js.map +0 -1
  784. package/esm/components/icons/Group.d.ts +0 -6
  785. package/esm/components/icons/Group.js +0 -4
  786. package/esm/components/icons/Group.js.map +0 -1
  787. package/esm/components/icons/History.d.ts +0 -7
  788. package/esm/components/icons/History.js +0 -4
  789. package/esm/components/icons/History.js.map +0 -1
  790. package/esm/components/icons/Image.d.ts +0 -4
  791. package/esm/components/icons/Image.js +0 -5
  792. package/esm/components/icons/Image.js.map +0 -1
  793. package/esm/components/icons/Info.d.ts +0 -6
  794. package/esm/components/icons/Info.js +0 -4
  795. package/esm/components/icons/Info.js.map +0 -1
  796. package/esm/components/icons/Link.d.ts +0 -6
  797. package/esm/components/icons/Link.js +0 -4
  798. package/esm/components/icons/Link.js.map +0 -1
  799. package/esm/components/icons/Linkedin.d.ts +0 -6
  800. package/esm/components/icons/Linkedin.js +0 -4
  801. package/esm/components/icons/Linkedin.js.map +0 -1
  802. package/esm/components/icons/Loading.d.ts +0 -7
  803. package/esm/components/icons/Loading.js +0 -7
  804. package/esm/components/icons/Loading.js.map +0 -1
  805. package/esm/components/icons/Logout.d.ts +0 -6
  806. package/esm/components/icons/Logout.js +0 -4
  807. package/esm/components/icons/Logout.js.map +0 -1
  808. package/esm/components/icons/Mail.d.ts +0 -6
  809. package/esm/components/icons/Mail.js +0 -4
  810. package/esm/components/icons/Mail.js.map +0 -1
  811. package/esm/components/icons/MapMarker.d.ts +0 -6
  812. package/esm/components/icons/MapMarker.js +0 -4
  813. package/esm/components/icons/MapMarker.js.map +0 -1
  814. package/esm/components/icons/MenuHorizontal.d.ts +0 -7
  815. package/esm/components/icons/MenuHorizontal.js +0 -4
  816. package/esm/components/icons/MenuHorizontal.js.map +0 -1
  817. package/esm/components/icons/MenuVertical.d.ts +0 -7
  818. package/esm/components/icons/MenuVertical.js +0 -4
  819. package/esm/components/icons/MenuVertical.js.map +0 -1
  820. package/esm/components/icons/Message.d.ts +0 -6
  821. package/esm/components/icons/Message.js +0 -4
  822. package/esm/components/icons/Message.js.map +0 -1
  823. package/esm/components/icons/Microphone.d.ts +0 -6
  824. package/esm/components/icons/Microphone.js +0 -4
  825. package/esm/components/icons/Microphone.js.map +0 -1
  826. package/esm/components/icons/Minus.d.ts +0 -6
  827. package/esm/components/icons/Minus.js +0 -4
  828. package/esm/components/icons/Minus.js.map +0 -1
  829. package/esm/components/icons/MinusCircle.d.ts +0 -6
  830. package/esm/components/icons/MinusCircle.js +0 -4
  831. package/esm/components/icons/MinusCircle.js.map +0 -1
  832. package/esm/components/icons/PaperClip.d.ts +0 -6
  833. package/esm/components/icons/PaperClip.js +0 -4
  834. package/esm/components/icons/PaperClip.js.map +0 -1
  835. package/esm/components/icons/Picture.d.ts +0 -6
  836. package/esm/components/icons/Picture.js +0 -4
  837. package/esm/components/icons/Picture.js.map +0 -1
  838. package/esm/components/icons/Plus.d.ts +0 -6
  839. package/esm/components/icons/Plus.js +0 -4
  840. package/esm/components/icons/Plus.js.map +0 -1
  841. package/esm/components/icons/Preview.d.ts +0 -4
  842. package/esm/components/icons/Preview.js +0 -5
  843. package/esm/components/icons/Preview.js.map +0 -1
  844. package/esm/components/icons/Print.d.ts +0 -6
  845. package/esm/components/icons/Print.js +0 -4
  846. package/esm/components/icons/Print.js.map +0 -1
  847. package/esm/components/icons/QuestionHelp.d.ts +0 -6
  848. package/esm/components/icons/QuestionHelp.js +0 -4
  849. package/esm/components/icons/QuestionHelp.js.map +0 -1
  850. package/esm/components/icons/Refresh.d.ts +0 -6
  851. package/esm/components/icons/Refresh.js +0 -4
  852. package/esm/components/icons/Refresh.js.map +0 -1
  853. package/esm/components/icons/SelectIcon.d.ts +0 -6
  854. package/esm/components/icons/SelectIcon.js +0 -4
  855. package/esm/components/icons/SelectIcon.js.map +0 -1
  856. package/esm/components/icons/Send.d.ts +0 -6
  857. package/esm/components/icons/Send.js +0 -4
  858. package/esm/components/icons/Send.js.map +0 -1
  859. package/esm/components/icons/Setting.d.ts +0 -6
  860. package/esm/components/icons/Setting.js +0 -4
  861. package/esm/components/icons/Setting.js.map +0 -1
  862. package/esm/components/icons/Share.d.ts +0 -6
  863. package/esm/components/icons/Share.js +0 -4
  864. package/esm/components/icons/Share.js.map +0 -1
  865. package/esm/components/icons/Sound.d.ts +0 -6
  866. package/esm/components/icons/Sound.js +0 -4
  867. package/esm/components/icons/Sound.js.map +0 -1
  868. package/esm/components/icons/SoundDeactivated.d.ts +0 -6
  869. package/esm/components/icons/SoundDeactivated.js +0 -4
  870. package/esm/components/icons/SoundDeactivated.js.map +0 -1
  871. package/esm/components/icons/Telegram.d.ts +0 -6
  872. package/esm/components/icons/Telegram.js +0 -4
  873. package/esm/components/icons/Telegram.js.map +0 -1
  874. package/esm/components/icons/ThumbDown.d.ts +0 -6
  875. package/esm/components/icons/ThumbDown.js +0 -4
  876. package/esm/components/icons/ThumbDown.js.map +0 -1
  877. package/esm/components/icons/ThumbUp.d.ts +0 -6
  878. package/esm/components/icons/ThumbUp.js +0 -4
  879. package/esm/components/icons/ThumbUp.js.map +0 -1
  880. package/esm/components/icons/Translation.d.ts +0 -6
  881. package/esm/components/icons/Translation.js +0 -4
  882. package/esm/components/icons/Translation.js.map +0 -1
  883. package/esm/components/icons/Twitter.d.ts +0 -6
  884. package/esm/components/icons/Twitter.js +0 -4
  885. package/esm/components/icons/Twitter.js.map +0 -1
  886. package/esm/components/icons/Upload.d.ts +0 -4
  887. package/esm/components/icons/Upload.js +0 -5
  888. package/esm/components/icons/Upload.js.map +0 -1
  889. package/esm/components/icons/User.d.ts +0 -6
  890. package/esm/components/icons/User.js +0 -4
  891. package/esm/components/icons/User.js.map +0 -1
  892. package/esm/components/icons/Warning.d.ts +0 -6
  893. package/esm/components/icons/Warning.js +0 -4
  894. package/esm/components/icons/Warning.js.map +0 -1
  895. package/esm/components/icons/WhatsApp.d.ts +0 -6
  896. package/esm/components/icons/WhatsApp.js +0 -4
  897. package/esm/components/icons/WhatsApp.js.map +0 -1
  898. package/esm/components/icons/loading.css +0 -14
  899. package/esm/components/layouts/WebsiteAssistant.d.ts +0 -4
  900. package/esm/components/layouts/WebsiteAssistant.js +0 -35
  901. package/esm/components/layouts/WebsiteAssistant.js.map +0 -1
  902. package/esm/components/layouts/website-assistant.css +0 -676
  903. package/esm/components/ui/Alert.css +0 -93
  904. package/esm/components/ui/Alert.d.ts +0 -18
  905. package/esm/components/ui/Alert.js +0 -39
  906. package/esm/components/ui/Alert.js.map +0 -1
  907. package/esm/components/ui/Button.css +0 -167
  908. package/esm/components/ui/Button.d.ts +0 -27
  909. package/esm/components/ui/Button.js +0 -20
  910. package/esm/components/ui/Button.js.map +0 -1
  911. package/esm/components/ui/Card.css +0 -65
  912. package/esm/components/ui/Card.d.ts +0 -13
  913. package/esm/components/ui/Card.js +0 -11
  914. package/esm/components/ui/Card.js.map +0 -1
  915. package/esm/components/ui/Checkbox.css +0 -116
  916. package/esm/components/ui/Checkbox.d.ts +0 -11
  917. package/esm/components/ui/Checkbox.js +0 -17
  918. package/esm/components/ui/Checkbox.js.map +0 -1
  919. package/esm/components/ui/ConfirmDialog.css +0 -42
  920. package/esm/components/ui/ConfirmDialog.d.ts +0 -11
  921. package/esm/components/ui/ConfirmDialog.js +0 -9
  922. package/esm/components/ui/ConfirmDialog.js.map +0 -1
  923. package/esm/components/ui/Details.css +0 -66
  924. package/esm/components/ui/Drawer.css +0 -270
  925. package/esm/components/ui/Drawer.d.ts +0 -46
  926. package/esm/components/ui/Drawer.js +0 -57
  927. package/esm/components/ui/Drawer.js.map +0 -1
  928. package/esm/components/ui/Dropdown.css +0 -173
  929. package/esm/components/ui/Dropdown.d.ts +0 -11
  930. package/esm/components/ui/Dropdown.js +0 -30
  931. package/esm/components/ui/Dropdown.js.map +0 -1
  932. package/esm/components/ui/Expandable.css +0 -15
  933. package/esm/components/ui/Expandable.d.ts +0 -15
  934. package/esm/components/ui/Expandable.js +0 -56
  935. package/esm/components/ui/Expandable.js.map +0 -1
  936. package/esm/components/ui/Modal.css +0 -98
  937. package/esm/components/ui/Modal.d.ts +0 -16
  938. package/esm/components/ui/Modal.js +0 -21
  939. package/esm/components/ui/Modal.js.map +0 -1
  940. package/esm/components/ui/Select.css +0 -138
  941. package/esm/components/ui/Select.d.ts +0 -17
  942. package/esm/components/ui/Select.js +0 -14
  943. package/esm/components/ui/Select.js.map +0 -1
  944. package/esm/components/ui/Slider.css +0 -192
  945. package/esm/components/ui/Slider.d.ts +0 -12
  946. package/esm/components/ui/Slider.js +0 -75
  947. package/esm/components/ui/Slider.js.map +0 -1
  948. package/esm/components/ui/Spin.css +0 -31
  949. package/esm/components/ui/Spin.d.ts +0 -9
  950. package/esm/components/ui/Spin.js +0 -9
  951. package/esm/components/ui/Spin.js.map +0 -1
  952. package/esm/components/ui/Table.css +0 -132
  953. package/esm/components/ui/Tooltip.css +0 -171
  954. package/esm/components/ui/Tooltip.d.ts +0 -11
  955. package/esm/components/ui/Tooltip.js +0 -87
  956. package/esm/components/ui/Tooltip.js.map +0 -1
@@ -24,6 +24,7 @@ import type {
24
24
  PiiDetectionConfig,
25
25
  } from '../../types/layout';
26
26
  import { checkPii } from '../../helpers/piiDetection'; // PII check when integrationConfig.layout has piiDetection.enabled
27
+ import { shouldRestartSessionOnPositionPopoverClose } from '../../helpers/positionPopover';
27
28
 
28
29
  // Libraries
29
30
  import React, {
@@ -39,7 +40,13 @@ import memoriApiClient from '@memori.ai/memori-api-client';
39
40
  import { IAudioContext } from 'standardized-audio-context';
40
41
  import cx from 'classnames';
41
42
  import { DateTime } from 'luxon';
42
- import { useAlertManager, createAlertOptions } from '@memori.ai/ui';
43
+ import {
44
+ useAlertManager,
45
+ createAlertOptions,
46
+ MemoriUIProvider,
47
+ AlertViewport,
48
+ } from '@memori.ai/ui';
49
+ import { WidgetSurfaceProvider } from '../../context/widgetSurfaceContext';
43
50
 
44
51
  // Components
45
52
  import MemoriAuth from '../Auth/Auth';
@@ -88,6 +95,16 @@ import { sanitizeText } from '../../helpers/sanitizer';
88
95
  import { TTSConfig, useTTS } from '../../helpers/tts/useTTS';
89
96
  import ChatHistoryDrawer from '../ChatHistoryDrawer/ChatHistory';
90
97
  import { STTConfig, useSTT } from '../../helpers/stt/useSTT';
98
+ import { useNats } from '../../helpers/nats/useNats';
99
+ import {
100
+ NatsProgressEvent,
101
+ NatsDialogResponseEvent,
102
+ NatsErrorEvent,
103
+ } from '../../helpers/nats/useNatsSession';
104
+ import {
105
+ isSessionExpiredNatsError,
106
+ isSessionExpiredNatsResponse,
107
+ } from '../../helpers/nats/isSessionExpiredError';
91
108
 
92
109
  // Widget utilities and helpers
93
110
  const getMemoriState = (integrationId?: string): object | null => {
@@ -118,7 +135,21 @@ const getMemoriState = (integrationId?: string): object | null => {
118
135
  };
119
136
  };
120
137
 
121
- /** Place spec with all nulls for postTextEnteredEvent when position is not set or user chose "I don't want to provide my position". */
138
+ /** Unified login token resolution: React state > ref > call-site override > props. */
139
+ const resolveLoginTokenValue = (
140
+ loginToken: string | undefined,
141
+ userTokenRef: string | undefined,
142
+ callAdditionalInfoLoginToken: string | undefined,
143
+ additionalInfoLoginToken: string | undefined,
144
+ authTokenProp: string | undefined
145
+ ): string | undefined =>
146
+ loginToken ??
147
+ userTokenRef ??
148
+ callAdditionalInfoLoginToken ??
149
+ additionalInfoLoginToken ??
150
+ authTokenProp;
151
+
152
+ /** Place spec with all nulls for postEnterTextAsync when position is not set or user chose "I don't want to provide my position". */
122
153
  const NULL_PLACE_SPEC = {
123
154
  placeName: null,
124
155
  latitude: null,
@@ -126,6 +157,18 @@ const NULL_PLACE_SPEC = {
126
157
  uncertaintyKm: null,
127
158
  } as const;
128
159
 
160
+ const logWidgetError = (context: string, detail?: unknown) => {
161
+ console.error(`[MemoriWidget] ${context}`, detail ?? '');
162
+ };
163
+
164
+ /** Reads correlation id from HTTP async response (supports camelCase / snake_case). */
165
+ function readCorrelationID(response: {
166
+ correlationID?: string;
167
+ }): string | undefined {
168
+ const value = response.correlationID;
169
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
170
+ }
171
+
129
172
  type MemoriTextEnteredEvent = CustomEvent<{
130
173
  text: string;
131
174
  waitForPrevious?: boolean;
@@ -359,7 +402,6 @@ window.typeBatchMessages = typeBatchMessages;
359
402
  let audioContext: IAudioContext;
360
403
 
361
404
  let memoriPassword: string | undefined;
362
- let userToken: string | undefined;
363
405
 
364
406
  export interface LayoutProps {
365
407
  Header?: typeof Header;
@@ -381,6 +423,9 @@ export interface LayoutProps {
381
423
  onSidebarToggle?: (isOpen: boolean) => void;
382
424
  /** When true or "true" (e.g. from integrationConfig or web component attribute), hide the 3D avatar. */
383
425
  avatar3dHidden?: boolean | string;
426
+ /** TOTEM only: max-width of the shared content axis (avatar + panel + status).
427
+ * Accepts a number (px) or a CSS length string; enables vertical-kiosk widths. */
428
+ totemContentMaxWidth?: number | string;
384
429
  }
385
430
 
386
431
  export interface Props {
@@ -474,20 +519,23 @@ export function getChatStyles(
474
519
 
475
520
  const primaryContent = config?.buttonTextColor ?? '#ffffff';
476
521
 
522
+ // Match @memori.ai/ui token semantics:
523
+ // --memori-surface-contrast = ink (#000 light / #fff dark)
524
+ // --memori-surface-contrast-inverse = surface (#fff light / #000 dark)
477
525
  return {
478
526
  '--memori-primary-color': primary,
479
527
  '--memori-primary': primary,
480
528
  '--memori-primary-content': primaryContent,
481
529
  '--memori-primary-hover':
482
- 'color-mix(in oklch, var(--memori-primary), var(--memori-surface-contrast-inverse, black) 15%)',
530
+ 'color-mix(in oklch, var(--memori-primary), var(--memori-surface-contrast, black) 15%)',
483
531
  '--memori-primary-active':
484
- 'color-mix(in oklch, var(--memori-primary), var(--memori-surface-contrast-inverse, black) 25%)',
532
+ 'color-mix(in oklch, var(--memori-primary), var(--memori-surface-contrast, black) 25%)',
485
533
  '--memori-primary-disabled':
486
534
  'color-mix(in oklch, var(--memori-primary), transparent 60%)',
487
535
  '--memori-primary-subtle':
488
- 'color-mix(in oklch, var(--memori-primary), var(--memori-surface-contrast, white) 60%)',
536
+ 'color-mix(in oklch, var(--memori-primary), var(--memori-surface-contrast-inverse, white) 60%)',
489
537
  '--memori-primary-subtle-hover':
490
- 'color-mix(in oklch, var(--memori-primary), var(--memori-surface-contrast, white) 50%)',
538
+ 'color-mix(in oklch, var(--memori-primary), var(--memori-surface-contrast-inverse, white) 50%)',
491
539
  '--memori-border-primary':
492
540
  'color-mix(in oklch, var(--memori-primary), transparent 70%)',
493
541
  '--memori-border-primary-hover':
@@ -498,9 +546,9 @@ export function getChatStyles(
498
546
  '--memori-shadow-primary':
499
547
  '0 8px 16px -4px color-mix(in oklch, var(--memori-primary), transparent 70%)',
500
548
  '--memori-skeleton-base':
501
- 'color-mix(in oklch, var(--memori-primary), var(--memori-surface-contrast, white) 85%)',
549
+ 'color-mix(in oklch, var(--memori-primary), var(--memori-surface-contrast-inverse, white) 85%)',
502
550
  '--memori-skeleton-highlight':
503
- 'color-mix(in oklch, var(--memori-primary), var(--memori-surface-contrast, white) 75%)',
551
+ 'color-mix(in oklch, var(--memori-primary), var(--memori-surface-contrast-inverse, white) 75%)',
504
552
  } as CSSProperties;
505
553
  }
506
554
 
@@ -576,6 +624,7 @@ const MemoriWidget = ({
576
624
  const {
577
625
  initSession,
578
626
  deleteSession,
627
+ postEnterTextAsync,
579
628
  postTextEnteredEvent,
580
629
  postPlaceChangedEvent,
581
630
  postDateChangedEvent,
@@ -588,58 +637,115 @@ const MemoriWidget = ({
588
637
  const [instruct, setInstruct] = useState(false);
589
638
  const [enableFocusChatInput, setEnableFocusChatInput] = useState(true);
590
639
 
591
- const widgetRootRef = useRef<HTMLDivElement>(null);
640
+ // Capture the widget root via a callback ref so the value is non-null on
641
+ // the first render that matters (used as the `container` for portal-based
642
+ // UI primitives via `MemoriUIProvider`). `useRef` would not trigger a
643
+ // re-render and would leave the value `null` on the first pass.
644
+ const [widgetRootEl, setWidgetRootEl] = useState<HTMLDivElement | null>(null);
645
+ // Inner surface establishes `contain: layout` for Drawers/Modals. Kept separate
646
+ // from widgetRootEl so Floating UI menus can portal outside containment.
647
+ const [widgetSurfaceEl, setWidgetSurfaceEl] = useState<HTMLDivElement | null>(
648
+ null
649
+ );
592
650
  const [isDarkTheme, setIsDarkTheme] = useState(false);
593
651
  useEffect(() => {
594
- const el = widgetRootRef.current;
595
- if (!el) return;
652
+ if (!widgetRootEl) return;
596
653
  const check = () => {
597
- setIsDarkTheme(!!el.closest('[data-theme="dark"]'));
654
+ setIsDarkTheme(!!widgetRootEl.closest('[data-theme="dark"]'));
598
655
  };
599
656
  check();
600
657
  const observer = new MutationObserver(check);
601
- const parent = el.parentElement ?? document.body;
658
+ const parent = widgetRootEl.parentElement ?? document.body;
602
659
  observer.observe(parent, {
603
660
  attributes: true,
604
661
  attributeFilter: ['data-theme'],
605
662
  subtree: true,
606
663
  });
607
664
  return () => observer.disconnect();
608
- }, []);
665
+ }, [widgetRootEl]);
609
666
 
610
667
  const [loginToken, setLoginToken] = useState<string | undefined>(
611
668
  additionalInfo?.loginToken ?? authToken
612
669
  );
670
+ const userTokenRef = useRef<string | undefined>(
671
+ additionalInfo?.loginToken ?? authToken
672
+ );
673
+ const prevPropsLoginTokenRef = useRef<string | undefined>(
674
+ additionalInfo?.loginToken ?? authToken
675
+ );
676
+
613
677
  const [user, setUser] = useState<User | undefined>({
614
678
  avatarURL: typeof userAvatar === 'string' ? userAvatar : undefined,
615
679
  } as User);
680
+
681
+ const resolveLoginToken = useCallback(
682
+ (callAdditionalInfoLoginToken?: string) =>
683
+ resolveLoginTokenValue(
684
+ loginToken,
685
+ userTokenRef.current,
686
+ callAdditionalInfoLoginToken,
687
+ additionalInfo?.loginToken,
688
+ authToken
689
+ ),
690
+ [loginToken, additionalInfo?.loginToken, authToken]
691
+ );
692
+
693
+ // Sync loginToken when props change (including explicit removal from parent)
616
694
  useEffect(() => {
617
- if (
618
- loginToken &&
619
- !user?.userID &&
620
- (showLogin || memori.requireLoginToken)
621
- ) {
622
- client.backend
623
- .pwlGetCurrentUser(loginToken)
624
- .then(({ user, resultCode }) => {
625
- if (user && resultCode === 0) {
626
- setUser(user);
627
- setLocalConfig('loginToken', loginToken);
628
-
629
- if (!birthDate && user.birthDate) {
630
- setBirthDate(user.birthDate);
631
- setLocalConfig('birthDate', user.birthDate);
632
- }
633
- } else {
634
- removeLocalConfig('loginToken');
635
- }
636
- });
695
+ const incomingToken = additionalInfo?.loginToken ?? authToken;
696
+ const prevPropsToken = prevPropsLoginTokenRef.current;
697
+ prevPropsLoginTokenRef.current = incomingToken;
698
+
699
+ if (incomingToken !== prevPropsToken) {
700
+ setLoginToken(incomingToken);
701
+ userTokenRef.current = incomingToken;
702
+ if (!incomingToken) {
703
+ removeLocalConfig('loginToken');
704
+ setUser(undefined);
705
+ }
637
706
  }
638
- }, [loginToken, user?.userID]);
707
+ }, [additionalInfo?.loginToken, authToken]);
708
+
709
+ useEffect(() => {
710
+ if (!loginToken || !(showLogin || memori.requireLoginToken)) {
711
+ return;
712
+ }
713
+
714
+ let cancelled = false;
715
+
716
+ client.backend
717
+ .pwlGetCurrentUser(loginToken)
718
+ .then(({ user: fetchedUser, resultCode }) => {
719
+ if (cancelled) return;
720
+
721
+ if (fetchedUser && resultCode === 0) {
722
+ setUser(fetchedUser);
723
+ setLocalConfig('loginToken', loginToken);
724
+ userTokenRef.current = loginToken;
725
+
726
+ if (!birthDate && fetchedUser.birthDate) {
727
+ setBirthDate(fetchedUser.birthDate);
728
+ setLocalConfig('birthDate', fetchedUser.birthDate);
729
+ }
730
+ } else {
731
+ setLoginToken(undefined);
732
+ userTokenRef.current = undefined;
733
+ setUser(undefined);
734
+ removeLocalConfig('loginToken');
735
+ }
736
+ });
737
+
738
+ return () => {
739
+ cancelled = true;
740
+ };
741
+ }, [loginToken, showLogin, memori.requireLoginToken]);
639
742
  const [showLoginDrawer, setShowLoginDrawer] = useState(false);
640
743
 
641
744
  const [clickedStart, setClickedStart] = useState(false);
642
745
  const [gotErrorInOpening, setGotErrorInOpening] = useState(false);
746
+ const sessionStartingRef = useRef(false);
747
+ const needsCredits = tenant?.billingDelegation;
748
+ const [hasEnoughCredits, setHasEnoughCredits] = useState<boolean>(true);
643
749
 
644
750
  const language =
645
751
  memori.culture?.split('-')?.[0]?.toUpperCase()! ||
@@ -701,7 +807,33 @@ const MemoriWidget = ({
701
807
  const [memoriTyping, setMemoriTyping] = useState<boolean>(false);
702
808
  const [typingText, setTypingText] = useState<string>();
703
809
 
704
- // Layout: prop can be string or object { name, piiDetection } (e.g. from integration customData when PII is enabled).
810
+ type EnterTextRetryParams = {
811
+ text?: string;
812
+ media?: Medium[];
813
+ translate?: boolean;
814
+ translatedText?: string;
815
+ hidden?: boolean;
816
+ typingText?: string;
817
+ useLoaderTextAsMsg?: boolean;
818
+ hasBatchQueued?: boolean;
819
+ expiredSessionID?: string;
820
+ continueFromChatLogID?: string;
821
+ };
822
+
823
+ type PendingEnterText = EnterTextRetryParams & {
824
+ msg?: string;
825
+ waitForResponse?: {
826
+ resolve: (event: NatsDialogResponseEvent) => void;
827
+ reject: (error: Error) => void;
828
+ timeoutId: ReturnType<typeof setTimeout>;
829
+ };
830
+ };
831
+ const pendingEnterTextRef = useRef<Map<string, PendingEnterText>>(new Map());
832
+ const bufferedNatsResponsesRef = useRef<Map<string, NatsDialogResponseEvent>>(
833
+ new Map()
834
+ );
835
+
836
+ // Layout: from prop (string only) or integrationConfig. PII detection is only from integrationConfig (customData.layout as object with piiDetection).
705
837
  const layoutName =
706
838
  typeof layout === 'string'
707
839
  ? layout
@@ -818,7 +950,10 @@ const MemoriWidget = ({
818
950
 
819
951
  if (!additionalInfo?.loginToken && !authToken) {
820
952
  setLoginToken(getLocalConfig<typeof loginToken>('loginToken', undefined));
821
- userToken = getLocalConfig<typeof loginToken>('loginToken', undefined);
953
+ userTokenRef.current = getLocalConfig<typeof loginToken>(
954
+ 'loginToken',
955
+ undefined
956
+ );
822
957
 
823
958
  setBirthDate(getLocalConfig<string | undefined>('birthDate', undefined));
824
959
  }
@@ -893,7 +1028,7 @@ const MemoriWidget = ({
893
1028
  return Object.keys(place).length > 0 ? place : undefined;
894
1029
  }, []);
895
1030
 
896
- /** Place to send with postTextEnteredEvent: real place, nulls when no/declined position, or undefined when position not needed. */
1031
+ /** Place to send with postEnterTextAsync: real place, nulls when no/declined position, or undefined when position not needed. */
897
1032
  const getPlaceSpecForEnterText = useCallback(
898
1033
  (venue: Venue | undefined) => {
899
1034
  if (!memori.needsPosition) return undefined;
@@ -967,6 +1102,7 @@ const MemoriWidget = ({
967
1102
  * @param typingText Optional custom typing indicator text
968
1103
  * @param useLoaderTextAsMsg Whether to use the loader text as the message (default false)
969
1104
  * @param hasBatchQueued Whether there are more messages queued to be sent (default false)
1105
+ * @param skipHistoryPush Skip adding the user message to history (e.g. session-expired retry)
970
1106
  */
971
1107
  const sendMessage = async (
972
1108
  text: string,
@@ -977,7 +1113,8 @@ const MemoriWidget = ({
977
1113
  hidden: boolean = false,
978
1114
  typingText?: string,
979
1115
  useLoaderTextAsMsg = false,
980
- hasBatchQueued = false
1116
+ hasBatchQueued = false,
1117
+ skipHistoryPush = false
981
1118
  ) => {
982
1119
  // Get the session ID from params or global state
983
1120
  const sessionID =
@@ -1044,7 +1181,7 @@ const MemoriWidget = ({
1044
1181
  }
1045
1182
 
1046
1183
  // Add user message to chat history if not hidden
1047
- if (!hidden)
1184
+ if (!hidden && !skipHistoryPush)
1048
1185
  pushMessage({
1049
1186
  text: text,
1050
1187
  translatedText,
@@ -1055,27 +1192,12 @@ const MemoriWidget = ({
1055
1192
  : !!newSessionId,
1056
1193
  });
1057
1194
 
1058
- // Show typing indicator
1059
- setMemoriTyping(true);
1060
- setTypingText(typingText);
1061
-
1195
+ // Show typing indicator after the async enter-text request is accepted (HTTP 200).
1062
1196
  let gotError = false;
1063
1197
 
1064
1198
  try {
1065
- // Add chat reference link to the message if it exists
1066
- // if (chatLogID) {
1067
- // msg =
1068
- // msg +
1069
- // ' \n\n' +
1070
- // '<chat-reference session-id="' +
1071
- // sessionID +
1072
- // '" event-log-id="' +
1073
- // chatLogID +
1074
- // '"></chat-reference>';
1075
- // }
1076
-
1077
1199
  const placeSpec = getPlaceSpecForEnterText(position);
1078
- const { currentState, ...response } = await postTextEnteredEvent({
1200
+ const response = await postEnterTextAsync({
1079
1201
  sessionId: sessionID,
1080
1202
  text: msg,
1081
1203
  ...(memori.needsDateTime && {
@@ -1083,85 +1205,35 @@ const MemoriWidget = ({
1083
1205
  }),
1084
1206
  ...(placeSpec !== undefined && { place: placeSpec }),
1085
1207
  });
1086
- if (response.resultCode === 0 && currentState) {
1087
- setChatLogID(undefined);
1088
- const emission =
1089
- useLoaderTextAsMsg && typingText
1090
- ? typingText
1091
- : currentState.emission ?? currentDialogState?.emission;
1092
-
1093
- if (
1094
- userLang.toLowerCase() !== language.toLowerCase() &&
1095
- emission &&
1096
- isMultilanguageEnabled
1097
- ) {
1098
- currentState.emission = emission;
1099
-
1100
- translateDialogState(currentState, userLang, msg).then(ts => {
1101
- let text = ts.translatedEmission || ts.emission;
1102
- if (text && shouldPlayAudio(text)) {
1103
- handleSpeak(text);
1104
- }
1105
- });
1106
- } else {
1107
- setCurrentDialogState({
1108
- ...currentState,
1109
- emission,
1110
- });
1111
-
1112
- if (emission) {
1113
- pushMessage({
1114
- text: emission,
1115
- emitter: currentState.emitter,
1116
- media: currentState.emittedMedia ?? currentState.media,
1117
- llmUsage: (currentState as any).llmUsage,
1118
- fromUser: false,
1119
- questionAnswered: msg,
1120
- generatedByAI: !!currentState.completion,
1121
- contextVars: currentState.contextVars,
1122
- date: currentState.currentDate,
1123
- placeName: currentState.currentPlaceName,
1124
- placeLatitude: currentState.currentLatitude,
1125
- placeLongitude: currentState.currentLongitude,
1126
- placeUncertaintyKm: currentState.currentUncertaintyKm,
1127
- tag: currentState.currentTag,
1128
- memoryTags: currentState.memoryTags,
1129
- } as any);
1130
- if (emission && shouldPlayAudio(emission)) {
1131
- handleSpeak(emission);
1132
- }
1133
- }
1134
- }
1208
+ const correlationID = readCorrelationID(response);
1209
+ if (response.resultCode === 0 && correlationID) {
1210
+ registerPendingEnterText(correlationID, {
1211
+ msg,
1212
+ text,
1213
+ media,
1214
+ translate,
1215
+ translatedText,
1216
+ hidden,
1217
+ typingText,
1218
+ useLoaderTextAsMsg,
1219
+ hasBatchQueued,
1220
+ });
1221
+ setMemoriTyping(true);
1222
+ setTypingText(typingText);
1223
+ } else if (response.resultCode === 0) {
1224
+ logWidgetError('enter-text missing correlationID', response);
1135
1225
  } else if (response.resultCode === 404) {
1136
- // Handle expired session
1137
- // remove last sent message, will set it as initial
1138
- setHistory(h => [...h.slice(0, h.length - 1)]);
1139
-
1140
- reopenSession(
1141
- true,
1142
- memoriPwd || memori.secretToken,
1143
- memoriTokens,
1144
- undefined,
1145
- undefined,
1146
- {
1147
- LANG: userLang,
1148
- PATHNAME: window.location.pathname,
1149
- ROUTE: window.location.pathname?.split('/')?.pop() || '',
1150
- ...(initialContextVars || {}),
1151
- },
1152
- initialQuestion,
1153
- undefined,
1154
- undefined,
1155
- undefined,
1156
- undefined,
1157
- true // isSessionExpired
1158
- ).then(state => {
1159
- console.info('session timeout');
1160
- if (state?.sessionID) {
1161
- setTimeout(() => {
1162
- sendMessage(text, media, state?.sessionID);
1163
- }, 500);
1164
- }
1226
+ retryAfterExpiredSessionRef.current({
1227
+ text,
1228
+ media,
1229
+ translate,
1230
+ translatedText,
1231
+ hidden,
1232
+ typingText,
1233
+ useLoaderTextAsMsg,
1234
+ hasBatchQueued,
1235
+ expiredSessionID: sessionID,
1236
+ continueFromChatLogID: chatLogID,
1165
1237
  });
1166
1238
  } else if (response.resultCode === 500 && response.resultMessage) {
1167
1239
  setHistory(h => [
@@ -1176,22 +1248,15 @@ const MemoriWidget = ({
1176
1248
  },
1177
1249
  ]);
1178
1250
  } else {
1179
- console.warn('[SEND_MESSAGE]', response);
1180
1251
  return Promise.reject(response);
1181
1252
  }
1182
1253
  } catch (error) {
1183
- console.log('error', error);
1184
- console.error(error);
1185
1254
  gotError = true;
1255
+ logWidgetError('sendMessage failed', error);
1186
1256
 
1187
1257
  setTypingText(undefined);
1188
1258
  setMemoriTyping(false);
1189
1259
  }
1190
-
1191
- if (!hasBatchQueued) {
1192
- setTypingText(undefined);
1193
- setMemoriTyping(false);
1194
- }
1195
1260
  };
1196
1261
 
1197
1262
  /**
@@ -1204,12 +1269,6 @@ const MemoriWidget = ({
1204
1269
  msg?: string,
1205
1270
  avoidPushingMessage: boolean = false
1206
1271
  ) => {
1207
- // console.log('[TRANSLATE] Starting translation with params:', {
1208
- // state,
1209
- // userLang,
1210
- // msg
1211
- // });
1212
-
1213
1272
  const emission = state?.emission ?? currentDialogState?.emission;
1214
1273
 
1215
1274
  let translatedState = { ...state };
@@ -1222,7 +1281,6 @@ const MemoriWidget = ({
1222
1281
  !isMultilanguageEnabled ||
1223
1282
  avoidPushingMessage
1224
1283
  ) {
1225
- // console.log('[TRANSLATE] Skipping translation - using original emission');
1226
1284
  translatedState = { ...state, emission };
1227
1285
  if (emission) {
1228
1286
  translatedMsg = {
@@ -1244,12 +1302,10 @@ const MemoriWidget = ({
1244
1302
  }
1245
1303
  } else {
1246
1304
  try {
1247
- // console.log('[TRANSLATE] Translating emission');
1248
1305
  const t = await getTranslation(emission, userLang, language, baseUrl);
1249
1306
 
1250
1307
  // Handle hints translation if present
1251
1308
  if (state.hints && state.hints.length > 0) {
1252
- // console.log('[TRANSLATE] Translating hints');
1253
1309
  const translatedHints = await Promise.all(
1254
1310
  (state.hints ?? []).map(async hint => {
1255
1311
  const tHint = await getTranslation(
@@ -1281,7 +1337,6 @@ const MemoriWidget = ({
1281
1337
  }
1282
1338
 
1283
1339
  if (t.text.length > 0) {
1284
- // console.log('[TRANSLATE] Creating translated message');
1285
1340
  translatedMsg = {
1286
1341
  text: emission,
1287
1342
  translatedText: t.text,
@@ -1302,7 +1357,6 @@ const MemoriWidget = ({
1302
1357
  };
1303
1358
  }
1304
1359
  } catch (error) {
1305
- console.error('[TRANSLATE] Error during translation:', error);
1306
1360
  translatedState = { ...state, emission };
1307
1361
  translatedMsg = {
1308
1362
  text: emission,
@@ -1323,10 +1377,8 @@ const MemoriWidget = ({
1323
1377
  }
1324
1378
  }
1325
1379
 
1326
- // console.log('[TRANSLATE] Setting translated state and message');
1327
1380
  setCurrentDialogState(translatedState);
1328
1381
  if (!avoidPushingMessage && translatedMsg) {
1329
- // console.log('[TRANSLATE] Pushing translated message', translatedMsg);
1330
1382
  pushMessage(translatedMsg);
1331
1383
  }
1332
1384
 
@@ -1432,7 +1484,6 @@ const MemoriWidget = ({
1432
1484
  executableSnippets?.forEach(s => {
1433
1485
  try {
1434
1486
  setTimeout(() => {
1435
- console.log('snippet', s);
1436
1487
  // eslint-disable-next-line no-new-func
1437
1488
  new Function(s.content ?? '')();
1438
1489
 
@@ -1446,8 +1497,8 @@ const MemoriWidget = ({
1446
1497
  );
1447
1498
  }, 400);
1448
1499
  }, 1000);
1449
- } catch (e) {
1450
- console.warn(e);
1500
+ } catch {
1501
+ // ignore snippet execution errors
1451
1502
  }
1452
1503
  });
1453
1504
  };
@@ -1498,6 +1549,10 @@ const MemoriWidget = ({
1498
1549
  return;
1499
1550
  }
1500
1551
 
1552
+ if (!(await checkCredits({ notify: true }))) {
1553
+ return;
1554
+ }
1555
+
1501
1556
  setLoading(true);
1502
1557
 
1503
1558
  try {
@@ -1519,8 +1574,8 @@ const MemoriWidget = ({
1519
1574
  referral = (() => {
1520
1575
  return window.location.href;
1521
1576
  })();
1522
- } catch (err) {
1523
- console.debug(err);
1577
+ } catch {
1578
+ // ignore referral URL errors
1524
1579
  }
1525
1580
 
1526
1581
  // Initialize session with parameters
@@ -1531,12 +1586,7 @@ const MemoriWidget = ({
1531
1586
  pin: params.pin ?? personification?.pin,
1532
1587
  additionalInfo: {
1533
1588
  ...(params.additionalInfo || additionalInfo || {}),
1534
- loginToken:
1535
- userToken ??
1536
- loginToken ??
1537
- params.additionalInfo?.loginToken ??
1538
- additionalInfo?.loginToken ??
1539
- authToken,
1589
+ loginToken: resolveLoginToken(params.additionalInfo?.loginToken),
1540
1590
  language: (
1541
1591
  userLang ??
1542
1592
  memori.culture?.split('-')?.[0] ??
@@ -1582,7 +1632,7 @@ const MemoriWidget = ({
1582
1632
  setGotErrorInOpening(true);
1583
1633
  }
1584
1634
  // Handle authentication error
1585
- else if (session?.resultCode === 403) {
1635
+ else if (session?.resultCode === 403 && memori.privacyType !== 'PUBLIC') {
1586
1636
  setMemoriPwd(undefined);
1587
1637
  setAuthModalState('password');
1588
1638
  return session;
@@ -1607,11 +1657,10 @@ const MemoriWidget = ({
1607
1657
  duration: 0,
1608
1658
  })
1609
1659
  );
1610
- setGotErrorInOpening(true);
1611
1660
  return session;
1612
1661
  }
1613
1662
  } catch (err) {
1614
- console.error(err);
1663
+ logWidgetError('fetchSession failed', err);
1615
1664
  }
1616
1665
  };
1617
1666
 
@@ -1639,7 +1688,8 @@ const MemoriWidget = ({
1639
1688
  additionalInfoProp?: { [key: string]: string | undefined },
1640
1689
  continueFromChatLogID?: string,
1641
1690
  continueFromSessionID?: string,
1642
- isSessionExpired?: boolean
1691
+ isSessionExpired?: boolean,
1692
+ suppressHistoryUpdate?: boolean
1643
1693
  ) => {
1644
1694
  // Set loading state while reopening session
1645
1695
  setLoading(true);
@@ -1650,12 +1700,10 @@ const MemoriWidget = ({
1650
1700
  undefined
1651
1701
  );
1652
1702
  let userBirthDate = birthDate ?? storageBirthDate;
1653
- // console.log('[REOPEN_SESSION] Using birth date:', userBirthDate);
1654
1703
 
1655
1704
  try {
1656
1705
  // Show age verification if required and birth date not provided
1657
1706
  if (!userBirthDate && !!minAge) {
1658
- // console.log('[REOPEN_SESSION] Age verification required, showing modal');
1659
1707
  setShowAgeVerification(true);
1660
1708
  return;
1661
1709
  }
@@ -1669,24 +1717,26 @@ const MemoriWidget = ({
1669
1717
  !recoveryTokens &&
1670
1718
  !memoriTokens
1671
1719
  ) {
1672
- // console.log('[REOPEN_SESSION] Authentication required, showing modal');
1673
1720
  setAuthModalState('password');
1674
1721
  return;
1675
1722
  }
1676
1723
 
1724
+ if (!(await checkCredits({ notify: true }))) {
1725
+ setLoading(false);
1726
+ return null;
1727
+ }
1728
+
1677
1729
  // Get current URL as referral
1678
1730
  let referral;
1679
1731
  try {
1680
1732
  referral = (() => {
1681
1733
  return window.location.href;
1682
1734
  })();
1683
- // console.log('[REOPEN_SESSION] Got referral:', referral);
1684
- } catch (err) {
1685
- console.debug('[REOPEN_SESSION] Error getting referral:', err);
1735
+ } catch {
1736
+ // ignore referral URL errors
1686
1737
  }
1687
1738
 
1688
1739
  // Initialize session with provided parameters
1689
- // console.log('[REOPEN_SESSION] Initializing session...');
1690
1740
  const { sessionID, currentState, ...response } = await initSession({
1691
1741
  memoriID: memori.engineMemoriID ?? '',
1692
1742
  password: password || memoriPwd || memori.secretToken,
@@ -1705,12 +1755,7 @@ const MemoriWidget = ({
1705
1755
  birthDate: userBirthDate,
1706
1756
  additionalInfo: {
1707
1757
  ...(additionalInfoProp || additionalInfo || {}),
1708
- loginToken:
1709
- userToken ??
1710
- loginToken ??
1711
- additionalInfoProp?.loginToken ??
1712
- additionalInfo?.loginToken ??
1713
- authToken,
1758
+ loginToken: resolveLoginToken(additionalInfoProp?.loginToken),
1714
1759
  language: (
1715
1760
  userLang ??
1716
1761
  memori.culture?.split('-')?.[0] ??
@@ -1723,30 +1768,36 @@ const MemoriWidget = ({
1723
1768
 
1724
1769
  // Handle successful session initialization
1725
1770
  if (sessionID && currentState && response.resultCode === 0) {
1726
- console.log(
1727
- '[REOPEN_SESSION] Session initialized successfully:',
1728
- sessionID
1729
- );
1730
1771
  setSessionId(sessionID);
1731
1772
 
1732
1773
  // Update dialog state and history if requested
1733
1774
  if (updateDialogState) {
1734
- // console.log('[REOPEN_SESSION] Updating dialog state');
1735
1775
  setCurrentDialogState(currentState);
1736
1776
 
1737
- if (currentState.emission) {
1738
- console.log(
1739
- '[REOPEN_SESSION] Processing emission:',
1740
- currentState.emission
1741
- );
1777
+ const sessionExpiredStatus =
1778
+ isSessionExpired && history.length > 1
1779
+ ? t('sessionExpiredReopening')
1780
+ : null;
1781
+
1782
+ if (sessionExpiredStatus && suppressHistoryUpdate) {
1783
+ pushMessage({
1784
+ text: '',
1785
+ emitter: 'system',
1786
+ fromUser: false,
1787
+ initial: sessionExpiredStatus as any,
1788
+ contextVars: {},
1789
+ date: new Date().toISOString(),
1790
+ });
1791
+ }
1792
+
1793
+ if (currentState.emission && !suppressHistoryUpdate) {
1742
1794
  // Determine initial status message based on context
1743
1795
  // Show status message only if session expired and there's existing history
1744
- const initialStatus =
1745
- isSessionExpired && history.length > 1
1746
- ? 'Session Expired, reopening session'
1747
- : history.length <= 1
1748
- ? true
1749
- : undefined;
1796
+ const initialStatus = sessionExpiredStatus
1797
+ ? sessionExpiredStatus
1798
+ : history.length <= 1
1799
+ ? true
1800
+ : undefined;
1750
1801
 
1751
1802
  // Set initial message or append to existing history
1752
1803
  history.length <= 1
@@ -1809,8 +1860,10 @@ const MemoriWidget = ({
1809
1860
  setGotErrorInOpening(true);
1810
1861
  }
1811
1862
  // Handle authentication error
1812
- else if (response?.resultCode === 403) {
1813
- console.error('[REOPEN_SESSION] Authentication error');
1863
+ else if (
1864
+ response?.resultCode === 403 &&
1865
+ memori.privacyType !== 'PUBLIC'
1866
+ ) {
1814
1867
  setMemoriPwd(undefined);
1815
1868
  setAuthModalState('password');
1816
1869
  }
@@ -1826,7 +1879,7 @@ const MemoriWidget = ({
1826
1879
  setGotErrorInOpening(true);
1827
1880
  }
1828
1881
  } catch (err) {
1829
- console.error('[REOPEN_SESSION] Caught error:', err);
1882
+ logWidgetError('reopenSession failed', err);
1830
1883
  }
1831
1884
  // Reset loading state
1832
1885
  setLoading(false);
@@ -1834,6 +1887,101 @@ const MemoriWidget = ({
1834
1887
  return null;
1835
1888
  };
1836
1889
 
1890
+ const retryAfterExpiredSessionRef = useRef<
1891
+ (params: EnterTextRetryParams) => ReturnType<typeof reopenSession>
1892
+ >(() => Promise.resolve(null));
1893
+
1894
+ retryAfterExpiredSessionRef.current = (params: EnterTextRetryParams) => {
1895
+ const {
1896
+ text,
1897
+ media,
1898
+ translate = true,
1899
+ translatedText,
1900
+ hidden = false,
1901
+ typingText,
1902
+ useLoaderTextAsMsg = false,
1903
+ hasBatchQueued = false,
1904
+ expiredSessionID,
1905
+ continueFromChatLogID: continueFromChatLogIDParam,
1906
+ } = params;
1907
+
1908
+ const continueFromSessionID = expiredSessionID ?? sessionId;
1909
+ const continueFromChatLogID = continueFromChatLogIDParam ?? chatLogID;
1910
+
1911
+ const reopenAfterExpiry = () =>
1912
+ reopenSession(
1913
+ true,
1914
+ memoriPwd || memori.secretToken,
1915
+ memoriTokens,
1916
+ undefined,
1917
+ undefined,
1918
+ {
1919
+ LANG: userLang,
1920
+ PATHNAME: window.location.pathname,
1921
+ ROUTE: window.location.pathname?.split('/')?.pop() || '',
1922
+ ...(initialContextVars || {}),
1923
+ },
1924
+ initialQuestion,
1925
+ undefined,
1926
+ undefined,
1927
+ continueFromChatLogID,
1928
+ continueFromSessionID,
1929
+ true,
1930
+ true
1931
+ );
1932
+
1933
+ const scheduleRetry = (newSessionID: string) => {
1934
+ setTimeout(() => {
1935
+ sendMessage(
1936
+ text!,
1937
+ media,
1938
+ newSessionID,
1939
+ translate,
1940
+ translatedText,
1941
+ hidden,
1942
+ typingText,
1943
+ useLoaderTextAsMsg,
1944
+ hasBatchQueued,
1945
+ true
1946
+ );
1947
+ }, 500);
1948
+ };
1949
+
1950
+ const handleReopenFailure = (
1951
+ state: Awaited<ReturnType<typeof reopenSession>>
1952
+ ) => {
1953
+ setMemoriTyping(false);
1954
+ setTypingText(undefined);
1955
+ // `null` = explicit failure; `undefined` = auth/age modal opened (message kept in history)
1956
+ if (state === null && text && !hidden) {
1957
+ add(
1958
+ createAlertOptions({
1959
+ description: t('errors.SESSION_EXPIRED'),
1960
+ severity: 'error',
1961
+ })
1962
+ );
1963
+ }
1964
+ };
1965
+
1966
+ if (!text) {
1967
+ return reopenAfterExpiry().then(state => {
1968
+ if (!state?.sessionID) {
1969
+ handleReopenFailure(state);
1970
+ }
1971
+ return state;
1972
+ });
1973
+ }
1974
+
1975
+ return reopenAfterExpiry().then(state => {
1976
+ if (state?.sessionID) {
1977
+ scheduleRetry(state.sessionID);
1978
+ } else {
1979
+ handleReopenFailure(state);
1980
+ }
1981
+ return state;
1982
+ });
1983
+ };
1984
+
1837
1985
  const changeTag = async (
1838
1986
  memoriId: string,
1839
1987
  sessionId: string,
@@ -1841,7 +1989,6 @@ const MemoriWidget = ({
1841
1989
  pin?: string
1842
1990
  ) => {
1843
1991
  if (!memoriId || !sessionId) {
1844
- console.error('CHANGETAG/Session not found');
1845
1992
  return Promise.reject('Session not found');
1846
1993
  }
1847
1994
 
@@ -1881,7 +2028,6 @@ const MemoriWidget = ({
1881
2028
  };
1882
2029
  }
1883
2030
  } else if ([400, 401, 403, 404, 500].includes(resultCode)) {
1884
- console.warn('[APPCONTEXT/CHANGETAG]', resultCode);
1885
2031
  let storageBirthDate = getLocalConfig<string | undefined>(
1886
2032
  'birthDate',
1887
2033
  undefined
@@ -1892,8 +2038,8 @@ const MemoriWidget = ({
1892
2038
  referral = (() => {
1893
2039
  return window.location.href;
1894
2040
  })();
1895
- } catch (err) {
1896
- console.debug(err);
2041
+ } catch {
2042
+ // ignore referral URL errors
1897
2043
  }
1898
2044
 
1899
2045
  fetchSession({
@@ -1911,11 +2057,7 @@ const MemoriWidget = ({
1911
2057
  birthDate: birthDate || storageBirthDate || undefined,
1912
2058
  additionalInfo: {
1913
2059
  ...(additionalInfo || {}),
1914
- loginToken:
1915
- userToken ??
1916
- loginToken ??
1917
- additionalInfo?.loginToken ??
1918
- authToken,
2060
+ loginToken: resolveLoginToken(),
1919
2061
  language: (
1920
2062
  userLang ??
1921
2063
  memori.culture?.split('-')?.[0] ??
@@ -1935,7 +2077,6 @@ const MemoriWidget = ({
1935
2077
  }
1936
2078
  } catch (_e) {
1937
2079
  let err = _e as Error;
1938
- console.warn('[APPCONTEXT/CHANGETAG]', err);
1939
2080
  return Promise.reject(err);
1940
2081
  }
1941
2082
 
@@ -1962,6 +2103,7 @@ const MemoriWidget = ({
1962
2103
  return () => {
1963
2104
  setHasUserActivatedSpeak(false);
1964
2105
  setClickedStart(false);
2106
+ sessionStartingRef.current = false;
1965
2107
  clearInteractionTimeout();
1966
2108
  timeoutRef.current = undefined;
1967
2109
  };
@@ -1974,8 +2116,6 @@ const MemoriWidget = ({
1974
2116
  const [requestedListening, setRequestedListening] = useState(false);
1975
2117
  const startListeningRef = useRef<(() => Promise<void>) | null>(null);
1976
2118
 
1977
- // console.log('tenantID', tenantID);
1978
-
1979
2119
  // Define TTS configuration
1980
2120
  const ttsConfig = useMemo(
1981
2121
  () => ({
@@ -2030,7 +2170,6 @@ const MemoriWidget = ({
2030
2170
  'muteSpeaker',
2031
2171
  !defaultEnableAudio
2032
2172
  );
2033
- console.log('[MemoriWidget] shouldPlayAudio', currentSpeakerMuted);
2034
2173
  return (
2035
2174
  text &&
2036
2175
  text.trim() &&
@@ -2042,7 +2181,6 @@ const MemoriWidget = ({
2042
2181
 
2043
2182
  // Create a single, centralized function to process and send messages
2044
2183
  const processSpeechAndSendMessage = (text: string) => {
2045
- // console.log('processSpeechAndSendMessage', text);
2046
2184
  // Skip if already processing or no text
2047
2185
  if (!text || text.trim().length === 0) {
2048
2186
  return;
@@ -2051,17 +2189,15 @@ const MemoriWidget = ({
2051
2189
  try {
2052
2190
  // Process the text
2053
2191
  const message = stripDuplicates(text);
2054
- console.debug('Processing speech message:', message);
2055
2192
 
2056
2193
  if (message.length > 0) {
2057
2194
  setUserMessage('');
2058
2195
 
2059
2196
  // Send the message
2060
- console.debug('Sending message:', message);
2061
2197
  sendMessage(message);
2062
2198
  }
2063
- } catch (error) {
2064
- console.error('Error in processSpeechAndSendMessage:', error);
2199
+ } catch {
2200
+ // ignore speech processing errors
2065
2201
  }
2066
2202
  };
2067
2203
 
@@ -2141,8 +2277,7 @@ const MemoriWidget = ({
2141
2277
  }
2142
2278
 
2143
2279
  return translatedState;
2144
- } catch (error) {
2145
- console.error('Error in translateAndSpeak:', error);
2280
+ } catch {
2146
2281
  // Still update activation state even if there's an error
2147
2282
  if (!hasUserActivatedSpeak) {
2148
2283
  setHasUserActivatedSpeak(true);
@@ -2159,6 +2294,277 @@ const MemoriWidget = ({
2159
2294
  ]
2160
2295
  );
2161
2296
 
2297
+ const processEnterTextDialogResponse = useCallback(
2298
+ (event: NatsDialogResponseEvent, pending: PendingEnterText) => {
2299
+ const {
2300
+ msg,
2301
+ typingText: pendingTypingText,
2302
+ useLoaderTextAsMsg,
2303
+ } = pending;
2304
+ const currentState = event.currentState;
2305
+
2306
+ if (event.resultCode !== 0 || !currentState) {
2307
+ if (isSessionExpiredNatsResponse(event) && pending.text) {
2308
+ setMemoriTyping(false);
2309
+ setTypingText(undefined);
2310
+ retryAfterExpiredSessionRef.current({
2311
+ text: pending.text,
2312
+ media: pending.media,
2313
+ translate: pending.translate,
2314
+ translatedText: pending.translatedText,
2315
+ hidden: pending.hidden,
2316
+ typingText: pending.typingText,
2317
+ useLoaderTextAsMsg: pending.useLoaderTextAsMsg,
2318
+ hasBatchQueued: pending.hasBatchQueued,
2319
+ expiredSessionID: sessionId,
2320
+ continueFromChatLogID: chatLogID,
2321
+ });
2322
+ return;
2323
+ }
2324
+
2325
+ if (event.resultCode === 500 && event.resultMessage) {
2326
+ setHistory(h => [
2327
+ ...h,
2328
+ {
2329
+ text: 'Error: ' + event.resultMessage,
2330
+ emitter: 'system',
2331
+ fromUser: false,
2332
+ initial: false,
2333
+ contextVars: {},
2334
+ date: new Date().toISOString(),
2335
+ },
2336
+ ]);
2337
+ }
2338
+ return;
2339
+ }
2340
+
2341
+ if (!msg) {
2342
+ return;
2343
+ }
2344
+
2345
+ setChatLogID(undefined);
2346
+ const emission =
2347
+ useLoaderTextAsMsg && pendingTypingText
2348
+ ? pendingTypingText
2349
+ : currentState.emission ?? currentDialogState?.emission;
2350
+
2351
+ if (
2352
+ userLang.toLowerCase() !== language.toLowerCase() &&
2353
+ emission &&
2354
+ isMultilanguageEnabled
2355
+ ) {
2356
+ currentState.emission = emission;
2357
+
2358
+ translateDialogState(currentState, userLang, msg).then(ts => {
2359
+ const text = ts.translatedEmission || ts.emission;
2360
+ if (text && shouldPlayAudio(text)) {
2361
+ handleSpeak(text);
2362
+ }
2363
+ });
2364
+ } else {
2365
+ setCurrentDialogState({
2366
+ ...currentState,
2367
+ emission,
2368
+ });
2369
+
2370
+ if (emission) {
2371
+ pushMessage({
2372
+ text: emission,
2373
+ emitter: currentState.emitter,
2374
+ media: currentState.emittedMedia ?? currentState.media,
2375
+ llmUsage: (currentState as any).llmUsage,
2376
+ fromUser: false,
2377
+ questionAnswered: msg,
2378
+ generatedByAI: !!currentState.completion,
2379
+ contextVars: currentState.contextVars,
2380
+ date: currentState.currentDate,
2381
+ placeName: currentState.currentPlaceName,
2382
+ placeLatitude: currentState.currentLatitude,
2383
+ placeLongitude: currentState.currentLongitude,
2384
+ placeUncertaintyKm: currentState.currentUncertaintyKm,
2385
+ tag: currentState.currentTag,
2386
+ memoryTags: currentState.memoryTags,
2387
+ } as any);
2388
+ if (emission && shouldPlayAudio(emission)) {
2389
+ handleSpeak(emission);
2390
+ }
2391
+ }
2392
+ }
2393
+ },
2394
+ [
2395
+ userLang,
2396
+ language,
2397
+ isMultilanguageEnabled,
2398
+ currentDialogState?.emission,
2399
+ translateDialogState,
2400
+ handleSpeak,
2401
+ shouldPlayAudio,
2402
+ ]
2403
+ );
2404
+
2405
+ const clearEnterTextPending = useCallback(
2406
+ (correlationID: string, pending: PendingEnterText) => {
2407
+ if (pending.waitForResponse?.timeoutId) {
2408
+ clearTimeout(pending.waitForResponse.timeoutId);
2409
+ }
2410
+ pendingEnterTextRef.current.delete(correlationID);
2411
+ },
2412
+ []
2413
+ );
2414
+
2415
+ const deliverEnterTextNatsError = useCallback(
2416
+ (event: NatsErrorEvent) => {
2417
+ const correlationID = event.correlationID;
2418
+ let pending: PendingEnterText | undefined;
2419
+
2420
+ if (correlationID) {
2421
+ pending = pendingEnterTextRef.current.get(correlationID);
2422
+ if (pending) {
2423
+ clearEnterTextPending(correlationID, pending);
2424
+ pending.waitForResponse?.reject(
2425
+ new Error(
2426
+ event.errorMessage ?? String(event.errorCode ?? 'NATS error')
2427
+ )
2428
+ );
2429
+ }
2430
+ }
2431
+
2432
+ if (isSessionExpiredNatsError(event) && pending?.text) {
2433
+ setMemoriTyping(false);
2434
+ setTypingText(undefined);
2435
+ retryAfterExpiredSessionRef.current({
2436
+ text: pending.text,
2437
+ media: pending.media,
2438
+ translate: pending.translate,
2439
+ translatedText: pending.translatedText,
2440
+ hidden: pending.hidden,
2441
+ typingText: pending.typingText,
2442
+ useLoaderTextAsMsg: pending.useLoaderTextAsMsg,
2443
+ hasBatchQueued: pending.hasBatchQueued,
2444
+ expiredSessionID: sessionId,
2445
+ continueFromChatLogID: chatLogID,
2446
+ });
2447
+ return;
2448
+ }
2449
+
2450
+ const errorText = event.errorMessage
2451
+ ? `Error: ${event.errorMessage}`
2452
+ : event.errorCode
2453
+ ? `Error: ${event.errorCode}`
2454
+ : 'Error: An unexpected error occurred';
2455
+
2456
+ pushMessage({
2457
+ text: errorText,
2458
+ emitter: 'system',
2459
+ fromUser: false,
2460
+ initial: false,
2461
+ contextVars: {},
2462
+ date: new Date().toISOString(),
2463
+ });
2464
+
2465
+ setMemoriTyping(false);
2466
+ setTypingText(undefined);
2467
+ },
2468
+ [clearEnterTextPending]
2469
+ );
2470
+
2471
+ const deliverEnterTextNatsResponse = useCallback(
2472
+ (correlationID: string, event: NatsDialogResponseEvent) => {
2473
+ const pending = pendingEnterTextRef.current.get(correlationID);
2474
+ if (!pending) {
2475
+ bufferedNatsResponsesRef.current.set(correlationID, event);
2476
+ return;
2477
+ }
2478
+
2479
+ clearEnterTextPending(correlationID, pending);
2480
+
2481
+ if (pending.waitForResponse) {
2482
+ pending.waitForResponse.resolve(event);
2483
+ setMemoriTyping(false);
2484
+ setTypingText(undefined);
2485
+ return;
2486
+ }
2487
+
2488
+ processEnterTextDialogResponse(event, pending);
2489
+
2490
+ if (!pending.hasBatchQueued) {
2491
+ setMemoriTyping(false);
2492
+ setTypingText(undefined);
2493
+ }
2494
+ },
2495
+ [processEnterTextDialogResponse, clearEnterTextPending]
2496
+ );
2497
+
2498
+ const registerPendingEnterText = useCallback(
2499
+ (correlationID: string, pending: PendingEnterText) => {
2500
+ const buffered = bufferedNatsResponsesRef.current.get(correlationID);
2501
+ if (buffered) {
2502
+ bufferedNatsResponsesRef.current.delete(correlationID);
2503
+ pendingEnterTextRef.current.set(correlationID, pending);
2504
+ deliverEnterTextNatsResponse(correlationID, buffered);
2505
+ return;
2506
+ }
2507
+
2508
+ pendingEnterTextRef.current.set(correlationID, pending);
2509
+ },
2510
+ [deliverEnterTextNatsResponse]
2511
+ );
2512
+
2513
+ const waitForEnterTextNatsResponse = useCallback(
2514
+ (correlationID: string, timeoutMs = 120000) =>
2515
+ new Promise<NatsDialogResponseEvent>((resolve, reject) => {
2516
+ const timeoutId = setTimeout(() => {
2517
+ const current = pendingEnterTextRef.current.get(correlationID);
2518
+ if (current) {
2519
+ clearEnterTextPending(correlationID, current);
2520
+ }
2521
+ logWidgetError('NATS timeout', { correlationID, timeoutMs });
2522
+ reject(new Error('NATS enter-text response timeout'));
2523
+ }, timeoutMs);
2524
+
2525
+ registerPendingEnterText(correlationID, {
2526
+ waitForResponse: {
2527
+ resolve: event => {
2528
+ clearTimeout(timeoutId);
2529
+ resolve(event);
2530
+ },
2531
+ reject: error => {
2532
+ clearTimeout(timeoutId);
2533
+ reject(error);
2534
+ },
2535
+ timeoutId,
2536
+ },
2537
+ });
2538
+ }),
2539
+ [registerPendingEnterText, clearEnterTextPending]
2540
+ );
2541
+
2542
+ // NATS subscription: receives progress updates and the async enter-text response.
2543
+ useNats({
2544
+ baseUrl,
2545
+ sessionId,
2546
+ onProgress: useCallback((event: NatsProgressEvent) => {
2547
+ if (event.message) {
2548
+ setTypingText(event.message);
2549
+ }
2550
+ }, []),
2551
+ onDialogResponse: useCallback(
2552
+ (event: NatsDialogResponseEvent) => {
2553
+ const correlationID = event.correlationID;
2554
+ if (!correlationID) {
2555
+ logWidgetError('NATS dialog response missing correlationID', event);
2556
+ setMemoriTyping(false);
2557
+ setTypingText(undefined);
2558
+ return;
2559
+ }
2560
+
2561
+ deliverEnterTextNatsResponse(correlationID, event);
2562
+ },
2563
+ [deliverEnterTextNatsResponse]
2564
+ ),
2565
+ onError: deliverEnterTextNatsError,
2566
+ });
2567
+
2162
2568
  const focusChatInput = () => {
2163
2569
  let textarea = document.querySelector(
2164
2570
  '#chat-fieldset textarea'
@@ -2187,8 +2593,8 @@ const MemoriWidget = ({
2187
2593
  setClickedStart(false);
2188
2594
  timeoutRef.current = undefined;
2189
2595
  ttsStop();
2190
- } catch (e) {
2191
- // console.log('Error: resetUIEffects', e);
2596
+ } catch {
2597
+ // ignore reset errors
2192
2598
  }
2193
2599
  };
2194
2600
  useEffect(() => {
@@ -2245,9 +2651,6 @@ const MemoriWidget = ({
2245
2651
  >();
2246
2652
 
2247
2653
  const globalBackground = integrationConfig?.globalBackground;
2248
- const globalBackgroundUrl = globalBackground
2249
- ? `url(${globalBackground})`
2250
- : null;
2251
2654
 
2252
2655
  const integrationProperties = (
2253
2656
  integration ? getChatStyles(integrationConfig) : {}
@@ -2290,7 +2693,7 @@ const MemoriWidget = ({
2290
2693
  }
2291
2694
  if (integrationConfig?.blurBackground) {
2292
2695
  integrationStylesheetParts.push(
2293
- '.memori-widget .memori--global-background { filter: blur(5px); }'
2696
+ '.memori-widget .memori-chat--history--has-global-background::before { filter: blur(5px); }'
2294
2697
  );
2295
2698
  }
2296
2699
  const integrationStylesheet = `@layer integration {
@@ -2444,12 +2847,6 @@ const MemoriWidget = ({
2444
2847
  chatLog?: ChatLog,
2445
2848
  targetSessionID?: string
2446
2849
  ) => {
2447
- // console.log('[onClickStart] Starting with params:', {
2448
- // session,
2449
- // initialSessionExpired,
2450
- // chatLog
2451
- // });
2452
-
2453
2850
  const sessionID = chatLog ? undefined : session?.sessionID || sessionId;
2454
2851
  const dialogState = chatLog
2455
2852
  ? undefined
@@ -2478,10 +2875,17 @@ const MemoriWidget = ({
2478
2875
  return;
2479
2876
  }
2480
2877
 
2878
+ if (!(await checkCredits({ notify: true }))) {
2879
+ setClickedStart(false);
2880
+ setLoading(false);
2881
+ return;
2882
+ }
2883
+
2481
2884
  // Handle age verification
2482
2885
  if (!sessionID && !!minAge && !birth) {
2483
2886
  setShowAgeVerification(true);
2484
2887
  setClickedStart(false);
2888
+ return;
2485
2889
  }
2486
2890
  // Handle authentication
2487
2891
  else if (
@@ -2498,117 +2902,125 @@ const MemoriWidget = ({
2498
2902
  }
2499
2903
  // Create new session if needed
2500
2904
  else if (!sessionID || initialSessionExpired) {
2501
- setClickedStart(false);
2502
2905
  setGotErrorInOpening(false);
2503
- const session = await fetchSession({
2504
- memoriID: memori.engineMemoriID!,
2505
- password: secret || memoriPwd || memori.secretToken,
2506
- tag: personification?.tag,
2507
- pin: personification?.pin,
2508
- continueFromChatLogID: chatLog?.chatLogID,
2509
- initialContextVars: {
2510
- LANG: userLang,
2511
- PATHNAME: window.location.pathname?.toUpperCase(),
2512
- ROUTE:
2513
- window.location.pathname?.split('/')?.pop()?.toUpperCase() || '',
2514
- ...((!chatLog
2515
- ? initialContextVars
2516
- : chatLog.lines[chatLog.lines.length - 1].contextVars) || {}),
2517
- },
2518
- initialQuestion: chatLog ? undefined : initialQuestion,
2519
- birthDate: birth,
2520
- additionalInfo: {
2521
- ...(additionalInfo || {}),
2522
- loginToken:
2523
- userToken ??
2524
- loginToken ??
2525
- additionalInfo?.loginToken ??
2526
- authToken,
2527
- language: (
2528
- userLang ??
2529
- memori.culture?.split('-')?.[0] ??
2530
- 'IT'
2531
- ).toLowerCase(),
2532
- timeZoneOffset: new Date().getTimezoneOffset().toString(),
2533
- },
2534
- });
2906
+ if (sessionStartingRef.current) {
2907
+ return;
2908
+ }
2909
+ sessionStartingRef.current = true;
2910
+ try {
2911
+ const session = await fetchSession({
2912
+ memoriID: memori.engineMemoriID!,
2913
+ password: secret || memoriPwd || memori.secretToken,
2914
+ tag: personification?.tag,
2915
+ pin: personification?.pin,
2916
+ continueFromChatLogID: chatLog?.chatLogID,
2917
+ initialContextVars: {
2918
+ LANG: userLang,
2919
+ PATHNAME: window.location.pathname?.toUpperCase(),
2920
+ ROUTE:
2921
+ window.location.pathname?.split('/')?.pop()?.toUpperCase() ||
2922
+ '',
2923
+ ...((!chatLog
2924
+ ? initialContextVars
2925
+ : chatLog.lines[chatLog.lines.length - 1].contextVars) || {}),
2926
+ },
2927
+ initialQuestion: chatLog ? undefined : initialQuestion,
2928
+ birthDate: birth,
2929
+ additionalInfo: {
2930
+ ...(additionalInfo || {}),
2931
+ loginToken: resolveLoginToken(),
2932
+ language: (
2933
+ userLang ??
2934
+ memori.culture?.split('-')?.[0] ??
2935
+ 'IT'
2936
+ ).toLowerCase(),
2937
+ timeZoneOffset: new Date().getTimezoneOffset().toString(),
2938
+ },
2939
+ });
2535
2940
 
2536
- if (session?.dialogState) {
2537
- // reset history
2538
- if (!chatLog) {
2539
- setHistory([]);
2941
+ if (session?.dialogState) {
2942
+ // reset history
2943
+ if (!chatLog) {
2944
+ setHistory([]);
2540
2945
 
2541
- // Use translateAndSpeak which already handles the speaking
2542
- await translateAndSpeak(session.dialogState, userLang);
2543
- // No need for additional handleSpeak call since translateAndSpeak already handles it
2544
- setHasUserActivatedSpeak(true);
2545
- } else {
2546
- const messages = chatLog.lines.map(
2547
- (l, i) =>
2548
- ({
2549
- text: l.text,
2550
- media: l.media
2551
- ?.filter(m => allowedMediaTypes.includes(m.mimeType))
2552
- ?.map(m => ({
2553
- mediumID: `${i}-${m.mimeType}`,
2554
- ...m,
2555
- })),
2556
- fromUser: l.inbound,
2557
- llmUsage: (l as any).llmUsage,
2558
- timestamp: l.timestamp,
2559
- emitter: l.emitter,
2560
- initial: i === 0,
2561
- } as Message)
2562
- );
2946
+ // Use translateAndSpeak which already handles the speaking
2947
+ await translateAndSpeak(session.dialogState, userLang);
2948
+ // No need for additional handleSpeak call since translateAndSpeak already handles it
2949
+ setHasUserActivatedSpeak(true);
2950
+ setClickedStart(false);
2951
+ } else {
2952
+ const messages = chatLog.lines.map(
2953
+ (l, i) =>
2954
+ ({
2955
+ text: l.text,
2956
+ media: l.media
2957
+ ?.filter(m => allowedMediaTypes.includes(m.mimeType))
2958
+ ?.map(m => ({
2959
+ mediumID: `${i}-${m.mimeType}`,
2960
+ ...m,
2961
+ })),
2962
+ fromUser: l.inbound,
2963
+ llmUsage: (l as any).llmUsage,
2964
+ timestamp: l.timestamp,
2965
+ emitter: l.emitter,
2966
+ initial: i === 0,
2967
+ } as Message)
2968
+ );
2563
2969
 
2564
- // we dont remove the last one as it is the current state
2565
- translatedMessages = messages ?? [];
2566
- if (
2567
- language.toUpperCase() !== userLang.toUpperCase() &&
2568
- isMultilanguageEnabled
2569
- ) {
2570
- try {
2571
- translatedMessages = await Promise.all(
2572
- messages.map(async m => {
2573
- // If original text is present, the message is already translated
2574
- if ('originalText' in m && m.originalText) {
2575
- return m;
2576
- }
2577
- // Otherwise translate the message
2578
- return {
2579
- ...m,
2580
- originalText: m.text,
2581
- text: (
2582
- await getTranslation(
2583
- m.text,
2584
- userLang,
2585
- language,
2586
- baseUrl
2587
- )
2588
- ).text,
2589
- };
2590
- })
2591
- );
2592
- } catch (e) {
2593
- console.error('[onClickStart] Error translating messages:', e);
2970
+ // we dont remove the last one as it is the current state
2971
+ translatedMessages = messages ?? [];
2972
+ if (
2973
+ language.toUpperCase() !== userLang.toUpperCase() &&
2974
+ isMultilanguageEnabled
2975
+ ) {
2976
+ try {
2977
+ translatedMessages = await Promise.all(
2978
+ messages.map(async m => {
2979
+ // If original text is present, the message is already translated
2980
+ if ('originalText' in m && m.originalText) {
2981
+ return m;
2982
+ }
2983
+ // Otherwise translate the message
2984
+ return {
2985
+ ...m,
2986
+ originalText: m.text,
2987
+ text: (
2988
+ await getTranslation(
2989
+ m.text,
2990
+ userLang,
2991
+ language,
2992
+ baseUrl
2993
+ )
2994
+ ).text,
2995
+ };
2996
+ })
2997
+ );
2998
+ } catch {
2999
+ // ignore translation errors
3000
+ }
2594
3001
  }
2595
- }
2596
3002
 
2597
- setHistory(translatedMessages);
3003
+ setHistory(translatedMessages);
2598
3004
 
2599
- translateDialogState(
2600
- session.dialogState,
2601
- userLang,
2602
- undefined,
2603
- true
2604
- ).finally(() => {
2605
- setHasUserActivatedSpeak(true);
2606
- });
3005
+ translateDialogState(
3006
+ session.dialogState,
3007
+ userLang,
3008
+ undefined,
3009
+ true
3010
+ ).finally(() => {
3011
+ setHasUserActivatedSpeak(true);
3012
+ setClickedStart(false);
3013
+ });
3014
+ }
3015
+ } else if (session?.resultCode === 0) {
3016
+ sessionStartingRef.current = false;
3017
+ await onClickStart((session as any) || undefined);
3018
+ } else {
3019
+ setLoading(false);
3020
+ setClickedStart(false);
2607
3021
  }
2608
- } else if (session?.resultCode === 0) {
2609
- await onClickStart((session as any) || undefined);
2610
- } else {
2611
- setLoading(false);
3022
+ } finally {
3023
+ sessionStartingRef.current = false;
2612
3024
  }
2613
3025
 
2614
3026
  return;
@@ -2621,9 +3033,7 @@ const MemoriWidget = ({
2621
3033
 
2622
3034
  if (response.resultCode !== 0 || !currentState) {
2623
3035
  const { chatLogs } = await getSessionChatLogs(sessionID!, sessionID!);
2624
- setGotErrorInOpening(true);
2625
3036
  setSessionId(undefined);
2626
- setClickedStart(false);
2627
3037
  await onClickStart(undefined, true, chatLogs?.[0]);
2628
3038
  return;
2629
3039
  }
@@ -2649,11 +3059,11 @@ const MemoriWidget = ({
2649
3059
 
2650
3060
  if (session && session.resultCode === 0) {
2651
3061
  await translateAndSpeak(session.currentState, userLang);
3062
+ setClickedStart(false);
2652
3063
  } else {
2653
3064
  throw new Error('No session');
2654
3065
  }
2655
- } catch (e) {
2656
- console.error('[onClickStart] Error changing tag:', e);
3066
+ } catch {
2657
3067
  reopenSession(
2658
3068
  true,
2659
3069
  memori?.secretToken,
@@ -2672,6 +3082,7 @@ const MemoriWidget = ({
2672
3082
  birth
2673
3083
  ).then(() => {
2674
3084
  setHasUserActivatedSpeak(true);
3085
+ setClickedStart(false);
2675
3086
  });
2676
3087
  }
2677
3088
  }
@@ -2694,6 +3105,7 @@ const MemoriWidget = ({
2694
3105
 
2695
3106
  if (session && session.resultCode === 0) {
2696
3107
  await translateAndSpeak(session.currentState, userLang);
3108
+ setClickedStart(false);
2697
3109
  } else {
2698
3110
  throw new Error('No session');
2699
3111
  }
@@ -2716,6 +3128,7 @@ const MemoriWidget = ({
2716
3128
  birth
2717
3129
  ).then(() => {
2718
3130
  setHasUserActivatedSpeak(true);
3131
+ setClickedStart(false);
2719
3132
  });
2720
3133
  }
2721
3134
  }
@@ -2762,14 +3175,14 @@ const MemoriWidget = ({
2762
3175
  ).text,
2763
3176
  }))
2764
3177
  );
2765
- } catch (e) {
2766
- console.error('[onClickStart] Error translating messages:', e);
3178
+ } catch {
3179
+ // ignore translation errors
2767
3180
  }
2768
3181
  }
2769
3182
 
2770
3183
  setHistory(translatedMessages);
2771
- } catch (e) {
2772
- console.error('[onClickStart] Error retrieving chat logs:', e);
3184
+ } catch {
3185
+ // ignore chat log retrieval errors
2773
3186
  }
2774
3187
 
2775
3188
  if (
@@ -2778,6 +3191,7 @@ const MemoriWidget = ({
2778
3191
  ) {
2779
3192
  // we have a history, don't push message
2780
3193
  setHasUserActivatedSpeak(true);
3194
+ setClickedStart(false);
2781
3195
  await translateAndSpeak(
2782
3196
  currentState,
2783
3197
  userLang,
@@ -2787,16 +3201,13 @@ const MemoriWidget = ({
2787
3201
  !!translatedMessages?.length
2788
3202
  );
2789
3203
  } else {
2790
- console.log('[onClickStart] Starting with initial question');
2791
3204
  // remove default initial message
2792
3205
  translatedMessages = [];
2793
3206
  setHistory([]);
2794
3207
 
2795
- setMemoriTyping(true);
2796
-
2797
3208
  // we have no chat history, we start by initial question
2798
3209
  const placeSpec = getPlaceSpecForEnterText(position);
2799
- const response = await postTextEnteredEvent({
3210
+ const response = await postEnterTextAsync({
2800
3211
  sessionId: sessionID!,
2801
3212
  text: initialQuestion,
2802
3213
  ...(memori.needsDateTime && {
@@ -2804,8 +3215,7 @@ const MemoriWidget = ({
2804
3215
  }),
2805
3216
  ...(placeSpec !== undefined && { place: placeSpec }),
2806
3217
  });
2807
-
2808
- // Handle 500 error from TextEnteredEvent
3218
+ // Handle 500 error from EnterTextAsync
2809
3219
  if (response.resultCode === 500 && response.resultMessage) {
2810
3220
  setHistory(h => [
2811
3221
  ...h,
@@ -2818,16 +3228,36 @@ const MemoriWidget = ({
2818
3228
  date: new Date().toISOString(),
2819
3229
  },
2820
3230
  ]);
2821
- setMemoriTyping(false);
2822
3231
  return;
2823
3232
  }
2824
3233
 
2825
- await translateAndSpeak(
2826
- response.currentState ?? currentState,
2827
- userLang,
2828
- undefined,
2829
- false
2830
- );
3234
+ const onClickStartCorrelationID = readCorrelationID(response);
3235
+ if (response.resultCode === 0 && onClickStartCorrelationID) {
3236
+ setMemoriTyping(true);
3237
+ try {
3238
+ const natsEvent = await waitForEnterTextNatsResponse(
3239
+ onClickStartCorrelationID
3240
+ );
3241
+ if (natsEvent.resultCode === 0 && natsEvent.currentState) {
3242
+ await translateAndSpeak(
3243
+ natsEvent.currentState,
3244
+ userLang,
3245
+ undefined,
3246
+ false
3247
+ );
3248
+ setClickedStart(false);
3249
+ }
3250
+ } catch (err) {
3251
+ logWidgetError('onClickStart NATS wait failed', err);
3252
+ setMemoriTyping(false);
3253
+ setTypingText(undefined);
3254
+ }
3255
+ } else if (response.resultCode === 0) {
3256
+ logWidgetError(
3257
+ 'onClickStart enter-text missing correlationID',
3258
+ response
3259
+ );
3260
+ }
2831
3261
  }
2832
3262
  }
2833
3263
  }
@@ -2838,6 +3268,7 @@ const MemoriWidget = ({
2838
3268
 
2839
3269
  // everything is fine, just translate dialog state and activate chat
2840
3270
  await translateAndSpeak(dialogState!, userLang);
3271
+ setClickedStart(false);
2841
3272
  }
2842
3273
  },
2843
3274
  [memoriPwd, memori, memoriTokens, birthDate, sessionId, userLang, position]
@@ -2845,19 +3276,40 @@ const MemoriWidget = ({
2845
3276
 
2846
3277
  const setPositionPopoverOpen = useCallback(
2847
3278
  (open: boolean) => {
2848
- setPositionPopoverOpenState(open);
2849
- if (!open && autoStart) {
2850
- onClickStart();
2851
- }
3279
+ setPositionPopoverOpenState(wasOpen => {
3280
+ if (
3281
+ shouldRestartSessionOnPositionPopoverClose(wasOpen, open, autoStart)
3282
+ ) {
3283
+ // Defer: React setState updaters must stay pure.
3284
+ queueMicrotask(() => {
3285
+ onClickStart();
3286
+ });
3287
+ }
3288
+ return open;
3289
+ });
2852
3290
  },
2853
3291
  [autoStart, onClickStart]
2854
3292
  );
2855
3293
 
2856
3294
  useEffect(() => {
2857
- if (!clickedStart && autoStart && selectedLayout !== 'HIDDEN_CHAT') {
3295
+ if (
3296
+ !clickedStart &&
3297
+ !sessionStartingRef.current &&
3298
+ !sessionId &&
3299
+ autoStart &&
3300
+ selectedLayout !== 'HIDDEN_CHAT' &&
3301
+ (!needsCredits || hasEnoughCredits)
3302
+ ) {
2858
3303
  onClickStart();
2859
3304
  }
2860
- }, [clickedStart, autoStart, selectedLayout]);
3305
+ }, [
3306
+ clickedStart,
3307
+ autoStart,
3308
+ selectedLayout,
3309
+ sessionId,
3310
+ needsCredits,
3311
+ hasEnoughCredits,
3312
+ ]);
2861
3313
 
2862
3314
  useEffect(() => {
2863
3315
  const targetNode =
@@ -2868,29 +3320,31 @@ const MemoriWidget = ({
2868
3320
  return;
2869
3321
  }
2870
3322
 
3323
+ const propsToken = additionalInfo?.loginToken ?? authToken;
3324
+ const initialDomToken = targetNode.getAttribute('authtoken') || undefined;
3325
+ if (initialDomToken && !propsToken) {
3326
+ setLoginToken(initialDomToken);
3327
+ userTokenRef.current = initialDomToken;
3328
+ }
3329
+
3330
+ const applyAuthTokenFromElement = (element: Element) => {
3331
+ const clientNode =
3332
+ element.nodeName === 'MEMORI-CLIENT'
3333
+ ? element
3334
+ : element.closest('memori-client') ?? element.parentElement;
3335
+ const token = clientNode?.getAttribute('authtoken') || undefined;
3336
+ setLoginToken(token);
3337
+ userTokenRef.current = token;
3338
+ };
3339
+
2871
3340
  const config = { attributes: true, childList: false, subtree: false };
2872
- const callback: MutationCallback = (mutationList, _observer) => {
3341
+ const callback: MutationCallback = mutationList => {
2873
3342
  for (const mutation of mutationList) {
2874
3343
  if (
2875
3344
  mutation.type === 'attributes' &&
2876
3345
  mutation.attributeName?.toLowerCase() === 'authtoken'
2877
3346
  ) {
2878
- if (mutation.target.nodeName === 'MEMORI-CLIENT') {
2879
- setLoginToken(
2880
- // @ts-ignore
2881
- mutation.target.getAttribute('authtoken') || undefined
2882
- );
2883
- // @ts-ignore
2884
- userToken = mutation.target.getAttribute('authtoken') || undefined;
2885
- } else {
2886
- // @ts-ignore
2887
- setLoginToken(
2888
- mutation.target?.parentElement?.getAttribute('authtoken') ||
2889
- undefined
2890
- );
2891
- // @ts-ignore
2892
- userToken = mutation.target.getAttribute('authtoken') || undefined;
2893
- }
3347
+ applyAuthTokenFromElement(mutation.target as Element);
2894
3348
  }
2895
3349
  }
2896
3350
  };
@@ -2900,7 +3354,7 @@ const MemoriWidget = ({
2900
3354
  return () => {
2901
3355
  observer.disconnect();
2902
3356
  };
2903
- }, []);
3357
+ }, [memori.name, memori.memoriID, additionalInfo?.loginToken, authToken]);
2904
3358
 
2905
3359
  /**
2906
3360
  * Experts references
@@ -2914,11 +3368,9 @@ const MemoriWidget = ({
2914
3368
 
2915
3369
  if (resp.resultCode === 0) {
2916
3370
  setExperts(experts);
2917
- } else {
2918
- console.warn('Error fetching experts', resp);
2919
3371
  }
2920
- } catch (err) {
2921
- console.warn(err);
3372
+ } catch {
3373
+ // ignore expert fetch errors
2922
3374
  }
2923
3375
  }, [sessionId, memori?.enableBoardOfExperts]);
2924
3376
  useEffect(() => {
@@ -2931,39 +3383,74 @@ const MemoriWidget = ({
2931
3383
  !!user?.userID &&
2932
3384
  user?.pAndCUAccepted;
2933
3385
 
2934
- // check if owner has enough credits
2935
- const needsCredits = tenant?.billingDelegation;
2936
- const [hasEnoughCredits, setHasEnoughCredits] = useState<boolean>(true);
2937
- const checkCredits = useCallback(async () => {
2938
- if (!tenant?.billingDelegation) return;
3386
+ const handleNotEnoughCredits = useCallback(() => {
3387
+ setHasEnoughCredits(false);
3388
+ setAuthModalState(null);
3389
+ add(
3390
+ createAlertOptions({
3391
+ description: t('notEnoughCredits'),
3392
+ severity: 'error',
3393
+ })
3394
+ );
3395
+ }, [add, t]);
3396
+ const checkCredits = useCallback(
3397
+ async (options?: { notify?: boolean }) => {
3398
+ if (!tenant?.billingDelegation) return true;
3399
+
3400
+ // Billing delegation is active: credits MUST be verified.
3401
+ // Without either owner identifier we cannot call the API, so we fail closed
3402
+ // instead of silently letting the session start unverified.
3403
+ if (!ownerUserID && !ownerUserName) {
3404
+ if (options?.notify) {
3405
+ handleNotEnoughCredits();
3406
+ } else {
3407
+ setHasEnoughCredits(false);
3408
+ }
3409
+ return false;
3410
+ }
2939
3411
 
2940
- try {
2941
- const resp = await getCredits({
2942
- operation: deepThoughtEnabled
2943
- ? 'dt_session_creation'
2944
- : 'session_creation',
2945
- baseUrl: baseUrl,
2946
- userID: ownerUserID,
2947
- userName: ownerUserName,
2948
- tenant: tenantID,
2949
- });
3412
+ try {
3413
+ const resp = await getCredits({
3414
+ operation: deepThoughtEnabled
3415
+ ? 'dt_session_creation'
3416
+ : 'session_creation',
3417
+ baseUrl: baseUrl,
3418
+ userID: ownerUserID,
3419
+ userName: ownerUserName,
3420
+ tenant: tenantID,
3421
+ });
2950
3422
 
2951
- if (resp.enough) {
2952
- setHasEnoughCredits(true);
2953
- } else {
2954
- setHasEnoughCredits(false);
2955
- console.warn('Not enough credits. Required:', resp.required);
3423
+ if (resp.enough) {
3424
+ setHasEnoughCredits(true);
3425
+ return true;
3426
+ } else {
3427
+ if (options?.notify) {
3428
+ handleNotEnoughCredits();
3429
+ } else {
3430
+ setHasEnoughCredits(false);
3431
+ }
3432
+ return false;
3433
+ }
3434
+ } catch (err) {
3435
+ logWidgetError('checkCredits failed', err);
3436
+ return true;
2956
3437
  }
2957
- } catch (e) {
2958
- let err = e as Error;
2959
- console.debug(err);
2960
- }
2961
- }, [tenant?.billingDelegation, deepThoughtEnabled]);
3438
+ },
3439
+ [
3440
+ baseUrl,
3441
+ deepThoughtEnabled,
3442
+ handleNotEnoughCredits,
3443
+ ownerUserID,
3444
+ ownerUserName,
3445
+ tenant?.billingDelegation,
3446
+ tenantID,
3447
+ ]
3448
+ );
2962
3449
  useEffect(() => {
2963
3450
  if (tenant?.billingDelegation) {
2964
3451
  checkCredits();
2965
3452
  }
2966
- }, [tenant?.billingDelegation, deepThoughtEnabled]);
3453
+ }, [tenant?.billingDelegation, deepThoughtEnabled, checkCredits]);
2967
3454
 
2968
3455
  useEffect(() => {
2969
3456
  if (__WEBCOMPONENT__) return;
@@ -3036,7 +3523,7 @@ const MemoriWidget = ({
3036
3523
  setShowLoginDrawer(false);
3037
3524
  setUser(undefined);
3038
3525
  setLoginToken(undefined);
3039
- userToken = undefined;
3526
+ userTokenRef.current = undefined;
3040
3527
  removeLocalConfig('loginToken');
3041
3528
  });
3042
3529
  },
@@ -3113,8 +3600,7 @@ const MemoriWidget = ({
3113
3600
  showTypingText:
3114
3601
  showTypingText ?? integrationConfig?.showTypingText ?? false,
3115
3602
  history: showFullHistory ? history : history.slice(-2),
3116
- authToken:
3117
- loginToken ?? userToken ?? additionalInfo?.loginToken ?? authToken,
3603
+ authToken: resolveLoginToken(),
3118
3604
  dialogState: currentDialogState,
3119
3605
  pushMessage,
3120
3606
  simulateUserPrompt,
@@ -3170,19 +3656,14 @@ const MemoriWidget = ({
3170
3656
  isChatlogPanel:
3171
3657
  (integrationConfig as { artifactChatLogPanel?: boolean } | undefined)
3172
3658
  ?.artifactChatLogPanel === true,
3659
+ globalBackground: globalBackground || undefined,
3173
3660
  };
3174
3661
 
3175
- const integrationBackground =
3176
- integration && globalBackgroundUrl ? (
3177
- <div className="memori--global-background">
3178
- <div
3179
- className="memori--global-background-image"
3180
- style={{ backgroundImage: globalBackgroundUrl }}
3181
- />
3182
- </div>
3183
- ) : (
3184
- <div className="memori--global-background no-background-image" />
3185
- );
3662
+ // Layout chrome placeholder (e.g. Totem gradient when no image). The actual
3663
+ // integration background image is applied on `.memori-chat--content` via chatProps.
3664
+ const integrationBackground = (
3665
+ <div className="memori--global-background no-background-image" />
3666
+ );
3186
3667
 
3187
3668
  const integrationStyle =
3188
3669
  integration &&
@@ -3216,9 +3697,19 @@ const MemoriWidget = ({
3216
3697
  ? ZoomedFullBodyLayout
3217
3698
  : FullPageLayout;
3218
3699
 
3700
+ // Resolve the widget theme once so both `data-theme` on the root and the
3701
+ // `MemoriUIProvider` (which stamps portaled popups) stay in sync.
3702
+ // Prefer integration config; fall back to host dark mode when unset.
3703
+ const widgetTheme: 'light' | 'dark' | undefined =
3704
+ integrationConfig?.theme === 'light' || integrationConfig?.theme === 'dark'
3705
+ ? integrationConfig.theme
3706
+ : isDarkTheme
3707
+ ? 'dark'
3708
+ : undefined;
3709
+
3219
3710
  return (
3220
3711
  <div
3221
- ref={widgetRootRef}
3712
+ ref={setWidgetRootEl}
3222
3713
  className={cx(
3223
3714
  'memori',
3224
3715
  'memori-widget',
@@ -3236,12 +3727,7 @@ const MemoriWidget = ({
3236
3727
  'memori--has-active-session': !!sessionId,
3237
3728
  }
3238
3729
  )}
3239
- data-theme={
3240
- integrationConfig?.theme === 'light' ||
3241
- integrationConfig?.theme === 'dark'
3242
- ? integrationConfig.theme
3243
- : undefined
3244
- }
3730
+ data-theme={widgetTheme}
3245
3731
  data-memori-name={memori?.name}
3246
3732
  data-memori-id={memori?.engineMemoriID}
3247
3733
  data-memori-secondary-id={memori?.memoriID}
@@ -3253,304 +3739,326 @@ const MemoriWidget = ({
3253
3739
  })}
3254
3740
  style={{ height }}
3255
3741
  >
3256
- <Layout
3257
- Header={Header}
3258
- headerProps={headerProps}
3259
- Avatar={Avatar}
3260
- avatarProps={avatarProps}
3261
- Chat={Chat}
3262
- chatProps={chatProps}
3263
- StartPanel={StartPanel}
3264
- startPanelProps={startPanelProps}
3265
- integrationStyle={integrationStyle}
3266
- integrationBackground={integrationBackground}
3267
- poweredBy={poweredBy}
3268
- autoStart={autoStart}
3269
- sessionId={sessionId}
3270
- hasUserActivatedSpeak={hasUserActivatedSpeak}
3271
- loading={loading}
3272
- avatar3dHidden={avatar3dHidden ?? integrationConfig?.avatar_3d_hidden}
3273
- />
3274
-
3275
- <ArtifactAPIBridge
3276
- pushMessage={(message: Message) => {
3277
- setHistory(history => {
3278
- if (!history.length) return history;
3279
- const lastMessage = history[history.length - 1];
3280
- if (!lastMessage || lastMessage.fromUser) return history;
3281
- // Create a new message object with the updated text
3282
- const updatedLastMessage = {
3283
- ...lastMessage,
3284
- text: lastMessage.text + message.text,
3285
- };
3286
- return [...history.slice(0, -1), updatedLastMessage];
3287
- });
3288
- }}
3289
- />
3290
-
3291
- <audio
3292
- id="memori-audio"
3293
- style={{ display: 'none' }}
3294
- src="https://aisuru.com/intro.mp3"
3295
- />
3296
-
3297
- {isClient && (
3298
- <MemoriAuth
3299
- withModal
3300
- pwdOrTokens={authModalState}
3301
- openModal={!!authModalState}
3302
- setPwdOrTokens={setAuthModalState}
3303
- showTokens={memori.privacyType === 'SECRET'}
3304
- onFinish={(values: any) => {
3305
- if (values['password']) setMemoriPwd(values['password']);
3306
- if (values['password']) memoriPassword = values['password'];
3307
- if (values['tokens']) setMemoriTokens(values['tokens']);
3308
-
3309
- return reopenSession(
3310
- !sessionId,
3311
- values['password'],
3312
- values['tokens'],
3313
- personification?.tag,
3314
- personification?.pin,
3315
- {
3316
- LANG: userLang,
3317
- PATHNAME: window.location.pathname?.toUpperCase(),
3318
- ROUTE:
3319
- window.location.pathname?.split('/')?.pop()?.toUpperCase() ||
3320
- '',
3321
- ...(initialContextVars || {}),
3322
- },
3323
- initialQuestion,
3324
- birthDate
3325
- )
3326
- .then(state => {
3327
- if (!state?.sessionID) {
3328
- throw new Error('AUTH_FAILED');
3742
+ <MemoriUIProvider container={widgetRootEl} theme={widgetTheme}>
3743
+ {/* Inside themed root so alert text uses dark-theme tokens (white). */}
3744
+ <AlertViewport placement="top-end" style={{ zIndex: 10002 }} />
3745
+ <WidgetSurfaceProvider value={widgetSurfaceEl}>
3746
+ <div ref={setWidgetSurfaceEl} className="memori-widget__surface">
3747
+ <Layout
3748
+ Header={Header}
3749
+ headerProps={headerProps}
3750
+ Avatar={Avatar}
3751
+ avatarProps={avatarProps}
3752
+ Chat={Chat}
3753
+ chatProps={chatProps}
3754
+ StartPanel={StartPanel}
3755
+ startPanelProps={startPanelProps}
3756
+ integrationStyle={integrationStyle}
3757
+ integrationBackground={integrationBackground}
3758
+ poweredBy={poweredBy}
3759
+ autoStart={autoStart}
3760
+ sessionId={sessionId}
3761
+ hasUserActivatedSpeak={hasUserActivatedSpeak}
3762
+ loading={loading}
3763
+ avatar3dHidden={
3764
+ avatar3dHidden ?? integrationConfig?.avatar_3d_hidden
3765
+ }
3766
+ totemContentMaxWidth={integrationConfig?.totemContentMaxWidth}
3767
+ />
3768
+
3769
+ <ArtifactAPIBridge
3770
+ pushMessage={(message: Message) => {
3771
+ setHistory(history => {
3772
+ if (!history.length) return history;
3773
+ const lastMessage = history[history.length - 1];
3774
+ if (!lastMessage || lastMessage.fromUser) return history;
3775
+ // Create a new message object with the updated text
3776
+ const updatedLastMessage = {
3777
+ ...lastMessage,
3778
+ text: lastMessage.text + message.text,
3779
+ };
3780
+ return [...history.slice(0, -1), updatedLastMessage];
3781
+ });
3782
+ }}
3783
+ />
3784
+
3785
+ <audio
3786
+ id="memori-audio"
3787
+ style={{ display: 'none' }}
3788
+ src="https://aisuru.com/intro.mp3"
3789
+ />
3790
+
3791
+ {isClient && (
3792
+ <MemoriAuth
3793
+ withModal
3794
+ pwdOrTokens={authModalState}
3795
+ openModal={!!authModalState}
3796
+ setPwdOrTokens={setAuthModalState}
3797
+ showTokens={memori.privacyType === 'SECRET'}
3798
+ onFinish={(values: any) => {
3799
+ if (values['password']) setMemoriPwd(values['password']);
3800
+ if (values['password']) memoriPassword = values['password'];
3801
+ if (values['tokens']) setMemoriTokens(values['tokens']);
3802
+
3803
+ return reopenSession(
3804
+ !sessionId,
3805
+ values['password'],
3806
+ values['tokens'],
3807
+ personification?.tag,
3808
+ personification?.pin,
3809
+ {
3810
+ LANG: userLang,
3811
+ PATHNAME: window.location.pathname?.toUpperCase(),
3812
+ ROUTE:
3813
+ window.location.pathname
3814
+ ?.split('/')
3815
+ ?.pop()
3816
+ ?.toUpperCase() || '',
3817
+ ...(initialContextVars || {}),
3818
+ },
3819
+ initialQuestion,
3820
+ birthDate
3821
+ )
3822
+ .then(state => {
3823
+ if (!state?.sessionID) {
3824
+ throw new Error('AUTH_FAILED');
3825
+ }
3826
+
3827
+ setAuthModalState(null);
3828
+ // If we got a valid state from reopenSession, don't call onClickStart again
3829
+ // to avoid duplicate snippet execution
3830
+ if (state?.dialogState) {
3831
+ setHasUserActivatedSpeak(true);
3832
+ } else {
3833
+ // Only call onClickStart if reopenSession didn't return a valid state
3834
+ onClickStart(state);
3835
+ }
3836
+ })
3837
+ .catch(error => {
3838
+ if (
3839
+ !(error instanceof Error) ||
3840
+ error.message !== 'AUTH_FAILED'
3841
+ ) {
3842
+ setGotErrorInOpening(true);
3843
+ }
3844
+ throw error;
3845
+ });
3846
+ }}
3847
+ minimumNumberOfRecoveryTokens={
3848
+ memori?.minimumNumberOfRecoveryTokens ?? 1
3329
3849
  }
3330
-
3331
- setAuthModalState(null);
3332
- // If we got a valid state from reopenSession, don't call onClickStart again
3333
- // to avoid duplicate snippet execution
3334
- if (state?.dialogState) {
3335
- setHasUserActivatedSpeak(true);
3336
- } else {
3337
- // Only call onClickStart if reopenSession didn't return a valid state
3338
- onClickStart(state);
3850
+ />
3851
+ )}
3852
+
3853
+ {isClient && (
3854
+ <AgeVerificationModal
3855
+ visible={showAgeVerification}
3856
+ minAge={minAge}
3857
+ onClose={birthDate => {
3858
+ if (birthDate) {
3859
+ setBirthDate(birthDate);
3860
+
3861
+ setLocalConfig('birthDate', birthDate);
3862
+
3863
+ reopenSession(
3864
+ !sessionId,
3865
+ memoriPassword || memoriPwd || memori?.secretToken,
3866
+ memoriTokens,
3867
+ personification?.tag,
3868
+ personification?.pin,
3869
+ {
3870
+ LANG: userLang,
3871
+ PATHNAME: window.location.pathname?.toUpperCase(),
3872
+ ROUTE:
3873
+ window.location.pathname
3874
+ ?.split('/')
3875
+ ?.pop()
3876
+ ?.toUpperCase() || '',
3877
+ ...(initialContextVars || {}),
3878
+ },
3879
+ initialQuestion,
3880
+ birthDate
3881
+ )
3882
+ .then(state => {
3883
+ setShowAgeVerification(false);
3884
+ setAuthModalState(null);
3885
+ onClickStart(state || undefined);
3886
+ })
3887
+ .catch(() => {
3888
+ setShowAgeVerification(false);
3889
+ setGotErrorInOpening(true);
3890
+ });
3891
+ } else {
3892
+ setShowAgeVerification(false);
3893
+ setClickedStart(false);
3894
+ }
3895
+ }}
3896
+ />
3897
+ )}
3898
+
3899
+ {showSettingsDrawer && (
3900
+ <SettingsDrawer
3901
+ layout={selectedLayout}
3902
+ open={!!showSettingsDrawer}
3903
+ onClose={() => setShowSettingsDrawer(false)}
3904
+ microphoneMode={
3905
+ continuousSpeech ? 'CONTINUOUS' : 'HOLD_TO_TALK'
3339
3906
  }
3340
- })
3341
- .catch(error => {
3342
- if (
3343
- !(error instanceof Error) ||
3344
- error.message !== 'AUTH_FAILED'
3345
- ) {
3346
- setGotErrorInOpening(true);
3907
+ continuousSpeechTimeout={continuousSpeechTimeout}
3908
+ setMicrophoneMode={mode =>
3909
+ setContinuousSpeech(mode === 'CONTINUOUS')
3347
3910
  }
3348
- throw error;
3349
- });
3350
- }}
3351
- minimumNumberOfRecoveryTokens={
3352
- memori?.minimumNumberOfRecoveryTokens ?? 1
3353
- }
3354
- />
3355
- )}
3356
-
3357
- {isClient && (
3358
- <AgeVerificationModal
3359
- visible={showAgeVerification}
3360
- minAge={minAge}
3361
- onClose={birthDate => {
3362
- if (birthDate) {
3363
- setBirthDate(birthDate);
3364
-
3365
- setLocalConfig('birthDate', birthDate);
3366
-
3367
- reopenSession(
3368
- !sessionId,
3369
- memoriPassword || memoriPwd || memori?.secretToken,
3370
- memoriTokens,
3371
- personification?.tag,
3372
- personification?.pin,
3373
- {
3374
- LANG: userLang,
3375
- PATHNAME: window.location.pathname?.toUpperCase(),
3376
- ROUTE:
3377
- window.location.pathname
3378
- ?.split('/')
3379
- ?.pop()
3380
- ?.toUpperCase() || '',
3381
- ...(initialContextVars || {}),
3382
- },
3383
- initialQuestion,
3384
- birthDate
3385
- )
3386
- .then(state => {
3387
- setShowAgeVerification(false);
3388
- setAuthModalState(null);
3389
- onClickStart(state || undefined);
3390
- })
3391
- .catch(() => {
3392
- setShowAgeVerification(false);
3393
- setGotErrorInOpening(true);
3394
- });
3395
- } else {
3396
- setShowAgeVerification(false);
3397
- setClickedStart(false);
3398
- }
3399
- }}
3400
- />
3401
- )}
3402
-
3403
- {showSettingsDrawer && (
3404
- <SettingsDrawer
3405
- layout={selectedLayout}
3406
- open={!!showSettingsDrawer}
3407
- onClose={() => setShowSettingsDrawer(false)}
3408
- microphoneMode={continuousSpeech ? 'CONTINUOUS' : 'HOLD_TO_TALK'}
3409
- continuousSpeechTimeout={continuousSpeechTimeout}
3410
- setMicrophoneMode={mode => setContinuousSpeech(mode === 'CONTINUOUS')}
3411
- setContinuousSpeechTimeout={setContinuousSpeechTimeout}
3412
- controlsPosition={controlsPosition}
3413
- setControlsPosition={setControlsPosition}
3414
- hideEmissions={hideEmissions}
3415
- setHideEmissions={setHideEmissions}
3416
- avatarType={avatarType}
3417
- setAvatarType={setAvatarType}
3418
- enablePositionControls={enablePositionControls}
3419
- setEnablePositionControls={setEnablePositionControls}
3420
- isAvatar3d={!!integrationConfig?.avatarURL}
3421
- additionalSettings={additionalSettings}
3422
- speakerMuted={speakerMuted}
3423
- />
3424
- )}
3425
-
3426
- {showChatHistoryDrawer && (
3427
- <ChatHistoryDrawer
3428
- open={!!showChatHistoryDrawer}
3429
- onClose={() => setShowChatHistoryDrawer(false)}
3430
- resumeSession={chatLog => {
3431
- setChatLogID(chatLog.chatLogID);
3432
- onClickStart(undefined, false, chatLog);
3433
- setShowChatHistoryDrawer(false);
3434
- }}
3435
- apiClient={client}
3436
- sessionId={sessionId || ''}
3437
- memori={memori}
3438
- baseUrl={baseUrl}
3439
- history={history}
3440
- apiUrl={client.constants.BACKEND_URL}
3441
- loginToken={loginToken}
3442
- language={language}
3443
- userLang={userLang}
3444
- isMultilanguageEnabled={isMultilanguageEnabled}
3445
- />
3446
- )}
3447
-
3448
- {showKnownFactsDrawer && sessionId && (
3449
- <KnownFacts
3450
- apiClient={client}
3451
- memori={memori}
3452
- sessionID={sessionId}
3453
- visible={showKnownFactsDrawer}
3454
- closeDrawer={() => setShowKnownFactsDrawer(false)}
3455
- />
3456
- )}
3457
-
3458
- {showExpertsDrawer && !!experts && (
3459
- <ExpertsDrawer
3460
- apiUrl={client.constants.BACKEND_URL}
3461
- baseUrl={baseUrl}
3462
- tenant={tenant}
3463
- experts={experts}
3464
- open={showExpertsDrawer}
3465
- onClose={() => setShowExpertsDrawer(false)}
3466
- />
3467
- )}
3468
-
3469
- {showLoginDrawer && tenant?.name && (
3470
- <LoginDrawer
3471
- tenant={tenant}
3472
- apiClient={client}
3473
- open={!!showLoginDrawer}
3474
- user={user}
3475
- loginToken={loginToken}
3476
- onClose={() => setShowLoginDrawer(false)}
3477
- drawerClassName={
3478
- selectedLayout === 'WEBSITE_ASSISTANT'
3479
- ? 'memori-drawer--above-website-assistant'
3480
- : undefined
3481
- }
3482
- onLogin={(user, token) => {
3483
- //The user is logged in, so we need to set open a new session with the new token
3484
- reopenSession(
3485
- false,
3486
- memoriPassword || memoriPwd || memori?.secretToken,
3487
- [],
3488
- personification?.tag,
3489
- personification?.pin,
3490
- {
3491
- LANG: userLang,
3492
- PATHNAME: window.location.pathname?.toUpperCase(),
3493
- ROUTE:
3494
- window.location.pathname?.split('/')?.pop()?.toUpperCase() ||
3495
- '',
3496
- ...(initialContextVars || {}),
3497
- },
3498
- undefined, // Don't send initialQuestion after login, only show the login status chip
3499
- birthDate,
3500
- { loginToken: token } as any,
3501
- undefined,
3502
- sessionId
3503
- ).then(state => {
3504
- setShowLoginDrawer(false);
3505
- setUser(user);
3506
- setLoginToken(token);
3507
- userToken = token;
3508
- setLocalConfig('loginToken', token);
3509
- // Push a message with initial status to show status message when a new session is created after login
3510
- if (
3511
- state?.sessionID &&
3512
- state.sessionID !== sessionId &&
3513
- state?.dialogState
3514
- ) {
3515
- // Push a message with initial status message showing successful login
3516
- // Only show the chip component, not the emission text
3517
- const username = user?.userName || t('login.user');
3518
- pushMessage({
3519
- text: '', // Empty text so only the chip is visible
3520
- emitter: state.dialogState.emitter,
3521
- media:
3522
- state.dialogState.emittedMedia ??
3523
- state.dialogState.media ??
3911
+ setContinuousSpeechTimeout={setContinuousSpeechTimeout}
3912
+ controlsPosition={controlsPosition}
3913
+ setControlsPosition={setControlsPosition}
3914
+ hideEmissions={hideEmissions}
3915
+ setHideEmissions={setHideEmissions}
3916
+ avatarType={avatarType}
3917
+ setAvatarType={setAvatarType}
3918
+ enablePositionControls={enablePositionControls}
3919
+ setEnablePositionControls={setEnablePositionControls}
3920
+ isAvatar3d={!!integrationConfig?.avatarURL}
3921
+ additionalSettings={additionalSettings}
3922
+ speakerMuted={speakerMuted}
3923
+ />
3924
+ )}
3925
+
3926
+ {showChatHistoryDrawer && (
3927
+ <ChatHistoryDrawer
3928
+ open={!!showChatHistoryDrawer}
3929
+ onClose={() => setShowChatHistoryDrawer(false)}
3930
+ resumeSession={chatLog => {
3931
+ setChatLogID(chatLog.chatLogID);
3932
+ onClickStart(undefined, false, chatLog);
3933
+ setShowChatHistoryDrawer(false);
3934
+ }}
3935
+ apiClient={client}
3936
+ sessionId={sessionId || ''}
3937
+ memori={memori}
3938
+ baseUrl={baseUrl}
3939
+ history={history}
3940
+ apiUrl={client.constants.BACKEND_URL}
3941
+ loginToken={loginToken}
3942
+ language={language}
3943
+ userLang={userLang}
3944
+ isMultilanguageEnabled={isMultilanguageEnabled}
3945
+ />
3946
+ )}
3947
+
3948
+ {showKnownFactsDrawer && sessionId && (
3949
+ <KnownFacts
3950
+ apiClient={client}
3951
+ memori={memori}
3952
+ sessionID={sessionId}
3953
+ visible={showKnownFactsDrawer}
3954
+ closeDrawer={() => setShowKnownFactsDrawer(false)}
3955
+ />
3956
+ )}
3957
+
3958
+ {showExpertsDrawer && !!experts && (
3959
+ <ExpertsDrawer
3960
+ apiUrl={client.constants.BACKEND_URL}
3961
+ baseUrl={baseUrl}
3962
+ tenant={tenant}
3963
+ experts={experts}
3964
+ open={showExpertsDrawer}
3965
+ onClose={() => setShowExpertsDrawer(false)}
3966
+ />
3967
+ )}
3968
+
3969
+ {showLoginDrawer && tenant?.name && (
3970
+ <LoginDrawer
3971
+ tenant={tenant}
3972
+ apiClient={client}
3973
+ open={!!showLoginDrawer}
3974
+ user={user}
3975
+ loginToken={loginToken}
3976
+ onClose={() => setShowLoginDrawer(false)}
3977
+ drawerClassName={
3978
+ selectedLayout === 'WEBSITE_ASSISTANT'
3979
+ ? 'memori-drawer--above-website-assistant'
3980
+ : undefined
3981
+ }
3982
+ onLogin={(user, token) => {
3983
+ //The user is logged in, so we need to set open a new session with the new token
3984
+ reopenSession(
3985
+ false,
3986
+ memoriPassword || memoriPwd || memori?.secretToken,
3524
3987
  [],
3525
- fromUser: false,
3526
- initial: t('login.successfullyLoggedIn', { username }) as any,
3527
- contextVars: state.dialogState.contextVars,
3528
- date: state.dialogState.currentDate,
3529
- placeName: state.dialogState.currentPlaceName,
3530
- placeLatitude: state.dialogState.currentLatitude,
3531
- placeLongitude: state.dialogState.currentLongitude,
3532
- placeUncertaintyKm: state.dialogState.currentUncertaintyKm,
3533
- tag: state.dialogState.currentTag,
3534
- memoryTags: state.dialogState.memoryTags,
3535
- });
3536
- // Update the dialog state so the UI reflects the new session
3537
- setCurrentDialogState(state.dialogState);
3538
- }
3539
- });
3540
- }}
3541
- setUser={setUser}
3542
- onLogout={() => {
3543
- if (!loginToken) return;
3544
- client.backend.pwlUserLogout(loginToken).then(() => {
3545
- setShowLoginDrawer(false);
3546
- setUser(undefined);
3547
- setLoginToken(undefined);
3548
- userToken = undefined;
3549
- removeLocalConfig('loginToken');
3550
- });
3551
- }}
3552
- />
3553
- )}
3988
+ personification?.tag,
3989
+ personification?.pin,
3990
+ {
3991
+ LANG: userLang,
3992
+ PATHNAME: window.location.pathname?.toUpperCase(),
3993
+ ROUTE:
3994
+ window.location.pathname
3995
+ ?.split('/')
3996
+ ?.pop()
3997
+ ?.toUpperCase() || '',
3998
+ ...(initialContextVars || {}),
3999
+ },
4000
+ undefined, // Don't send initialQuestion after login, only show the login status chip
4001
+ birthDate,
4002
+ { loginToken: token } as any,
4003
+ undefined,
4004
+ sessionId
4005
+ ).then(state => {
4006
+ setShowLoginDrawer(false);
4007
+ setUser(user);
4008
+ setLoginToken(token);
4009
+ userTokenRef.current = token;
4010
+ setLocalConfig('loginToken', token);
4011
+ // Push a message with initial status to show status message when a new session is created after login
4012
+ if (
4013
+ state?.sessionID &&
4014
+ state.sessionID !== sessionId &&
4015
+ state?.dialogState
4016
+ ) {
4017
+ // Push a message with initial status message showing successful login
4018
+ // Only show the chip component, not the emission text
4019
+ const username = user?.userName || t('login.user');
4020
+ pushMessage({
4021
+ text: '', // Empty text so only the chip is visible
4022
+ emitter: state.dialogState.emitter,
4023
+ media:
4024
+ state.dialogState.emittedMedia ??
4025
+ state.dialogState.media ??
4026
+ [],
4027
+ fromUser: false,
4028
+ initial: t('login.successfullyLoggedIn', {
4029
+ username,
4030
+ }) as any,
4031
+ contextVars: state.dialogState.contextVars,
4032
+ date: state.dialogState.currentDate,
4033
+ placeName: state.dialogState.currentPlaceName,
4034
+ placeLatitude: state.dialogState.currentLatitude,
4035
+ placeLongitude: state.dialogState.currentLongitude,
4036
+ placeUncertaintyKm:
4037
+ state.dialogState.currentUncertaintyKm,
4038
+ tag: state.dialogState.currentTag,
4039
+ memoryTags: state.dialogState.memoryTags,
4040
+ });
4041
+ // Update the dialog state so the UI reflects the new session
4042
+ setCurrentDialogState(state.dialogState);
4043
+ }
4044
+ });
4045
+ }}
4046
+ setUser={setUser}
4047
+ onLogout={() => {
4048
+ if (!loginToken) return;
4049
+ client.backend.pwlUserLogout(loginToken).then(() => {
4050
+ setShowLoginDrawer(false);
4051
+ setUser(undefined);
4052
+ setLoginToken(undefined);
4053
+ userTokenRef.current = undefined;
4054
+ removeLocalConfig('loginToken');
4055
+ });
4056
+ }}
4057
+ />
4058
+ )}
4059
+ </div>
4060
+ </WidgetSurfaceProvider>
4061
+ </MemoriUIProvider>
3554
4062
  </div>
3555
4063
  );
3556
4064
  };