@memori.ai/memori-react 9.0.0-alpha.5 → 9.0.0-alpha.6

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 (186) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/components/AgeVerificationModal/AgeVerificationModal.js +5 -2
  3. package/dist/components/AgeVerificationModal/AgeVerificationModal.js.map +1 -1
  4. package/dist/components/Avatar/Avatar.js +5 -10
  5. package/dist/components/Avatar/Avatar.js.map +1 -1
  6. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +8 -1
  7. package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
  8. package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js +1 -1
  9. package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js.map +1 -1
  10. package/dist/components/Avatar/AvatarView/AvatarComponent/constants.d.ts +2 -0
  11. package/dist/components/Avatar/AvatarView/AvatarComponent/constants.js +14 -5
  12. package/dist/components/Avatar/AvatarView/AvatarComponent/constants.js.map +1 -1
  13. package/dist/components/ChatBubble/ChatBubble.js +19 -15
  14. package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
  15. package/dist/components/CompletionProviderStatus/CompletionProviderStatus.js +6 -3
  16. package/dist/components/CompletionProviderStatus/CompletionProviderStatus.js.map +1 -1
  17. package/dist/components/DateSelector/DateSelector.d.ts +2 -1
  18. package/dist/components/DateSelector/DateSelector.js +17 -7
  19. package/dist/components/DateSelector/DateSelector.js.map +1 -1
  20. package/dist/components/FilePreview/FilePreview.js +22 -5
  21. package/dist/components/FilePreview/FilePreview.js.map +1 -1
  22. package/dist/components/MediaWidget/MediaItemWidget.js +14 -12
  23. package/dist/components/MediaWidget/MediaItemWidget.js.map +1 -1
  24. package/dist/components/MediaWidget/MediaItemWidget.utils.d.ts +3 -2
  25. package/dist/components/MediaWidget/MediaItemWidget.utils.js +28 -6
  26. package/dist/components/MediaWidget/MediaItemWidget.utils.js.map +1 -1
  27. package/dist/components/MediaWidget/MediaPreviewModal.js +6 -7
  28. package/dist/components/MediaWidget/MediaPreviewModal.js.map +1 -1
  29. package/dist/components/MemoriWidget/MemoriWidget.js +632 -280
  30. package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
  31. package/dist/components/UploadButton/UploadButton.js +21 -5
  32. package/dist/components/UploadButton/UploadButton.js.map +1 -1
  33. package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js +123 -59
  34. package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
  35. package/dist/components/layouts/WebsiteAssistant/website-assistant.css +2 -1
  36. package/dist/helpers/constants.d.ts +3 -0
  37. package/dist/helpers/constants.js +27 -1
  38. package/dist/helpers/constants.js.map +1 -1
  39. package/dist/helpers/credits.d.ts +5 -2
  40. package/dist/helpers/credits.js +5 -1
  41. package/dist/helpers/credits.js.map +1 -1
  42. package/dist/helpers/message.d.ts +1 -1
  43. package/dist/helpers/message.js +4 -4
  44. package/dist/helpers/message.js.map +1 -1
  45. package/dist/helpers/nats/getNatsConfig.d.ts +9 -0
  46. package/dist/helpers/nats/getNatsConfig.js +65 -0
  47. package/dist/helpers/nats/getNatsConfig.js.map +1 -0
  48. package/dist/helpers/nats/isSessionExpiredError.d.ts +3 -0
  49. package/dist/helpers/nats/isSessionExpiredError.js +36 -0
  50. package/dist/helpers/nats/isSessionExpiredError.js.map +1 -0
  51. package/dist/helpers/nats/useNats.d.ts +12 -0
  52. package/dist/helpers/nats/useNats.js +75 -0
  53. package/dist/helpers/nats/useNats.js.map +1 -0
  54. package/dist/helpers/nats/useNatsSession.d.ts +28 -0
  55. package/dist/helpers/nats/useNatsSession.js +212 -0
  56. package/dist/helpers/nats/useNatsSession.js.map +1 -0
  57. package/dist/helpers/utils.d.ts +21 -0
  58. package/dist/helpers/utils.js +75 -4
  59. package/dist/helpers/utils.js.map +1 -1
  60. package/dist/locales/de.json +1 -0
  61. package/dist/locales/en.json +1 -0
  62. package/dist/locales/es.json +1 -0
  63. package/dist/locales/fr.json +1 -0
  64. package/dist/locales/it.json +1 -0
  65. package/dist/styles.css +1 -1
  66. package/dist/types/integration.d.ts +3 -0
  67. package/dist/types/integration.js +16 -0
  68. package/dist/types/integration.js.map +1 -0
  69. package/dist/version.d.ts +1 -1
  70. package/dist/version.js +1 -1
  71. package/esm/components/AgeVerificationModal/AgeVerificationModal.js +5 -2
  72. package/esm/components/AgeVerificationModal/AgeVerificationModal.js.map +1 -1
  73. package/esm/components/Avatar/Avatar.js +5 -10
  74. package/esm/components/Avatar/Avatar.js.map +1 -1
  75. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +9 -2
  76. package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
  77. package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js +2 -2
  78. package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.js.map +1 -1
  79. package/esm/components/Avatar/AvatarView/AvatarComponent/constants.d.ts +2 -0
  80. package/esm/components/Avatar/AvatarView/AvatarComponent/constants.js +13 -4
  81. package/esm/components/Avatar/AvatarView/AvatarComponent/constants.js.map +1 -1
  82. package/esm/components/ChatBubble/ChatBubble.js +19 -15
  83. package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
  84. package/esm/components/CompletionProviderStatus/CompletionProviderStatus.js +6 -3
  85. package/esm/components/CompletionProviderStatus/CompletionProviderStatus.js.map +1 -1
  86. package/esm/components/DateSelector/DateSelector.d.ts +2 -1
  87. package/esm/components/DateSelector/DateSelector.js +17 -7
  88. package/esm/components/DateSelector/DateSelector.js.map +1 -1
  89. package/esm/components/FilePreview/FilePreview.js +24 -7
  90. package/esm/components/FilePreview/FilePreview.js.map +1 -1
  91. package/esm/components/MediaWidget/MediaItemWidget.js +16 -14
  92. package/esm/components/MediaWidget/MediaItemWidget.js.map +1 -1
  93. package/esm/components/MediaWidget/MediaItemWidget.utils.d.ts +3 -2
  94. package/esm/components/MediaWidget/MediaItemWidget.utils.js +27 -6
  95. package/esm/components/MediaWidget/MediaItemWidget.utils.js.map +1 -1
  96. package/esm/components/MediaWidget/MediaPreviewModal.js +6 -7
  97. package/esm/components/MediaWidget/MediaPreviewModal.js.map +1 -1
  98. package/esm/components/MemoriWidget/MemoriWidget.js +632 -280
  99. package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
  100. package/esm/components/UploadButton/UploadButton.js +21 -5
  101. package/esm/components/UploadButton/UploadButton.js.map +1 -1
  102. package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js +123 -59
  103. package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
  104. package/esm/components/layouts/WebsiteAssistant/website-assistant.css +2 -1
  105. package/esm/helpers/constants.d.ts +3 -0
  106. package/esm/helpers/constants.js +26 -0
  107. package/esm/helpers/constants.js.map +1 -1
  108. package/esm/helpers/credits.d.ts +5 -2
  109. package/esm/helpers/credits.js +5 -1
  110. package/esm/helpers/credits.js.map +1 -1
  111. package/esm/helpers/message.d.ts +1 -1
  112. package/esm/helpers/message.js +2 -2
  113. package/esm/helpers/message.js.map +1 -1
  114. package/esm/helpers/nats/getNatsConfig.d.ts +9 -0
  115. package/esm/helpers/nats/getNatsConfig.js +61 -0
  116. package/esm/helpers/nats/getNatsConfig.js.map +1 -0
  117. package/esm/helpers/nats/isSessionExpiredError.d.ts +3 -0
  118. package/esm/helpers/nats/isSessionExpiredError.js +32 -0
  119. package/esm/helpers/nats/isSessionExpiredError.js.map +1 -0
  120. package/esm/helpers/nats/useNats.d.ts +12 -0
  121. package/esm/helpers/nats/useNats.js +72 -0
  122. package/esm/helpers/nats/useNats.js.map +1 -0
  123. package/esm/helpers/nats/useNatsSession.d.ts +28 -0
  124. package/esm/helpers/nats/useNatsSession.js +208 -0
  125. package/esm/helpers/nats/useNatsSession.js.map +1 -0
  126. package/esm/helpers/utils.d.ts +21 -0
  127. package/esm/helpers/utils.js +68 -3
  128. package/esm/helpers/utils.js.map +1 -1
  129. package/esm/locales/de.json +1 -0
  130. package/esm/locales/en.json +1 -0
  131. package/esm/locales/es.json +1 -0
  132. package/esm/locales/fr.json +1 -0
  133. package/esm/locales/it.json +1 -0
  134. package/esm/styles.css +1 -1
  135. package/esm/types/integration.d.ts +3 -0
  136. package/esm/types/integration.js +11 -0
  137. package/esm/types/integration.js.map +1 -0
  138. package/esm/version.d.ts +1 -1
  139. package/esm/version.js +1 -1
  140. package/package.json +5 -3
  141. package/src/components/AgeVerificationModal/AgeVerificationModal.tsx +6 -1
  142. package/src/components/Avatar/Avatar.stories.tsx +45 -28
  143. package/src/components/Avatar/Avatar.test.tsx +54 -0
  144. package/src/components/Avatar/Avatar.tsx +8 -12
  145. package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.tsx +12 -5
  146. package/src/components/Avatar/AvatarView/AvatarComponent/components/controllers/MorphTargetController.ts +2 -1
  147. package/src/components/Avatar/AvatarView/AvatarComponent/constants.ts +16 -4
  148. package/src/components/Avatar/__snapshots__/Avatar.test.tsx.snap +164 -0
  149. package/src/components/ChatBubble/ChatBubble.tsx +37 -12
  150. package/src/components/CompletionProviderStatus/CompletionProviderStatus.tsx +8 -4
  151. package/src/components/DateSelector/DateSelector.stories.tsx +11 -2
  152. package/src/components/DateSelector/DateSelector.tsx +28 -9
  153. package/src/components/FilePreview/FilePreview.tsx +28 -7
  154. package/src/components/MediaWidget/MediaItemWidget.tsx +26 -13
  155. package/src/components/MediaWidget/MediaItemWidget.utils.test.ts +45 -2
  156. package/src/components/MediaWidget/MediaItemWidget.utils.ts +39 -6
  157. package/src/components/MediaWidget/MediaPreviewModal.tsx +9 -7
  158. package/src/components/MemoriWidget/MemoriWidget.tsx +785 -331
  159. package/src/components/StartPanel/StartPanel.stories.tsx +22 -0
  160. package/src/components/StartPanel/StartPanel.test.tsx +64 -1
  161. package/src/components/StartPanel/__snapshots__/StartPanel.test.tsx.snap +261 -0
  162. package/src/components/UploadButton/UploadButton.tsx +30 -11
  163. package/src/components/UploadButton/UploadDocuments/UploadDocuments.tsx +148 -61
  164. package/src/components/UploadButton/__snapshots__/UploadButton.test.tsx.snap +2 -2
  165. package/src/components/layouts/WebsiteAssistant/website-assistant.css +2 -1
  166. package/src/components/layouts/layouts.stories.tsx +131 -12
  167. package/src/helpers/constants.ts +32 -1
  168. package/src/helpers/credits.ts +16 -1
  169. package/src/helpers/message.test.ts +28 -1
  170. package/src/helpers/message.ts +4 -4
  171. package/src/helpers/nats/getNatsConfig.ts +145 -0
  172. package/src/helpers/nats/isSessionExpiredError.test.ts +38 -0
  173. package/src/helpers/nats/isSessionExpiredError.ts +51 -0
  174. package/src/helpers/nats/useNats.ts +124 -0
  175. package/src/helpers/nats/useNatsSession.ts +394 -0
  176. package/src/helpers/utils.test.ts +162 -0
  177. package/src/helpers/utils.ts +108 -3
  178. package/src/index.stories.tsx +32 -0
  179. package/src/locales/de.json +1 -0
  180. package/src/locales/en.json +1 -0
  181. package/src/locales/es.json +1 -0
  182. package/src/locales/fr.json +1 -0
  183. package/src/locales/it.json +1 -0
  184. package/src/types/integration.test.ts +32 -0
  185. package/src/types/integration.ts +31 -0
  186. package/src/version.ts +1 -1
