@memori.ai/memori-react 8.8.5 → 8.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/README.md +28 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +0 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +0 -10
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js +0 -9
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js.map +1 -1
- package/dist/components/Chat/Chat.css +31 -0
- package/dist/components/Chat/Chat.js +18 -4
- package/dist/components/Chat/Chat.js.map +1 -1
- package/dist/components/ChatBubble/ChatBubble.js +1 -2
- package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
- package/dist/components/ChatInputs/ChatInputs.css +23 -0
- package/dist/components/ChatInputs/ChatInputs.d.ts +1 -0
- package/dist/components/ChatInputs/ChatInputs.js +37 -21
- package/dist/components/ChatInputs/ChatInputs.js.map +1 -1
- package/dist/components/ChatTextArea/ChatTextArea.css +31 -0
- package/dist/components/ChatTextArea/ChatTextArea.d.ts +1 -0
- package/dist/components/ChatTextArea/ChatTextArea.js +9 -2
- package/dist/components/ChatTextArea/ChatTextArea.js.map +1 -1
- package/dist/components/FilePreview/FilePreview.css +39 -0
- package/dist/components/Header/Header.js +3 -16
- package/dist/components/Header/Header.js.map +1 -1
- package/dist/components/MediaWidget/LinkItemWidget.js +1 -1
- package/dist/components/MediaWidget/LinkItemWidget.js.map +1 -1
- package/dist/components/MediaWidget/MediaItemWidget.js +5 -9
- package/dist/components/MediaWidget/MediaItemWidget.js.map +1 -1
- package/dist/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.js +65 -51
- package/dist/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.js.map +1 -1
- package/dist/components/MemoriArtifactSystem/utils/ArtifactAPI.d.ts +5 -0
- package/dist/components/MemoriArtifactSystem/utils/ArtifactAPI.js +287 -0
- package/dist/components/MemoriArtifactSystem/utils/ArtifactAPI.js.map +1 -0
- package/dist/components/MemoriWidget/MemoriWidget.d.ts +12 -0
- package/dist/components/MemoriWidget/MemoriWidget.js +12 -3
- package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/dist/components/Snippet/Snippet.js +4 -3
- package/dist/components/Snippet/Snippet.js.map +1 -1
- package/dist/components/StartPanel/StartPanel.css +14 -0
- package/dist/components/StartPanel/StartPanel.js +2 -2
- package/dist/components/StartPanel/StartPanel.js.map +1 -1
- package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js +0 -21
- package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
- package/dist/components/VenueWidget/VenueWidget.js +0 -1
- package/dist/components/VenueWidget/VenueWidget.js.map +1 -1
- package/dist/components/layouts/HiddenChat.js +0 -15
- package/dist/components/layouts/HiddenChat.js.map +1 -1
- package/dist/components/layouts/chat.css +2 -2
- package/dist/context/visemeContext.js +0 -6
- package/dist/context/visemeContext.js.map +1 -1
- package/dist/helpers/constants.d.ts +11 -0
- package/dist/helpers/constants.js +24 -2
- package/dist/helpers/constants.js.map +1 -1
- package/dist/helpers/tts/useTTS.js +0 -3
- package/dist/helpers/tts/useTTS.js.map +1 -1
- package/dist/helpers/utils.d.ts +1 -0
- package/dist/helpers/utils.js +6 -1
- package/dist/helpers/utils.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/locales/de.json +2 -0
- package/dist/locales/en.json +2 -0
- package/dist/locales/es.json +2 -0
- package/dist/locales/fr.json +2 -0
- package/dist/locales/it.json +2 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +0 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js +0 -10
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js +0 -9
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.js.map +1 -1
- package/esm/components/Chat/Chat.css +31 -0
- package/esm/components/Chat/Chat.js +19 -5
- package/esm/components/Chat/Chat.js.map +1 -1
- package/esm/components/ChatBubble/ChatBubble.js +1 -2
- package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
- package/esm/components/ChatInputs/ChatInputs.css +23 -0
- package/esm/components/ChatInputs/ChatInputs.d.ts +1 -0
- package/esm/components/ChatInputs/ChatInputs.js +37 -21
- package/esm/components/ChatInputs/ChatInputs.js.map +1 -1
- package/esm/components/ChatTextArea/ChatTextArea.css +31 -0
- package/esm/components/ChatTextArea/ChatTextArea.d.ts +1 -0
- package/esm/components/ChatTextArea/ChatTextArea.js +9 -2
- package/esm/components/ChatTextArea/ChatTextArea.js.map +1 -1
- package/esm/components/FilePreview/FilePreview.css +39 -0
- package/esm/components/Header/Header.js +3 -16
- package/esm/components/Header/Header.js.map +1 -1
- package/esm/components/MediaWidget/LinkItemWidget.js +1 -1
- package/esm/components/MediaWidget/LinkItemWidget.js.map +1 -1
- package/esm/components/MediaWidget/MediaItemWidget.js +5 -9
- package/esm/components/MediaWidget/MediaItemWidget.js.map +1 -1
- package/esm/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.js +65 -51
- package/esm/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.js.map +1 -1
- package/esm/components/MemoriArtifactSystem/utils/ArtifactAPI.d.ts +5 -0
- package/esm/components/MemoriArtifactSystem/utils/ArtifactAPI.js +282 -0
- package/esm/components/MemoriArtifactSystem/utils/ArtifactAPI.js.map +1 -0
- package/esm/components/MemoriWidget/MemoriWidget.d.ts +12 -0
- package/esm/components/MemoriWidget/MemoriWidget.js +12 -3
- package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/esm/components/Snippet/Snippet.js +4 -3
- package/esm/components/Snippet/Snippet.js.map +1 -1
- package/esm/components/StartPanel/StartPanel.css +14 -0
- package/esm/components/StartPanel/StartPanel.js +3 -3
- package/esm/components/StartPanel/StartPanel.js.map +1 -1
- package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js +0 -21
- package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
- package/esm/components/VenueWidget/VenueWidget.js +0 -1
- package/esm/components/VenueWidget/VenueWidget.js.map +1 -1
- package/esm/components/layouts/HiddenChat.js +0 -15
- package/esm/components/layouts/HiddenChat.js.map +1 -1
- package/esm/components/layouts/chat.css +2 -2
- package/esm/context/visemeContext.js +0 -6
- package/esm/context/visemeContext.js.map +1 -1
- package/esm/helpers/constants.d.ts +11 -0
- package/esm/helpers/constants.js +22 -1
- package/esm/helpers/constants.js.map +1 -1
- package/esm/helpers/tts/useTTS.js +0 -3
- package/esm/helpers/tts/useTTS.js.map +1 -1
- package/esm/helpers/utils.d.ts +1 -0
- package/esm/helpers/utils.js +4 -0
- package/esm/helpers/utils.js.map +1 -1
- package/esm/index.js.map +1 -1
- package/esm/locales/de.json +2 -0
- package/esm/locales/en.json +2 -0
- package/esm/locales/es.json +2 -0
- package/esm/locales/fr.json +2 -0
- package/esm/locales/it.json +2 -0
- package/package.json +1 -1
- package/src/components/Avatar/AvatarView/AvatarComponent/avatarComponent.tsx +0 -1
- package/src/components/Avatar/AvatarView/AvatarComponent/components/FullbodyAvatar/fullbodyAvatar.tsx +0 -17
- package/src/components/Avatar/AvatarView/AvatarComponent/components/controllers/AvatarAnimator.ts +0 -20
- package/src/components/Chat/Chat.css +31 -0
- package/src/components/Chat/Chat.stories.tsx +503 -9
- package/src/components/Chat/Chat.tsx +23 -3
- package/src/components/Chat/__snapshots__/Chat.test.tsx.snap +73 -73
- package/src/components/ChatBubble/ChatBubble.tsx +1 -2
- package/src/components/ChatBubble/__snapshots__/ChatBubble.test.tsx.snap +25 -25
- package/src/components/ChatInputs/ChatInputs.css +23 -0
- package/src/components/ChatInputs/ChatInputs.tsx +36 -14
- package/src/components/ChatTextArea/ChatTextArea.css +31 -0
- package/src/components/ChatTextArea/ChatTextArea.tsx +11 -1
- package/src/components/FilePreview/FilePreview.css +39 -0
- package/src/components/Header/Header.tsx +0 -13
- package/src/components/MediaWidget/LinkItemWidget.tsx +1 -1
- package/src/components/MediaWidget/MediaItemWidget.stories.tsx +33 -0
- package/src/components/MediaWidget/MediaItemWidget.tsx +7 -10
- package/src/components/MediaWidget/__snapshots__/LinkItemWidget.test.tsx.snap +4 -4
- package/src/components/MediaWidget/__snapshots__/MediaItemWidget.test.tsx.snap +6 -6
- package/src/components/MediaWidget/__snapshots__/MediaWidget.test.tsx.snap +2 -2
- package/src/components/MemoriArtifactSystem/ArtifactDrawer.stories.tsx +766 -2
- package/src/components/MemoriArtifactSystem/components/ArtifactHandler/ArtifactHandler.tsx +103 -89
- package/src/components/MemoriArtifactSystem/utils/ArtifactAPI.test.tsx +307 -0
- package/src/components/MemoriArtifactSystem/utils/ArtifactAPI.tsx +373 -0
- package/src/components/MemoriWidget/MemoriWidget.tsx +26 -4
- package/src/components/Snippet/Snippet.tsx +3 -2
- package/src/components/StartPanel/StartPanel.css +14 -0
- package/src/components/StartPanel/StartPanel.tsx +23 -10
- package/src/components/StartPanel/__snapshots__/StartPanel.test.tsx.snap +206 -84
- package/src/components/UploadButton/UploadDocuments/UploadDocuments.tsx +0 -23
- package/src/components/VenueWidget/VenueWidget.tsx +0 -1
- package/src/components/layouts/HiddenChat.tsx +0 -16
- package/src/components/layouts/__snapshots__/Chat.test.tsx.snap +204 -82
- package/src/components/layouts/__snapshots__/FullPage.test.tsx.snap +408 -164
- package/src/components/layouts/__snapshots__/HiddenChat.test.tsx.snap +204 -82
- package/src/components/layouts/__snapshots__/Totem.test.tsx.snap +204 -82
- package/src/components/layouts/__snapshots__/ZoomedFullBody.test.tsx.snap +204 -82
- package/src/components/layouts/chat.css +2 -2
- package/src/context/visemeContext.tsx +0 -7
- package/src/helpers/constants.ts +28 -3
- package/src/helpers/tts/useTTS.ts +0 -2
- package/src/helpers/utils.ts +5 -0
- package/src/index.tsx +0 -1
- package/src/locales/de.json +2 -0
- package/src/locales/en.json +2 -0
- package/src/locales/es.json +2 -0
- package/src/locales/fr.json +2 -0
- package/src/locales/it.json +2 -0
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import { useArtifact } from '../context/ArtifactContext';
|
|
3
|
+
import type { ArtifactData } from '../types/artifact.types';
|
|
4
|
+
import { Message } from '@memori.ai/memori-api-client/dist/types';
|
|
5
|
+
|
|
6
|
+
// Queue for calls made before the component is ready
|
|
7
|
+
const pendingCalls: Array<{ method: string; args: any[] }> = [];
|
|
8
|
+
let isReady = false;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Initialize the MemoriArtifactAPI stub on window
|
|
12
|
+
* This should be called as early as possible to prevent "undefined" errors
|
|
13
|
+
*/
|
|
14
|
+
export const initMemoriArtifactAPI = () => {
|
|
15
|
+
if (typeof window === 'undefined') return;
|
|
16
|
+
|
|
17
|
+
// Only initialize if not already present
|
|
18
|
+
if ((window as any).MemoriArtifactAPI) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
(window as any).MemoriArtifactAPI = {
|
|
23
|
+
_isReady: () => isReady,
|
|
24
|
+
_setReady: (ready: boolean) => { isReady = ready; },
|
|
25
|
+
_getPendingCalls: () => pendingCalls,
|
|
26
|
+
_clearPendingCalls: () => { pendingCalls.length = 0; },
|
|
27
|
+
|
|
28
|
+
openArtifact: (artifact: ArtifactData) => {
|
|
29
|
+
if (!isReady) {
|
|
30
|
+
pendingCalls.push({ method: 'openArtifact', args: [artifact] });
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
createAndOpenArtifact: (content: string, mimeType?: string, title?: string) => {
|
|
34
|
+
if (!isReady) {
|
|
35
|
+
pendingCalls.push({ method: 'createAndOpenArtifact', args: [content, mimeType, title] });
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
createFromOutputElement: (outputElement: HTMLOutputElement) => {
|
|
39
|
+
if (!isReady) {
|
|
40
|
+
pendingCalls.push({ method: 'createFromOutputElement', args: [outputElement] });
|
|
41
|
+
return 'pending';
|
|
42
|
+
}
|
|
43
|
+
return 'not-ready';
|
|
44
|
+
},
|
|
45
|
+
closeArtifact: () => {
|
|
46
|
+
if (!isReady) {
|
|
47
|
+
pendingCalls.push({ method: 'closeArtifact', args: [] });
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
toggleFullscreen: () => {
|
|
51
|
+
if (!isReady) {
|
|
52
|
+
pendingCalls.push({ method: 'toggleFullscreen', args: [] });
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
getState: () => {
|
|
56
|
+
if (!isReady) {
|
|
57
|
+
return { currentArtifact: null, isDrawerOpen: false, isFullscreen: false };
|
|
58
|
+
}
|
|
59
|
+
return { currentArtifact: null, isDrawerOpen: false, isFullscreen: false };
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Initialize immediately when this module is loaded
|
|
65
|
+
initMemoriArtifactAPI();
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Componente che espone le funzioni dell'Artifact System come API globale
|
|
69
|
+
* Questo permette di controllare gli artifacts da JavaScript vanilla esterno
|
|
70
|
+
*/
|
|
71
|
+
export const ArtifactAPIBridge = ({
|
|
72
|
+
pushMessage,
|
|
73
|
+
}: {
|
|
74
|
+
pushMessage: (message: Message) => void;
|
|
75
|
+
}) => {
|
|
76
|
+
const { openArtifact, closeArtifact, toggleFullscreen, state } =
|
|
77
|
+
useArtifact();
|
|
78
|
+
|
|
79
|
+
const apiRef = useRef<any>(null);
|
|
80
|
+
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
// Update API with actual implementations
|
|
83
|
+
if (typeof window !== 'undefined') {
|
|
84
|
+
const windowApi = (window as any).MemoriArtifactAPI;
|
|
85
|
+
|
|
86
|
+
// Store reference to actual implementations
|
|
87
|
+
apiRef.current = {
|
|
88
|
+
/**
|
|
89
|
+
* Apri un artifact esistente
|
|
90
|
+
* @param artifact - Oggetto ArtifactData completo
|
|
91
|
+
*/
|
|
92
|
+
openArtifact: (artifact: ArtifactData) => {
|
|
93
|
+
openArtifact(artifact);
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Crea e apri un artifact con parametri semplici
|
|
98
|
+
* @param content - Contenuto dell'artifact (HTML, markdown, ecc.)
|
|
99
|
+
* @param mimeType - Tipo MIME (default: 'html')
|
|
100
|
+
* @param title - Titolo da mostrare (default: auto-generato)
|
|
101
|
+
*/
|
|
102
|
+
createAndOpenArtifact: (
|
|
103
|
+
content: string,
|
|
104
|
+
mimeType: string = 'html',
|
|
105
|
+
title?: string
|
|
106
|
+
) => {
|
|
107
|
+
const autoTitle = title || getTitleFromMimeType(mimeType);
|
|
108
|
+
|
|
109
|
+
// Create the artifact object
|
|
110
|
+
const artifact: ArtifactData = {
|
|
111
|
+
id: `artifact-${Date.now()}-${Math.random()
|
|
112
|
+
.toString(36)
|
|
113
|
+
.substr(2, 9)}`,
|
|
114
|
+
content,
|
|
115
|
+
mimeType,
|
|
116
|
+
title: autoTitle,
|
|
117
|
+
timestamp: new Date(),
|
|
118
|
+
size: content.length,
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// Create wrapped message text for artifact detection
|
|
122
|
+
// Don't reassign content parameter - use a new variable
|
|
123
|
+
let messageText = content;
|
|
124
|
+
if (!messageText.includes('<output class="memori-artifact">')) {
|
|
125
|
+
messageText = `<output class="memori-artifact" data-mimetype="${mimeType}" data-title="${autoTitle}">${content}</output>`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
//we have to push in the history the artifact as message
|
|
129
|
+
pushMessage({
|
|
130
|
+
text: messageText,
|
|
131
|
+
timestamp: new Date().toISOString(),
|
|
132
|
+
fromUser: false as const,
|
|
133
|
+
media: [],
|
|
134
|
+
initial: false,
|
|
135
|
+
translatedText: undefined,
|
|
136
|
+
questionAnswered: undefined,
|
|
137
|
+
generatedByAI: false,
|
|
138
|
+
contextVars: undefined,
|
|
139
|
+
date: undefined,
|
|
140
|
+
placeName: undefined,
|
|
141
|
+
placeLatitude: undefined,
|
|
142
|
+
placeLongitude: undefined,
|
|
143
|
+
placeUncertaintyKm: undefined,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Open the artifact immediately
|
|
147
|
+
openArtifact(artifact);
|
|
148
|
+
},
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Crea un artifact da un elemento <output> esistente nel DOM
|
|
152
|
+
* @param outputElement - Elemento DOM <output class="memori-artifact">
|
|
153
|
+
* @returns artifactId
|
|
154
|
+
*/
|
|
155
|
+
createFromOutputElement: (outputElement: HTMLOutputElement) => {
|
|
156
|
+
const content = outputElement.innerHTML;
|
|
157
|
+
const mimeType =
|
|
158
|
+
outputElement.getAttribute('data-mimetype') || 'html';
|
|
159
|
+
const title =
|
|
160
|
+
outputElement.getAttribute('data-title') ||
|
|
161
|
+
getTitleFromMimeType(mimeType);
|
|
162
|
+
|
|
163
|
+
// Nascondi l'elemento originale
|
|
164
|
+
outputElement.style.display = 'none';
|
|
165
|
+
outputElement.setAttribute('data-memori-processed', 'true');
|
|
166
|
+
|
|
167
|
+
const artifact: ArtifactData = {
|
|
168
|
+
id: `artifact-${Date.now()}-${Math.random()
|
|
169
|
+
.toString(36)
|
|
170
|
+
.substr(2, 9)}`,
|
|
171
|
+
content,
|
|
172
|
+
mimeType,
|
|
173
|
+
title,
|
|
174
|
+
timestamp: new Date(),
|
|
175
|
+
size: content.length,
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// Create wrapped message text for artifact detection
|
|
179
|
+
// Don't reassign content - use a new variable
|
|
180
|
+
let messageText = content;
|
|
181
|
+
if (!messageText.includes('<output class="memori-artifact">')) {
|
|
182
|
+
messageText = `<output class="memori-artifact" data-mimetype="${mimeType}" data-title="${title}">${content}</output>`;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
pushMessage({
|
|
186
|
+
text: messageText,
|
|
187
|
+
timestamp: new Date().toISOString(),
|
|
188
|
+
fromUser: false as const,
|
|
189
|
+
media: [],
|
|
190
|
+
initial: false,
|
|
191
|
+
translatedText: undefined,
|
|
192
|
+
questionAnswered: undefined,
|
|
193
|
+
generatedByAI: false,
|
|
194
|
+
contextVars: undefined,
|
|
195
|
+
date: undefined,
|
|
196
|
+
placeName: undefined,
|
|
197
|
+
placeLatitude: undefined,
|
|
198
|
+
placeLongitude: undefined,
|
|
199
|
+
placeUncertaintyKm: undefined,
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Open the artifact immediately
|
|
203
|
+
openArtifact(artifact);
|
|
204
|
+
|
|
205
|
+
return artifact.id;
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Chiudi l'artifact drawer corrente
|
|
210
|
+
*/
|
|
211
|
+
closeArtifact: () => {
|
|
212
|
+
closeArtifact();
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Toggle fullscreen dell'artifact drawer
|
|
217
|
+
*/
|
|
218
|
+
toggleFullscreen: () => {
|
|
219
|
+
toggleFullscreen();
|
|
220
|
+
},
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Ottieni lo stato corrente del sistema artifacts
|
|
224
|
+
*/
|
|
225
|
+
getState: () => {
|
|
226
|
+
return {
|
|
227
|
+
currentArtifact: state.currentArtifact,
|
|
228
|
+
isDrawerOpen: state.isDrawerOpen,
|
|
229
|
+
isFullscreen: state.isFullscreen,
|
|
230
|
+
};
|
|
231
|
+
},
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
// Update window API methods to use the real implementations
|
|
235
|
+
if (windowApi) {
|
|
236
|
+
windowApi.openArtifact = apiRef.current.openArtifact;
|
|
237
|
+
windowApi.createAndOpenArtifact = apiRef.current.createAndOpenArtifact;
|
|
238
|
+
windowApi.createFromOutputElement = apiRef.current.createFromOutputElement;
|
|
239
|
+
windowApi.closeArtifact = apiRef.current.closeArtifact;
|
|
240
|
+
windowApi.toggleFullscreen = apiRef.current.toggleFullscreen;
|
|
241
|
+
windowApi.getState = apiRef.current.getState;
|
|
242
|
+
|
|
243
|
+
// Mark API as ready
|
|
244
|
+
windowApi._setReady(true);
|
|
245
|
+
|
|
246
|
+
// Process any pending calls that were queued before ready
|
|
247
|
+
const pendingCalls = windowApi._getPendingCalls();
|
|
248
|
+
if (pendingCalls.length > 0) {
|
|
249
|
+
pendingCalls.forEach((call: { method: string; args: any[] }) => {
|
|
250
|
+
try {
|
|
251
|
+
const method = (apiRef.current as any)[call.method];
|
|
252
|
+
if (method) {
|
|
253
|
+
method(...call.args);
|
|
254
|
+
}
|
|
255
|
+
} catch (error) {
|
|
256
|
+
// Swallow error, remove log
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
windowApi._clearPendingCalls();
|
|
260
|
+
}
|
|
261
|
+
} else {
|
|
262
|
+
// If windowApi doesn't exist yet, initialize it now
|
|
263
|
+
(window as any).MemoriArtifactAPI = {
|
|
264
|
+
...apiRef.current,
|
|
265
|
+
_isReady: true,
|
|
266
|
+
_pendingCalls: [],
|
|
267
|
+
_setReady: (ready: boolean) => {
|
|
268
|
+
(window as any).MemoriArtifactAPI._isReady = ready;
|
|
269
|
+
},
|
|
270
|
+
_getPendingCalls: () => {
|
|
271
|
+
return (window as any).MemoriArtifactAPI._pendingCalls;
|
|
272
|
+
},
|
|
273
|
+
_clearPendingCalls: () => {
|
|
274
|
+
(window as any).MemoriArtifactAPI._pendingCalls = [];
|
|
275
|
+
},
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return () => {
|
|
281
|
+
// Clean up the API on unmount
|
|
282
|
+
if (typeof window !== 'undefined') {
|
|
283
|
+
delete (window as any).MemoriArtifactAPI;
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
}, [openArtifact, closeArtifact, toggleFullscreen, state, pushMessage]);
|
|
287
|
+
|
|
288
|
+
return null;
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
// Helper functions
|
|
292
|
+
function getTitleFromMimeType(mimeType: string): string {
|
|
293
|
+
if (mimeType.includes('html')) return 'HTML Document';
|
|
294
|
+
if (mimeType.includes('markdown')) return 'Markdown Document';
|
|
295
|
+
if (mimeType.includes('javascript')) return 'JavaScript Code';
|
|
296
|
+
if (mimeType.includes('python')) return 'Python Code';
|
|
297
|
+
if (mimeType.includes('json')) return 'JSON Data';
|
|
298
|
+
if (mimeType.includes('css')) return 'CSS Stylesheet';
|
|
299
|
+
if (mimeType.includes('typescript')) return 'TypeScript Code';
|
|
300
|
+
if (mimeType.includes('xml')) return 'XML Document';
|
|
301
|
+
if (mimeType.includes('svg')) return 'SVG Image';
|
|
302
|
+
return 'Document';
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function createArtifactHandler(
|
|
306
|
+
content: string,
|
|
307
|
+
mimeType: string,
|
|
308
|
+
title: string
|
|
309
|
+
): HTMLDivElement {
|
|
310
|
+
const handler = document.createElement('div');
|
|
311
|
+
handler.className = 'memori-artifact-handler';
|
|
312
|
+
handler.style.cssText = `
|
|
313
|
+
display: flex;
|
|
314
|
+
align-items: center;
|
|
315
|
+
gap: 12px;
|
|
316
|
+
padding: 16px;
|
|
317
|
+
margin: 12px 0;
|
|
318
|
+
background: white;
|
|
319
|
+
border: 1px solid #e5e7eb;
|
|
320
|
+
border-radius: 12px;
|
|
321
|
+
cursor: pointer;
|
|
322
|
+
transition: all 0.2s ease;
|
|
323
|
+
`;
|
|
324
|
+
|
|
325
|
+
const icon = getIconForMimeType(mimeType);
|
|
326
|
+
const size = `${(content.length / 1024).toFixed(1)} KB`;
|
|
327
|
+
|
|
328
|
+
handler.innerHTML = `
|
|
329
|
+
<div style="font-size: 32px;">${icon}</div>
|
|
330
|
+
<div style="flex: 1;">
|
|
331
|
+
<div style="font-weight: 600; margin-bottom: 4px;">${escapeHtml(
|
|
332
|
+
title
|
|
333
|
+
)}</div>
|
|
334
|
+
<div style="font-size: 13px; color: #6b7280;">${mimeType} • ${size}</div>
|
|
335
|
+
</div>
|
|
336
|
+
<div>
|
|
337
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
338
|
+
<polyline points="9 18 15 12 9 6"></polyline>
|
|
339
|
+
</svg>
|
|
340
|
+
</div>
|
|
341
|
+
`;
|
|
342
|
+
|
|
343
|
+
handler.addEventListener('mouseenter', () => {
|
|
344
|
+
handler.style.background = '#faf5ff';
|
|
345
|
+
handler.style.borderColor = '#9333ea';
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
handler.addEventListener('mouseleave', () => {
|
|
349
|
+
handler.style.background = 'white';
|
|
350
|
+
handler.style.borderColor = '#e5e7eb';
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
return handler;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function getIconForMimeType(mimeType: string): string {
|
|
357
|
+
if (mimeType.includes('html')) return '🌐';
|
|
358
|
+
if (mimeType.includes('markdown')) return '📝';
|
|
359
|
+
if (mimeType.includes('javascript') || mimeType.includes('typescript'))
|
|
360
|
+
return '📜';
|
|
361
|
+
if (mimeType.includes('python')) return '🐍';
|
|
362
|
+
if (mimeType.includes('json')) return '📊';
|
|
363
|
+
if (mimeType.includes('css')) return '🎨';
|
|
364
|
+
if (mimeType.includes('xml')) return '📋';
|
|
365
|
+
if (mimeType.includes('svg')) return '🖼️';
|
|
366
|
+
return '📄';
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function escapeHtml(text: string): string {
|
|
370
|
+
const div = document.createElement('div');
|
|
371
|
+
div.textContent = text;
|
|
372
|
+
return div.innerHTML;
|
|
373
|
+
}
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
ChatLog,
|
|
18
18
|
} from '@memori.ai/memori-api-client/src/types';
|
|
19
19
|
import { ArtifactData } from '../MemoriArtifactSystem/types/artifact.types';
|
|
20
|
+
import { ArtifactAPIBridge } from '../MemoriArtifactSystem/utils/ArtifactAPI';
|
|
20
21
|
|
|
21
22
|
// Libraries
|
|
22
23
|
import React, {
|
|
@@ -320,6 +321,18 @@ declare global {
|
|
|
320
321
|
typeMessage: typeof typeMessage;
|
|
321
322
|
typeMessageHidden: typeof typeMessageHidden;
|
|
322
323
|
typeBatchMessages: typeof typeBatchMessages;
|
|
324
|
+
MemoriArtifactAPI?: {
|
|
325
|
+
openArtifact: (artifact: ArtifactData) => void;
|
|
326
|
+
createAndOpenArtifact: (content: string, mimeType?: string, title?: string) => void;
|
|
327
|
+
createFromOutputElement: (outputElement: HTMLOutputElement) => string;
|
|
328
|
+
closeArtifact: () => void;
|
|
329
|
+
toggleFullscreen: () => void;
|
|
330
|
+
getState: () => {
|
|
331
|
+
currentArtifact: ArtifactData | null;
|
|
332
|
+
isDrawerOpen: boolean;
|
|
333
|
+
isFullscreen: boolean
|
|
334
|
+
};
|
|
335
|
+
};
|
|
323
336
|
}
|
|
324
337
|
}
|
|
325
338
|
window.getMemoriState = getMemoriState;
|
|
@@ -1725,7 +1738,6 @@ const MemoriWidget = ({
|
|
|
1725
1738
|
|
|
1726
1739
|
if (isVisible && !isTabVisible) {
|
|
1727
1740
|
// Tab became visible - start polling and send immediate date event
|
|
1728
|
-
console.log('Tab is now active/visible - starting date polling');
|
|
1729
1741
|
sendDateChangedEvent({
|
|
1730
1742
|
sessionID: sessionId,
|
|
1731
1743
|
state: currentDialogState,
|
|
@@ -1733,7 +1745,6 @@ const MemoriWidget = ({
|
|
|
1733
1745
|
startDatePolling();
|
|
1734
1746
|
} else if (!isVisible && isTabVisible) {
|
|
1735
1747
|
// Tab became hidden - stop polling
|
|
1736
|
-
console.log('Tab is now hidden - stopping date polling');
|
|
1737
1748
|
stopDatePolling();
|
|
1738
1749
|
}
|
|
1739
1750
|
|
|
@@ -1974,7 +1985,6 @@ const MemoriWidget = ({
|
|
|
1974
1985
|
]
|
|
1975
1986
|
);
|
|
1976
1987
|
|
|
1977
|
-
|
|
1978
1988
|
const focusChatInput = () => {
|
|
1979
1989
|
let textarea = document.querySelector(
|
|
1980
1990
|
'#chat-fieldset textarea'
|
|
@@ -2901,7 +2911,8 @@ const MemoriWidget = ({
|
|
|
2901
2911
|
layout,
|
|
2902
2912
|
memoriTyping,
|
|
2903
2913
|
typingText,
|
|
2904
|
-
showTypingText:
|
|
2914
|
+
showTypingText:
|
|
2915
|
+
showTypingText ?? integrationConfig?.showTypingText ?? false,
|
|
2905
2916
|
history: showFullHistory ? history : history.slice(-2),
|
|
2906
2917
|
authToken:
|
|
2907
2918
|
loginToken ?? userToken ?? additionalInfo?.loginToken ?? authToken,
|
|
@@ -3045,6 +3056,17 @@ const MemoriWidget = ({
|
|
|
3045
3056
|
loading={loading}
|
|
3046
3057
|
/>
|
|
3047
3058
|
|
|
3059
|
+
<ArtifactAPIBridge pushMessage={(message: Message) => {
|
|
3060
|
+
setHistory(history => {
|
|
3061
|
+
if (!history.length) return history;
|
|
3062
|
+
const lastMessage = history[history.length - 1];
|
|
3063
|
+
if (!lastMessage || lastMessage.fromUser) return history;
|
|
3064
|
+
// Create a new message object with the updated text
|
|
3065
|
+
const updatedLastMessage = { ...lastMessage, text: lastMessage.text + message.text };
|
|
3066
|
+
return [...history.slice(0, -1), updatedLastMessage];
|
|
3067
|
+
});
|
|
3068
|
+
}} />
|
|
3069
|
+
|
|
3048
3070
|
<audio
|
|
3049
3071
|
id="memori-audio"
|
|
3050
3072
|
style={{ display: 'none' }}
|
|
@@ -5,6 +5,7 @@ import Copy from '../icons/Copy';
|
|
|
5
5
|
import { prismSyntaxLangs } from '../../helpers/constants';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
import cx from 'classnames';
|
|
8
|
+
import { stripDocumentAttachmentTags, stripOutputTags } from '../../helpers/utils';
|
|
8
9
|
|
|
9
10
|
export interface Props {
|
|
10
11
|
medium: Medium;
|
|
@@ -107,8 +108,8 @@ const Snippet = ({
|
|
|
107
108
|
}
|
|
108
109
|
>
|
|
109
110
|
{medium.content?.length && medium.content.length > 200 && preview
|
|
110
|
-
? `${medium.content
|
|
111
|
-
:
|
|
111
|
+
? `${stripDocumentAttachmentTags(medium.content)?.slice(0, 200)}\n...`
|
|
112
|
+
: stripDocumentAttachmentTags(medium.content ?? '')}
|
|
112
113
|
</code>
|
|
113
114
|
</pre>
|
|
114
115
|
|
|
@@ -155,6 +155,20 @@
|
|
|
155
155
|
color: #000;
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
.memori--language-chooser select optgroup {
|
|
159
|
+
background: #fff;
|
|
160
|
+
color: #666;
|
|
161
|
+
font-size: 0.9em;
|
|
162
|
+
font-style: normal;
|
|
163
|
+
font-weight: 700;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.memori--language-chooser select optgroup option {
|
|
167
|
+
padding-left: 0.5rem;
|
|
168
|
+
color: #000;
|
|
169
|
+
font-weight: 400;
|
|
170
|
+
}
|
|
171
|
+
|
|
158
172
|
.memori--completions-enabled,
|
|
159
173
|
.memori--board-of-experts,
|
|
160
174
|
.memori--nsfw {
|
|
@@ -11,7 +11,7 @@ import Tooltip from '../ui/Tooltip';
|
|
|
11
11
|
import { getTranslation } from '../../helpers/translations';
|
|
12
12
|
import Button from '../ui/Button';
|
|
13
13
|
import Translation from '../icons/Translation';
|
|
14
|
-
import {
|
|
14
|
+
import { getGroupedChatLanguages } from '../../helpers/constants';
|
|
15
15
|
import BlockedMemoriBadge from '../BlockedMemoriBadge/BlockedMemoriBadge';
|
|
16
16
|
import AI from '../icons/AI';
|
|
17
17
|
import Group from '../icons/Group';
|
|
@@ -259,15 +259,28 @@ const StartPanel: React.FC<Props> = ({
|
|
|
259
259
|
setUserLang(e.target.value);
|
|
260
260
|
}}
|
|
261
261
|
>
|
|
262
|
-
{
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
262
|
+
<optgroup label={t('popularLanguages') || 'Popular'}>
|
|
263
|
+
{getGroupedChatLanguages().popular.map(lang => (
|
|
264
|
+
<option
|
|
265
|
+
key={`popular-${lang.value}`}
|
|
266
|
+
value={lang.value}
|
|
267
|
+
aria-label={lang.label}
|
|
268
|
+
>
|
|
269
|
+
{lang.label}
|
|
270
|
+
</option>
|
|
271
|
+
))}
|
|
272
|
+
</optgroup>
|
|
273
|
+
<optgroup label={t('allLanguages') || 'All Languages'}>
|
|
274
|
+
{getGroupedChatLanguages().all.map(lang => (
|
|
275
|
+
<option
|
|
276
|
+
key={`all-${lang.value}`}
|
|
277
|
+
value={lang.value}
|
|
278
|
+
aria-label={lang.label}
|
|
279
|
+
>
|
|
280
|
+
{lang.label}
|
|
281
|
+
</option>
|
|
282
|
+
))}
|
|
283
|
+
</optgroup>
|
|
271
284
|
</select>
|
|
272
285
|
</div>
|
|
273
286
|
)}
|