@memori.ai/memori-react 9.0.0-alpha.0 → 9.0.0-alpha.10

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