@@ -0,0 +1,3 @@
1
+ export type AvatarMode = 'readyplayerme' | 'readyplayerme-full' | 'customglb' | 'customrpm' | 'userAvatar' | 'avatar-configurator';
2
+ export declare const is3dAvatarWithUrl: (avatar: AvatarMode | string | undefined, avatarURL: string | undefined) => boolean;
3
+ export declare const usesRpmAvatarView: (avatar: AvatarMode | string | undefined) => boolean;
@@ -0,0 +1,11 @@
1
+ export const is3dAvatarWithUrl = (avatar, avatarURL) => !!avatarURL &&
2
+ (avatar === 'readyplayerme' ||
3
+ avatar === 'readyplayerme-full' ||
4
+ avatar === 'customglb' ||
5
+ avatar === 'customrpm' ||
6
+ avatar === 'avatar-configurator');
7
+ export const usesRpmAvatarView = (avatar) => avatar === 'readyplayerme' ||
8
+ avatar === 'readyplayerme-full' ||
9
+ avatar === 'customrpm' ||
10
+ avatar === 'avatar-configurator';
11
+ //# sourceMappingURL=integration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration.js","sourceRoot":"","sources":["../../src/types/integration.ts"],"names":[],"mappings":"AAYA,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,MAAuC,EACvC,SAA6B,EACpB,EAAE,CACX,CAAC,CAAC,SAAS;IACX,CAAC,MAAM,KAAK,eAAe;QACzB,MAAM,KAAK,oBAAoB;QAC/B,MAAM,KAAK,WAAW;QACtB,MAAM,KAAK,WAAW;QACtB,MAAM,KAAK,qBAAqB,CAAC,CAAC;AAGtC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,MAAuC,EAC9B,EAAE,CACX,MAAM,KAAK,eAAe;IAC1B,MAAM,KAAK,oBAAoB;IAC/B,MAAM,KAAK,WAAW;IACtB,MAAM,KAAK,qBAAqB,CAAC"}
package/esm/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "9.0.0-alpha.5";
1
+ export declare const version = "9.0.0-alpha.6";
package/esm/version.js CHANGED
@@ -1,2 +1,2 @@
1
- export const version = '9.0.0-alpha.5';
1
+ export const version = '9.0.0-alpha.6';
2
2
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "9.0.0-alpha.5",
2
+ "version": "9.0.0-alpha.6",
3
3
  "name": "@memori.ai/memori-react",
4
4
  "author": "Memori Srl",
5
5
  "main": "dist/index.js",
@@ -301,12 +301,14 @@
301
301
  "typescript": ">=4.8"
302
302
  },
303
303
  "dependencies": {
304
- "@memori.ai/memori-api-client": "6.22.0",
304
+ "@memori.ai/memori-api-client": "6.24.1",
305
305
  "@memori.ai/ui": "^1.16.1",
306
+ "@nats-io/jetstream": "^3.4.0",
307
+ "@nats-io/nats-core": "^3.4.0",
306
308
  "@react-three/drei": "8.20.2",
307
309
  "@react-three/fiber": "7.0.25",
308
310
  "classnames": "2.5.1",
309
- "dompurify": "^3.4.0",
311
+ "dompurify": "^3.4.12",
310
312
  "ellipsed": "1.6.0",
311
313
  "i18next": "22.0.6",
312
314
  "katex": "^0.16.11",
@@ -66,6 +66,10 @@ const AgeVerificationModal = ({ visible = false, onClose, minAge }: Props) => {
66
66
  setSubmitting(false);
67
67
  }, [add, birthDate, minAge, onClose, t]);
68
68
 
69
+ const handleDateChange = useCallback((date: DateTime | undefined) => {
70
+ setBirthDate(date);
71
+ }, []);
72
+
69
73
  return (
70
74
  <Modal
71
75
  open={visible}
@@ -93,8 +97,9 @@ const AgeVerificationModal = ({ visible = false, onClose, minAge }: Props) => {
93
97
  required
94
98
  >
95
99
  <DateSelector
100
+ minAge={minAge}
96
101
  onChange={date => {
97
- setBirthDate(date);
102
+ handleDateChange(date);
98
103
  setError(undefined);
99
104
  }}
100
105
  />
@@ -6,6 +6,7 @@ import Avatar, { Props } from './Avatar';
6
6
 
7
7
  import './Avatar.css';
8
8
  import { ArtifactProvider } from '../MemoriArtifactSystem/context/ArtifactContext';
9
+ import { VisemeProvider } from '../../context/visemeContext';
9
10
 
10
11
  const meta: Meta = {
11
12
  title: 'Widget/Avatar',
@@ -33,34 +34,38 @@ const Template: Story<Props> = args => {
33
34
 
34
35
  return (
35
36
  <I18nWrapper>
36
- <ArtifactProvider>
37
- <div
38
- style={
39
- args.integrationConfig?.avatar === 'customglb' ||
40
- args.integrationConfig?.avatar === 'readyplayerme' ||
41
- args.integrationConfig?.avatar === 'readyplayerme-full'
42
- ? {}
43
- : { marginTop: '20vw' }
44
- }
45
- >
46
- <Avatar
47
- {...args}
48
- integrationConfig={
49
- args.integrationConfig
50
- ? {
51
- ...args.integrationConfig,
52
- avatarURL:
53
- args.integrationConfig.avatarURL?.split('#')?.[0] +
54
- `#${new Date(Date.now()).toISOString()}`,
55
- }
56
- : undefined
57
- }
58
- avatar3dVisible={avatar3dVisible}
59
- setAvatar3dVisible={setAvatar3dVisible}
60
- key={Date.now()}
61
- />
62
- </div>
63
- </ArtifactProvider>
37
+ <VisemeProvider>
38
+ {' '}
39
+ <ArtifactProvider>
40
+ <div
41
+ style={
42
+ args.integrationConfig?.avatar === 'customglb' ||
43
+ args.integrationConfig?.avatar === 'readyplayerme' ||
44
+ args.integrationConfig?.avatar === 'readyplayerme-full' ||
45
+ args.integrationConfig?.avatar === 'avatar-configurator'
46
+ ? {}
47
+ : { marginTop: '20vw' }
48
+ }
49
+ >
50
+ <Avatar
51
+ {...args}
52
+ integrationConfig={
53
+ args.integrationConfig
54
+ ? {
55
+ ...args.integrationConfig,
56
+ avatarURL:
57
+ args.integrationConfig.avatarURL?.split('#')?.[0] +
58
+ `#${new Date(Date.now()).toISOString()}`,
59
+ }
60
+ : undefined
61
+ }
62
+ avatar3dVisible={avatar3dVisible}
63
+ setAvatar3dVisible={setAvatar3dVisible}
64
+ key={Date.now()}
65
+ />
66
+ </div>
67
+ </ArtifactProvider>
68
+ </VisemeProvider>
64
69
  </I18nWrapper>
65
70
  );
66
71
  };
@@ -141,3 +146,15 @@ FullbodyReadyPlayerMeAvatar.args = {
141
146
  'https://models.readyplayer.me/63b55751f17e295642bf07a2.glb#1669136149862',
142
147
  },
143
148
  };
149
+
150
+ export const AvatarConfigurator = Template.bind({});
151
+ AvatarConfigurator.args = {
152
+ ...FullbodyReadyPlayerMeAvatar.args,
153
+ integrationConfig: {
154
+ ...integrationConfig,
155
+ avatar: 'avatar-configurator',
156
+ avatarURL:
157
+ 'https://models.readyplayer.me/63b55751f17e295642bf07a2.glb#1669136149862',
158
+ },
159
+ avatarType: 'avatar3d',
160
+ };
@@ -102,3 +102,57 @@ it('renders Avatar with rpm 3d avatar unchanged', () => {
102
102
  );
103
103
  expect(container).toMatchSnapshot();
104
104
  });
105
+
106
+ it('renders Avatar with avatar-configurator like readyplayerme-full', () => {
107
+ const { container } = render(
108
+ <VisemeProvider>
109
+ <Avatar
110
+ memori={memori}
111
+ integration={integration}
112
+ isTotem={false}
113
+ setEnablePositionControls={() => {}}
114
+ integrationConfig={{
115
+ ...integrationConfig,
116
+ avatar: 'avatar-configurator',
117
+ avatarURL:
118
+ 'https://assets.memori.ai/api/v2/asset/b791f77c-1a94-4272-829e-eca82fcc62b7.glb',
119
+ }}
120
+ tenant={tenant}
121
+ instruct={false}
122
+ avatar3dVisible={true}
123
+ setAvatar3dVisible={() => {}}
124
+ hasUserActivatedSpeak={false}
125
+ isPlayingAudio={false}
126
+ avatarType="avatar3d"
127
+ />
128
+ </VisemeProvider>
129
+ );
130
+ expect(container).toMatchSnapshot();
131
+ });
132
+
133
+ it('renders Avatar with avatar-configurator on totem layout unchanged', () => {
134
+ const { container } = render(
135
+ <VisemeProvider>
136
+ <Avatar
137
+ memori={memori}
138
+ integration={integration}
139
+ isTotem
140
+ setEnablePositionControls={() => {}}
141
+ integrationConfig={{
142
+ ...integrationConfig,
143
+ avatar: 'avatar-configurator',
144
+ avatarURL:
145
+ 'https://assets.memori.ai/api/v2/asset/b791f77c-1a94-4272-829e-eca82fcc62b7.glb',
146
+ }}
147
+ tenant={tenant}
148
+ instruct={false}
149
+ avatar3dVisible={true}
150
+ setAvatar3dVisible={() => {}}
151
+ hasUserActivatedSpeak={false}
152
+ isPlayingAudio={false}
153
+ avatarType="avatar3d"
154
+ />
155
+ </VisemeProvider>
156
+ );
157
+ expect(container).toMatchSnapshot();
158
+ });
@@ -15,6 +15,7 @@ import { Eye, EyeOff, Pencil } from 'lucide-react';
15
15
  import cx from 'classnames';
16
16
  import ContainerAvatarView from './AvatarView';
17
17
  import { useViseme } from '../../context/visemeContext';
18
+ import { is3dAvatarWithUrl, usesRpmAvatarView } from '../../types/integration';
18
19
 
19
20
  export interface Props {
20
21
  memori: Memori;
@@ -88,11 +89,10 @@ const Avatar: React.FC<Props> = ({
88
89
 
89
90
  const renderAvatar = () => {
90
91
  if (
91
- (integrationConfig?.avatar === 'readyplayerme' ||
92
- integrationConfig?.avatar === 'readyplayerme-full' ||
93
- integrationConfig?.avatar === 'customglb' ||
94
- integrationConfig?.avatar === 'customrpm') &&
95
- integrationConfig?.avatarURL &&
92
+ is3dAvatarWithUrl(
93
+ integrationConfig?.avatar,
94
+ integrationConfig?.avatarURL
95
+ ) &&
96
96
  avatarType &&
97
97
  avatarType !== 'blob'
98
98
  ) {
@@ -121,12 +121,8 @@ const Avatar: React.FC<Props> = ({
121
121
  };
122
122
 
123
123
  const renderAvatarContent = () => {
124
- if (!isClient) return null;
125
- if (
126
- integrationConfig?.avatar === 'readyplayerme' ||
127
- integrationConfig?.avatar === 'readyplayerme-full' ||
128
- integrationConfig?.avatar === 'customrpm'
129
- ) {
124
+ if (!isClient || !integrationConfig) return null;
125
+ if (usesRpmAvatarView(integrationConfig.avatar)) {
130
126
  return (
131
127
  <ErrorBoundary
132
128
  fallback={
@@ -161,7 +157,7 @@ const Avatar: React.FC<Props> = ({
161
157
  );
162
158
  }
163
159
 
164
- if (integrationConfig?.avatar === 'customglb') {
160
+ if (integrationConfig.avatar === 'customglb') {
165
161
  return (
166
162
  <ModelViewer
167
163
  poster={getAvatarUrl() || ''}
@@ -9,6 +9,7 @@ import {
9
9
  ANIMATION_URLS,
10
10
  AVATAR_POSITION,
11
11
  AVATAR_ROTATION,
12
+ MALE_EXCLUDED_ANIMATIONS,
12
13
  SCALE_LERP_FACTOR,
13
14
  } from '../../constants';
14
15
  import DynamicShadow from '../../Shadow/DynamicShadow';
@@ -64,11 +65,17 @@ export function FullbodyAvatar({
64
65
  return found;
65
66
  }, [scene]);
66
67
 
67
- // Merge base and additional animations only if needed
68
- const mergedAnimations = useMemo(
69
- () => needsAdditionalAnimations ? [...baseAnimations, ...additionalAnimations] : baseAnimations,
70
- [baseAnimations, additionalAnimations, needsAdditionalAnimations]
71
- );
68
+ // Merge base and additional animations only if needed.
69
+ // For male avatars, exclude problematic idle clips from the full set (base + pack).
70
+ const mergedAnimations = useMemo(() => {
71
+ const clips = needsAdditionalAnimations
72
+ ? [...baseAnimations, ...additionalAnimations]
73
+ : baseAnimations;
74
+
75
+ if (sex !== 'MALE') return clips;
76
+
77
+ return clips.filter(clip => !MALE_EXCLUDED_ANIMATIONS.has(clip.name));
78
+ }, [baseAnimations, additionalAnimations, needsAdditionalAnimations, sex]);
72
79
 
73
80
  // Create animation actions from the merged animations
74
81
  const { actions } = useAnimations(mergedAnimations, scene);
@@ -2,6 +2,7 @@ import { SkinnedMesh } from 'three';
2
2
  import { MathUtils } from 'three';
3
3
  import {
4
4
  EMOTION_SMOOTHING,
5
+ EMOTION_INTENSITY,
5
6
  VISEME_SMOOTHING,
6
7
  BLINK_CONFIG,
7
8
  MAPPING_EMOTIONS_ITALIAN_TO_ENGLISH,
@@ -214,7 +215,7 @@ export class MorphTargetController {
214
215
  const currentEmotionValue = this.currentEmotionValues[key] || 0;
215
216
  const newEmotionValue = MathUtils.lerp(
216
217
  currentEmotionValue,
217
- targetEmotionValue * 1.5, // Apply emotion at 80% intensity for more natural expressions
218
+ targetEmotionValue * EMOTION_INTENSITY,
218
219
  EMOTION_SMOOTHING
219
220
  );
220
221
  this.currentEmotionValues[key] = newEmotionValue;
@@ -58,7 +58,8 @@ export const MAPPING_BLEND_SHAPE_TO_EMOTION_RPM: BlendShapeMap = [
58
58
  'browDownRight': 0.5,
59
59
  'browOuterUpLeft': 0.5,
60
60
  'browOuterUpRight': 0.5,
61
- 'mouthSmile': -0.2,
61
+ 'mouthSmileLeft': -0.2,
62
+ 'mouthSmileRight': -0.2,
62
63
  },
63
64
  },
64
65
  {
@@ -77,7 +78,8 @@ export const MAPPING_BLEND_SHAPE_TO_EMOTION_RPM: BlendShapeMap = [
77
78
  'browDownRight': -0.5,
78
79
  'eyeSquintLeft': 0.5,
79
80
  'eyeSquintRight': 0.5,
80
- 'mouthSmile': -0.6,
81
+ 'mouthSmileLeft': -0.6,
82
+ 'mouthSmileRight': -0.6,
81
83
  },
82
84
  },
83
85
  {
@@ -88,7 +90,8 @@ export const MAPPING_BLEND_SHAPE_TO_EMOTION_RPM: BlendShapeMap = [
88
90
  'browOuterUpRight': 0.5,
89
91
  'eyeWideLeft': 0.5,
90
92
  'eyeWideRight': 0.5,
91
- 'mouthSmile': 0.5,
93
+ 'mouthSmileLeft': 0.5,
94
+ 'mouthSmileRight': 0.5,
92
95
  },
93
96
  },
94
97
  {
@@ -97,7 +100,8 @@ export const MAPPING_BLEND_SHAPE_TO_EMOTION_RPM: BlendShapeMap = [
97
100
  'browDownLeft': 0.5,
98
101
  'browDownRight': 0.5,
99
102
  'browInnerUp': 0.5,
100
- 'mouthSmile': 0.5,
103
+ 'mouthSmileLeft': 0.5,
104
+ 'mouthSmileRight': 0.5,
101
105
  },
102
106
  },
103
107
  ];
@@ -109,6 +113,12 @@ export const ANIMATION_URLS = {
109
113
  'https://assets.memori.ai/api/v2/asset/2adc934b-24b2-45bd-94ad-ffec58d3cb32.glb',
110
114
  };
111
115
 
116
+ /** Idle clips excluded from the male animation pack. */
117
+ export const MALE_EXCLUDED_ANIMATIONS = new Set([
118
+ 'Idle',
119
+ 'Idle2'
120
+ ]);
121
+
112
122
  // Blink configuration
113
123
  export const BLINK_CONFIG = {
114
124
  minInterval: 1000,
@@ -127,3 +137,5 @@ export const DEFAULT_CONFIG: AnimationConfig = {
127
137
  // Smoothing factors for emotion and viseme morphs
128
138
  export const EMOTION_SMOOTHING = 0.3;
129
139
  export const VISEME_SMOOTHING = 0.5;
140
+ /** Multiplier applied to emotion morph target values before clamping (1 = raw mapping). */
141
+ export const EMOTION_INTENSITY = 2.5;
@@ -1,5 +1,169 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
+ exports[`renders Avatar with avatar-configurator like readyplayerme-full 1`] = `
4
+ <div>
5
+ <div
6
+ class="memori--avatar-wrapper memori--avatar-avatar-configurator"
7
+ >
8
+ <div
9
+ class="memori--blob-container"
10
+ >
11
+ <div
12
+ class="memori-blob"
13
+ >
14
+ <div
15
+ class="mainDiv"
16
+ />
17
+ <div
18
+ class="mainDiv"
19
+ />
20
+ <div
21
+ class="mainDiv"
22
+ />
23
+ <div
24
+ class="mainDiv"
25
+ />
26
+ <div
27
+ class="mainDiv"
28
+ />
29
+ </div>
30
+ </div>
31
+ </div>
32
+ <div
33
+ class="memori--avatar-toggle"
34
+ >
35
+ <button
36
+ aria-label="hide"
37
+ class="memori-button memori-button--ghost memori-button--md"
38
+ tabindex="0"
39
+ type="button"
40
+ >
41
+ <span
42
+ class="memori-button__icon"
43
+ >
44
+ <svg
45
+ aria-hidden="true"
46
+ class="lucide lucide-eye-off"
47
+ fill="none"
48
+ height="24"
49
+ stroke="currentColor"
50
+ stroke-linecap="round"
51
+ stroke-linejoin="round"
52
+ stroke-width="2"
53
+ viewBox="0 0 24 24"
54
+ width="24"
55
+ xmlns="http://www.w3.org/2000/svg"
56
+ >
57
+ <path
58
+ d="M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49"
59
+ />
60
+ <path
61
+ d="M14.084 14.158a3 3 0 0 1-4.242-4.242"
62
+ />
63
+ <path
64
+ d="M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143"
65
+ />
66
+ <path
67
+ d="m2 2 20 20"
68
+ />
69
+ </svg>
70
+ </span>
71
+ <span
72
+ class="memori-button__content"
73
+ >
74
+ <span
75
+ class="memori--avatar-toggle-text"
76
+ >
77
+ hide
78
+ </span>
79
+ </span>
80
+ </button>
81
+ </div>
82
+ </div>
83
+ `;
84
+
85
+ exports[`renders Avatar with avatar-configurator on totem layout unchanged 1`] = `
86
+ <div>
87
+ <div
88
+ class="memori--avatar-wrapper memori--avatar-avatar-configurator"
89
+ >
90
+ <div
91
+ class="memori--blob-container"
92
+ >
93
+ <div
94
+ class="memori-blob"
95
+ >
96
+ <div
97
+ class="mainDiv"
98
+ />
99
+ <div
100
+ class="mainDiv"
101
+ />
102
+ <div
103
+ class="mainDiv"
104
+ />
105
+ <div
106
+ class="mainDiv"
107
+ />
108
+ <div
109
+ class="mainDiv"
110
+ />
111
+ </div>
112
+ </div>
113
+ </div>
114
+ <div
115
+ class="memori--avatar-toggle"
116
+ >
117
+ <button
118
+ aria-label="hide"
119
+ class="memori-button memori-button--ghost memori-button--md"
120
+ tabindex="0"
121
+ type="button"
122
+ >
123
+ <span
124
+ class="memori-button__icon"
125
+ >
126
+ <svg
127
+ aria-hidden="true"
128
+ class="lucide lucide-eye-off"
129
+ fill="none"
130
+ height="24"
131
+ stroke="currentColor"
132
+ stroke-linecap="round"
133
+ stroke-linejoin="round"
134
+ stroke-width="2"
135
+ viewBox="0 0 24 24"
136
+ width="24"
137
+ xmlns="http://www.w3.org/2000/svg"
138
+ >
139
+ <path
140
+ d="M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49"
141
+ />
142
+ <path
143
+ d="M14.084 14.158a3 3 0 0 1-4.242-4.242"
144
+ />
145
+ <path
146
+ d="M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143"
147
+ />
148
+ <path
149
+ d="m2 2 20 20"
150
+ />
151
+ </svg>
152
+ </span>
153
+ <span
154
+ class="memori-button__content"
155
+ >
156
+ <span
157
+ class="memori--avatar-toggle-text"
158
+ >
159
+ hide
160
+ </span>
161
+ </span>
162
+ </button>
163
+ </div>
164
+ </div>
165
+ `;
166
+
3
167
  exports[`renders Avatar with blob and avatar in blob unchanged 1`] = `
4
168
  <div>
5
169
  <div
@@ -129,13 +129,16 @@ const ChatBubble: React.FC<Props> = ({
129
129
  const [copyStatus, setCopyStatus] = useState<{
130
130
  plain: 'idle' | 'success' | 'error';
131
131
  raw: 'idle' | 'success' | 'error';
132
- }>({ plain: 'idle', raw: 'idle' });
132
+ functionCache: 'idle' | 'success' | 'error';
133
+ }>({ plain: 'idle', raw: 'idle', functionCache: 'idle' });
133
134
  const copyResetTimers = useRef<{
134
135
  plain: ReturnType<typeof setTimeout> | null;
135
136
  raw: ReturnType<typeof setTimeout> | null;
137
+ functionCache: ReturnType<typeof setTimeout> | null;
136
138
  }>({
137
139
  plain: null,
138
140
  raw: null,
141
+ functionCache: null,
139
142
  });
140
143
  // Initialize MathJax on component mount
141
144
  useEffect(() => {
@@ -244,26 +247,33 @@ const ChatBubble: React.FC<Props> = ({
244
247
 
245
248
  useEffect(() => {
246
249
  return () => {
247
- (Object.keys(copyResetTimers.current) as Array<'plain' | 'raw'>).forEach(
248
- key => {
249
- const timer = copyResetTimers.current[key];
250
- if (timer) {
251
- clearTimeout(timer);
252
- copyResetTimers.current[key] = null;
253
- }
250
+ (
251
+ Object.keys(copyResetTimers.current) as Array<
252
+ 'plain' | 'raw' | 'functionCache'
253
+ >
254
+ ).forEach(key => {
255
+ const timer = copyResetTimers.current[key];
256
+ if (timer) {
257
+ clearTimeout(timer);
258
+ copyResetTimers.current[key] = null;
254
259
  }
255
- );
260
+ });
256
261
  };
257
262
  }, []);
258
263
 
259
- const clearCopyReset = (type: 'plain' | 'raw') => {
264
+ const functionCacheCopyText =
265
+ functionCacheData
266
+ ?.map(f => `${f.title}\n\n${f.content}`)
267
+ .join('\n\n---\n\n') ?? '';
268
+
269
+ const clearCopyReset = (type: 'plain' | 'raw' | 'functionCache') => {
260
270
  if (copyResetTimers.current[type]) {
261
271
  clearTimeout(copyResetTimers.current[type]!);
262
272
  copyResetTimers.current[type] = null;
263
273
  }
264
274
  };
265
275
 
266
- const scheduleCopyReset = (type: 'plain' | 'raw') => {
276
+ const scheduleCopyReset = (type: 'plain' | 'raw' | 'functionCache') => {
267
277
  clearCopyReset(type);
268
278
  copyResetTimers.current[type] = setTimeout(() => {
269
279
  setCopyStatus(prev => ({ ...prev, [type]: 'idle' }));
@@ -271,7 +281,10 @@ const ChatBubble: React.FC<Props> = ({
271
281
  }, COPY_FEEDBACK_MS);
272
282
  };
273
283
 
274
- const handleCopyClick = async (type: 'plain' | 'raw', text: string) => {
284
+ const handleCopyClick = async (
285
+ type: 'plain' | 'raw' | 'functionCache',
286
+ text: string
287
+ ) => {
275
288
  if (!text?.length) return;
276
289
  try {
277
290
  if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) {
@@ -827,6 +840,18 @@ const ChatBubble: React.FC<Props> = ({
827
840
  closable={true}
828
841
  onOpenChange={setOpenFunctionCache}
829
842
  >
843
+ <div style={{ marginBottom: '1rem' }}>
844
+ <Button
845
+ icon={<Copy aria-hidden />}
846
+ onClick={() =>
847
+ handleCopyClick('functionCache', functionCacheCopyText)
848
+ }
849
+ >
850
+ {copyStatus.functionCache === 'success'
851
+ ? copiedLabel
852
+ : t('copy') || 'Copy'}
853
+ </Button>
854
+ </div>
830
855
  {functionCacheData?.map((f, i) => (
831
856
  <div
832
857
  key={f.mediumID}
@@ -33,17 +33,21 @@ const PROVIDER_CONFIGS: Record<string, ProviderConfig> = {
33
33
  statusPage: 'https://status.mistral-data.com/',
34
34
  apiComponentName: ['Mistral'],
35
35
  },
36
+ // Use status.claude.com directly: status.anthropic.com 302-redirects and
37
+ // browsers block the redirected response (missing CORS on the redirect).
36
38
  Anthropic: {
37
- statusUrl: 'https://status.anthropic.com/api/v2/summary.json',
38
- statusPage: 'https://status.anthropic.com/',
39
- apiComponentName: ['api.anthropic.com'],
39
+ statusUrl: 'https://status.claude.com/api/v2/summary.json',
40
+ statusPage: 'https://status.claude.com/',
41
+ apiComponentName: [
42
+ 'Claude API (api.anthropic.com)',
43
+ 'api.anthropic.com',
44
+ ],
40
45
  },
41
46
  };
42
47
 
43
48
  // Modified to handle fetch errors, different component names, and check incidents
44
49
  const fetchProviderStatus = async (config: ProviderConfig): Promise<Status> => {
45
50
  try {
46
- // Use cross-fetch instead of native fetch
47
51
  const response = await fetch(config.statusUrl);
48
52
  if (!response.ok) {
49
53
  console.warn(`Status API returned ${response.status}`);