@memori.ai/memori-react 8.41.6 → 8.43.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.
Files changed (240) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/components/Chat/Chat.js +1 -1
  3. package/dist/components/Chat/Chat.js.map +1 -1
  4. package/dist/components/ChatHistoryDrawer/ChatResumeDrawer.css +372 -0
  5. package/dist/components/ChatHistoryDrawer/ChatResumeDrawer.d.ts +36 -0
  6. package/dist/components/ChatHistoryDrawer/ChatResumeDrawer.js +116 -0
  7. package/dist/components/ChatHistoryDrawer/ChatResumeDrawer.js.map +1 -0
  8. package/dist/components/ChatInputs/ChatInputs.d.ts +1 -0
  9. package/dist/components/ChatInputs/ChatInputs.js +2 -2
  10. package/dist/components/ChatInputs/ChatInputs.js.map +1 -1
  11. package/dist/components/DrawerFooter/DrawerFooter.css +62 -0
  12. package/dist/components/DrawerFooter/DrawerFooter.d.ts +12 -0
  13. package/dist/components/DrawerFooter/DrawerFooter.js +10 -0
  14. package/dist/components/DrawerFooter/DrawerFooter.js.map +1 -0
  15. package/dist/components/IconButton/IconButton.css +144 -0
  16. package/dist/components/IconButton/IconButton.d.ts +9 -0
  17. package/dist/components/IconButton/IconButton.js +36 -0
  18. package/dist/components/IconButton/IconButton.js.map +1 -0
  19. package/dist/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js +1 -1
  20. package/dist/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js.map +1 -1
  21. package/dist/components/MobileSessionPanel/MobileSessionPanel.css +459 -0
  22. package/dist/components/MobileSessionPanel/MobileSessionPanel.d.ts +65 -0
  23. package/dist/components/MobileSessionPanel/MobileSessionPanel.js +294 -0
  24. package/dist/components/MobileSessionPanel/MobileSessionPanel.js.map +1 -0
  25. package/dist/components/PositionPopover/PositionPopover.css +219 -0
  26. package/dist/components/PositionPopover/PositionPopover.d.ts +22 -0
  27. package/dist/components/PositionPopover/PositionPopover.js +195 -0
  28. package/dist/components/PositionPopover/PositionPopover.js.map +1 -0
  29. package/dist/components/UploadButton/UploadButton.d.ts +1 -0
  30. package/dist/components/UploadButton/UploadButton.js +12 -18
  31. package/dist/components/UploadButton/UploadButton.js.map +1 -1
  32. package/dist/components/UploadButton/UploadDocuments/UploadDocuments.d.ts +1 -6
  33. package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js +7 -139
  34. package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
  35. package/dist/components/icons/Print.js +1 -1
  36. package/dist/components/icons/Print.js.map +1 -1
  37. package/dist/components/layouts/WebsiteAssistant/WebsiteAssistant.d.ts +4 -0
  38. package/dist/components/layouts/WebsiteAssistant/WebsiteAssistant.js +64 -0
  39. package/dist/components/layouts/WebsiteAssistant/WebsiteAssistant.js.map +1 -0
  40. package/dist/components/layouts/WebsiteAssistant/website-assistant.css +806 -0
  41. package/dist/components/layouts/fullpage.css +522 -0
  42. package/dist/context/widgetSurfaceContext.d.ts +3 -0
  43. package/dist/context/widgetSurfaceContext.js +11 -0
  44. package/dist/context/widgetSurfaceContext.js.map +1 -0
  45. package/dist/helpers/constants.d.ts +1 -0
  46. package/dist/helpers/constants.js +24 -1
  47. package/dist/helpers/constants.js.map +1 -1
  48. package/dist/helpers/convertDocument.d.ts +1 -0
  49. package/dist/helpers/convertDocument.js +24 -0
  50. package/dist/helpers/convertDocument.js.map +1 -0
  51. package/dist/helpers/media.js +18 -3
  52. package/dist/helpers/media.js.map +1 -1
  53. package/dist/helpers/positionPopover.d.ts +1 -0
  54. package/dist/helpers/positionPopover.js +7 -0
  55. package/dist/helpers/positionPopover.js.map +1 -0
  56. package/dist/helpers/tts/muteSpeaker.d.ts +13 -0
  57. package/dist/helpers/tts/muteSpeaker.js +26 -0
  58. package/dist/helpers/tts/muteSpeaker.js.map +1 -0
  59. package/dist/helpers/usePressTooltip.d.ts +13 -0
  60. package/dist/helpers/usePressTooltip.js +23 -0
  61. package/dist/helpers/usePressTooltip.js.map +1 -0
  62. package/dist/icons/FacebookIcon.d.ts +3 -0
  63. package/dist/icons/FacebookIcon.js +6 -0
  64. package/dist/icons/FacebookIcon.js.map +1 -0
  65. package/dist/icons/LinkedinIcon.d.ts +3 -0
  66. package/dist/icons/LinkedinIcon.js +6 -0
  67. package/dist/icons/LinkedinIcon.js.map +1 -0
  68. package/dist/icons/MemoriIcon.d.ts +3 -0
  69. package/dist/icons/MemoriIcon.js +8 -0
  70. package/dist/icons/MemoriIcon.js.map +1 -0
  71. package/dist/icons/TelegramIcon.d.ts +3 -0
  72. package/dist/icons/TelegramIcon.js +6 -0
  73. package/dist/icons/TelegramIcon.js.map +1 -0
  74. package/dist/icons/TwitterIcon.d.ts +3 -0
  75. package/dist/icons/TwitterIcon.js +6 -0
  76. package/dist/icons/TwitterIcon.js.map +1 -0
  77. package/dist/icons/WhatsappIcon.d.ts +3 -0
  78. package/dist/icons/WhatsappIcon.js +6 -0
  79. package/dist/icons/WhatsappIcon.js.map +1 -0
  80. package/dist/icons/artifacts/DocumentIcon.d.ts +3 -0
  81. package/dist/icons/artifacts/DocumentIcon.js +6 -0
  82. package/dist/icons/artifacts/DocumentIcon.js.map +1 -0
  83. package/dist/icons/artifacts/HtmlIcon.d.ts +3 -0
  84. package/dist/icons/artifacts/HtmlIcon.js +6 -0
  85. package/dist/icons/artifacts/HtmlIcon.js.map +1 -0
  86. package/dist/icons/artifacts/JavascriptIcon.d.ts +3 -0
  87. package/dist/icons/artifacts/JavascriptIcon.js +6 -0
  88. package/dist/icons/artifacts/JavascriptIcon.js.map +1 -0
  89. package/dist/icons/artifacts/MarkdownIcon.d.ts +3 -0
  90. package/dist/icons/artifacts/MarkdownIcon.js +6 -0
  91. package/dist/icons/artifacts/MarkdownIcon.js.map +1 -0
  92. package/dist/icons/artifacts/PythonIcon.d.ts +3 -0
  93. package/dist/icons/artifacts/PythonIcon.js +6 -0
  94. package/dist/icons/artifacts/PythonIcon.js.map +1 -0
  95. package/dist/icons/artifacts/SvgIcon.d.ts +3 -0
  96. package/dist/icons/artifacts/SvgIcon.js +6 -0
  97. package/dist/icons/artifacts/SvgIcon.js.map +1 -0
  98. package/dist/icons/artifacts/XmlIcon.d.ts +3 -0
  99. package/dist/icons/artifacts/XmlIcon.js +6 -0
  100. package/dist/icons/artifacts/XmlIcon.js.map +1 -0
  101. package/dist/icons/artifacts/cssIcon.d.ts +3 -0
  102. package/dist/icons/artifacts/cssIcon.js +6 -0
  103. package/dist/icons/artifacts/cssIcon.js.map +1 -0
  104. package/dist/testUtils.d.ts +5 -0
  105. package/dist/testUtils.js +18 -0
  106. package/dist/testUtils.js.map +1 -0
  107. package/dist/version.d.ts +1 -1
  108. package/dist/version.js +1 -1
  109. package/esm/components/Chat/Chat.js +1 -1
  110. package/esm/components/Chat/Chat.js.map +1 -1
  111. package/esm/components/ChatHistoryDrawer/ChatResumeDrawer.css +372 -0
  112. package/esm/components/ChatHistoryDrawer/ChatResumeDrawer.d.ts +36 -0
  113. package/esm/components/ChatHistoryDrawer/ChatResumeDrawer.js +113 -0
  114. package/esm/components/ChatHistoryDrawer/ChatResumeDrawer.js.map +1 -0
  115. package/esm/components/ChatInputs/ChatInputs.d.ts +1 -0
  116. package/esm/components/ChatInputs/ChatInputs.js +2 -2
  117. package/esm/components/ChatInputs/ChatInputs.js.map +1 -1
  118. package/esm/components/DrawerFooter/DrawerFooter.css +62 -0
  119. package/esm/components/DrawerFooter/DrawerFooter.d.ts +12 -0
  120. package/esm/components/DrawerFooter/DrawerFooter.js +8 -0
  121. package/esm/components/DrawerFooter/DrawerFooter.js.map +1 -0
  122. package/esm/components/IconButton/IconButton.css +144 -0
  123. package/esm/components/IconButton/IconButton.d.ts +9 -0
  124. package/esm/components/IconButton/IconButton.js +33 -0
  125. package/esm/components/IconButton/IconButton.js.map +1 -0
  126. package/esm/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js +2 -2
  127. package/esm/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.js.map +1 -1
  128. package/esm/components/MobileSessionPanel/MobileSessionPanel.css +459 -0
  129. package/esm/components/MobileSessionPanel/MobileSessionPanel.d.ts +65 -0
  130. package/esm/components/MobileSessionPanel/MobileSessionPanel.js +291 -0
  131. package/esm/components/MobileSessionPanel/MobileSessionPanel.js.map +1 -0
  132. package/esm/components/PositionPopover/PositionPopover.css +219 -0
  133. package/esm/components/PositionPopover/PositionPopover.d.ts +22 -0
  134. package/esm/components/PositionPopover/PositionPopover.js +190 -0
  135. package/esm/components/PositionPopover/PositionPopover.js.map +1 -0
  136. package/esm/components/UploadButton/UploadButton.d.ts +1 -0
  137. package/esm/components/UploadButton/UploadButton.js +13 -19
  138. package/esm/components/UploadButton/UploadButton.js.map +1 -1
  139. package/esm/components/UploadButton/UploadDocuments/UploadDocuments.d.ts +1 -6
  140. package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js +8 -140
  141. package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
  142. package/esm/components/icons/Print.js +1 -1
  143. package/esm/components/icons/Print.js.map +1 -1
  144. package/esm/components/layouts/WebsiteAssistant/WebsiteAssistant.d.ts +4 -0
  145. package/esm/components/layouts/WebsiteAssistant/WebsiteAssistant.js +61 -0
  146. package/esm/components/layouts/WebsiteAssistant/WebsiteAssistant.js.map +1 -0
  147. package/esm/components/layouts/WebsiteAssistant/website-assistant.css +806 -0
  148. package/esm/components/layouts/fullpage.css +522 -0
  149. package/esm/context/widgetSurfaceContext.d.ts +3 -0
  150. package/esm/context/widgetSurfaceContext.js +7 -0
  151. package/esm/context/widgetSurfaceContext.js.map +1 -0
  152. package/esm/helpers/constants.d.ts +1 -0
  153. package/esm/helpers/constants.js +23 -0
  154. package/esm/helpers/constants.js.map +1 -1
  155. package/esm/helpers/convertDocument.d.ts +1 -0
  156. package/esm/helpers/convertDocument.js +20 -0
  157. package/esm/helpers/convertDocument.js.map +1 -0
  158. package/esm/helpers/media.js +18 -3
  159. package/esm/helpers/media.js.map +1 -1
  160. package/esm/helpers/positionPopover.d.ts +1 -0
  161. package/esm/helpers/positionPopover.js +4 -0
  162. package/esm/helpers/positionPopover.js.map +1 -0
  163. package/esm/helpers/tts/muteSpeaker.d.ts +13 -0
  164. package/esm/helpers/tts/muteSpeaker.js +21 -0
  165. package/esm/helpers/tts/muteSpeaker.js.map +1 -0
  166. package/esm/helpers/usePressTooltip.d.ts +13 -0
  167. package/esm/helpers/usePressTooltip.js +20 -0
  168. package/esm/helpers/usePressTooltip.js.map +1 -0
  169. package/esm/icons/FacebookIcon.d.ts +3 -0
  170. package/esm/icons/FacebookIcon.js +4 -0
  171. package/esm/icons/FacebookIcon.js.map +1 -0
  172. package/esm/icons/LinkedinIcon.d.ts +3 -0
  173. package/esm/icons/LinkedinIcon.js +4 -0
  174. package/esm/icons/LinkedinIcon.js.map +1 -0
  175. package/esm/icons/MemoriIcon.d.ts +3 -0
  176. package/esm/icons/MemoriIcon.js +6 -0
  177. package/esm/icons/MemoriIcon.js.map +1 -0
  178. package/esm/icons/TelegramIcon.d.ts +3 -0
  179. package/esm/icons/TelegramIcon.js +4 -0
  180. package/esm/icons/TelegramIcon.js.map +1 -0
  181. package/esm/icons/TwitterIcon.d.ts +3 -0
  182. package/esm/icons/TwitterIcon.js +4 -0
  183. package/esm/icons/TwitterIcon.js.map +1 -0
  184. package/esm/icons/WhatsappIcon.d.ts +3 -0
  185. package/esm/icons/WhatsappIcon.js +4 -0
  186. package/esm/icons/WhatsappIcon.js.map +1 -0
  187. package/esm/icons/artifacts/DocumentIcon.d.ts +3 -0
  188. package/esm/icons/artifacts/DocumentIcon.js +4 -0
  189. package/esm/icons/artifacts/DocumentIcon.js.map +1 -0
  190. package/esm/icons/artifacts/HtmlIcon.d.ts +3 -0
  191. package/esm/icons/artifacts/HtmlIcon.js +4 -0
  192. package/esm/icons/artifacts/HtmlIcon.js.map +1 -0
  193. package/esm/icons/artifacts/JavascriptIcon.d.ts +3 -0
  194. package/esm/icons/artifacts/JavascriptIcon.js +4 -0
  195. package/esm/icons/artifacts/JavascriptIcon.js.map +1 -0
  196. package/esm/icons/artifacts/MarkdownIcon.d.ts +3 -0
  197. package/esm/icons/artifacts/MarkdownIcon.js +4 -0
  198. package/esm/icons/artifacts/MarkdownIcon.js.map +1 -0
  199. package/esm/icons/artifacts/PythonIcon.d.ts +3 -0
  200. package/esm/icons/artifacts/PythonIcon.js +4 -0
  201. package/esm/icons/artifacts/PythonIcon.js.map +1 -0
  202. package/esm/icons/artifacts/SvgIcon.d.ts +3 -0
  203. package/esm/icons/artifacts/SvgIcon.js +4 -0
  204. package/esm/icons/artifacts/SvgIcon.js.map +1 -0
  205. package/esm/icons/artifacts/XmlIcon.d.ts +3 -0
  206. package/esm/icons/artifacts/XmlIcon.js +4 -0
  207. package/esm/icons/artifacts/XmlIcon.js.map +1 -0
  208. package/esm/icons/artifacts/cssIcon.d.ts +3 -0
  209. package/esm/icons/artifacts/cssIcon.js +4 -0
  210. package/esm/icons/artifacts/cssIcon.js.map +1 -0
  211. package/esm/testUtils.d.ts +5 -0
  212. package/esm/testUtils.js +15 -0
  213. package/esm/testUtils.js.map +1 -0
  214. package/esm/version.d.ts +1 -1
  215. package/esm/version.js +1 -1
  216. package/package.json +2 -2
  217. package/src/components/Chat/Chat.tsx +1 -0
  218. package/src/components/Chat/__snapshots__/Chat.test.tsx.snap +10 -10
  219. package/src/components/ChatInputs/ChatInputs.tsx +3 -0
  220. package/src/components/FilePreview/FilePreview.stories.tsx +0 -3
  221. package/src/components/MemoriArtifactSystem/components/ArtifactPreview/ArtifactPreview.tsx +2 -2
  222. package/src/components/UploadButton/UploadButton.stories.tsx +2 -2
  223. package/src/components/UploadButton/UploadButton.tsx +19 -19
  224. package/src/components/UploadButton/UploadDocuments/UploadDocuments.tsx +13 -187
  225. package/src/components/UploadButton/__snapshots__/UploadButton.test.tsx.snap +2 -2
  226. package/src/components/icons/Print.tsx +6 -2
  227. package/src/helpers/constants.ts +24 -0
  228. package/src/helpers/convertDocument.test.ts +67 -0
  229. package/src/helpers/convertDocument.ts +35 -0
  230. package/src/helpers/media.test.ts +36 -0
  231. package/src/helpers/media.ts +39 -12
  232. package/src/version.ts +1 -1
  233. package/dist/components/MemoriArtifactSystem/utils/applyEdits.d.ts +0 -8
  234. package/dist/components/MemoriArtifactSystem/utils/applyEdits.js +0 -117
  235. package/dist/components/MemoriArtifactSystem/utils/applyEdits.js.map +0 -1
  236. package/dist/helpers/nats/natsBundled.js +0 -13224
  237. package/esm/components/MemoriArtifactSystem/utils/applyEdits.d.ts +0 -8
  238. package/esm/components/MemoriArtifactSystem/utils/applyEdits.js +0 -112
  239. package/esm/components/MemoriArtifactSystem/utils/applyEdits.js.map +0 -1
  240. package/esm/helpers/nats/natsBundled.js +0 -13225
@@ -9,13 +9,17 @@ import UploadDocuments from './UploadDocuments/UploadDocuments';
9
9
  import UploadImages from './UploadImages/UploadImages';
10
10
  import { useTranslation } from 'react-i18next';
11
11
  import memoriApiClient from '@memori.ai/memori-api-client';
12
- import { officeNativeExtensions } from '../../helpers/constants';
12
+ import {
13
+ documentConversionExtensions,
14
+ officeNativeExtensions,
15
+ } from '../../helpers/constants';
13
16
  import Tooltip from '../ui/Tooltip';
14
17
  // Props interface
15
18
  interface UploadManagerProps {
16
19
  authToken?: string;
17
20
  client?: ReturnType<typeof memoriApiClient>;
18
21
  sessionID?: string;
22
+ baseUrl?: string;
19
23
  isMediaAccepted?: boolean;
20
24
  setDocumentPreviewFiles: any;
21
25
  documentPreviewFiles: {
@@ -40,6 +44,7 @@ const UploadButton: React.FC<UploadManagerProps> = ({
40
44
  authToken = '',
41
45
  client,
42
46
  sessionID = '',
47
+ baseUrl = '',
43
48
  isMediaAccepted = false,
44
49
  setDocumentPreviewFiles,
45
50
  documentPreviewFiles,
@@ -101,14 +106,8 @@ const UploadButton: React.FC<UploadManagerProps> = ({
101
106
 
102
107
  // Check if file is a document
103
108
  const isDocumentFile = (file: File): boolean => {
104
- const documentExtensions = [
105
- '.pdf',
106
- '.txt',
107
- '.json',
108
- '.xlsx',
109
- '.csv',
110
- '.md',
111
- '.html',
109
+ const documentExtensions: readonly string[] = [
110
+ ...documentConversionExtensions,
112
111
  ...officeNativeExtensions,
113
112
  ];
114
113
  const fileExt = `.${file.name.split('.').pop()?.toLowerCase()}`;
@@ -453,17 +452,11 @@ ${file.textAssetUrl || ''}
453
452
  // Document validation and error handling
454
453
  const validateDocumentFile = (file: File): boolean => {
455
454
  const fileExt = `.${file.name.split('.').pop()?.toLowerCase()}`;
456
- const ALLOWED_FILE_TYPES = [
457
- '.pdf',
458
- '.txt',
459
- '.json',
460
- '.xlsx',
461
- '.csv',
462
- '.md',
463
- '.html',
455
+ const ALLOWED_FILE_TYPES: readonly string[] = [
456
+ ...documentConversionExtensions,
464
457
  ...officeNativeExtensions,
465
458
  ];
466
- const MAX_FILE_SIZE = 15 * 1024 * 1024; // 15MB
459
+ const MAX_FILE_SIZE = 25 * 1024 * 1024;
467
460
 
468
461
  if (!ALLOWED_FILE_TYPES.includes(fileExt)) {
469
462
  addError({
@@ -578,7 +571,13 @@ ${file.textAssetUrl || ''}
578
571
  <input
579
572
  ref={unifiedInputRef}
580
573
  type="file"
581
- accept={`.jpg,.jpeg,.png,.pdf,.txt,.json,.xlsx,.csv,.md,.html,${officeNativeExtensions.join(',')}`}
574
+ accept={[
575
+ '.jpg',
576
+ '.jpeg',
577
+ '.png',
578
+ ...documentConversionExtensions,
579
+ ...officeNativeExtensions,
580
+ ].join(',')}
582
581
  multiple
583
582
  className="memori--upload-file-input"
584
583
  onChange={handleFileInputChange}
@@ -634,6 +633,7 @@ ${file.textAssetUrl || ''}
634
633
  authToken={authToken}
635
634
  client={client}
636
635
  sessionID={sessionID}
636
+ baseUrl={baseUrl}
637
637
  memoriID={memoriID}
638
638
  maxDocuments={maxDocumentsPerMessage}
639
639
  documentPreviewFiles={documentPreviewFiles}
@@ -5,8 +5,12 @@ import { DocumentIcon } from '../../icons/Document';
5
5
  import Modal from '../../ui/Modal';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import memoriApiClient from '@memori.ai/memori-api-client';
8
- import { officeNativeExtensions } from '../../../helpers/constants';
8
+ import {
9
+ documentConversionExtensions,
10
+ officeNativeExtensions,
11
+ } from '../../../helpers/constants';
9
12
  import { isOfficeNativeFilename } from '../../../helpers/utils';
13
+ import { convertDocument } from '../../../helpers/convertDocument';
10
14
  // Types
11
15
  type PreviewFile = {
12
16
  name: string;
@@ -18,21 +22,6 @@ type PreviewFile = {
18
22
  error?: boolean;
19
23
  };
20
24
 
21
- // Constants
22
- const PDF_JS_VERSION = '3.11.174';
23
- const WORKER_URL = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${PDF_JS_VERSION}/pdf.worker.min.js`;
24
- const PDF_JS_URL = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${PDF_JS_VERSION}/pdf.min.js`;
25
- const XLSX_URL =
26
- 'https://cdn.sheetjs.com/xlsx-0.20.0/package/dist/xlsx.full.min.js';
27
-
28
- // Add type definitions for external libraries
29
- declare global {
30
- interface Window {
31
- pdfjsLib: any;
32
- XLSX: any;
33
- }
34
- }
35
-
36
25
  // Props interface
37
26
  interface UploadDocumentsProps {
38
27
  setDocumentPreviewFiles: (
@@ -47,6 +36,7 @@ interface UploadDocumentsProps {
47
36
  authToken?: string;
48
37
  client?: ReturnType<typeof memoriApiClient>;
49
38
  sessionID?: string;
39
+ baseUrl?: string;
50
40
  memoriID?: string;
51
41
  maxDocuments?: number;
52
42
  documentPreviewFiles: any;
@@ -71,6 +61,7 @@ const UploadDocuments: React.FC<UploadDocumentsProps> = ({
71
61
  authToken = '',
72
62
  client,
73
63
  sessionID = '',
64
+ baseUrl = '',
74
65
  memoriID = '',
75
66
  maxDocuments,
76
67
  documentPreviewFiles,
@@ -123,182 +114,19 @@ const UploadDocuments: React.FC<UploadDocumentsProps> = ({
123
114
  return { valid: true };
124
115
  };
125
116
 
126
- const extractTextFromPDF = async (file: File): Promise<string> => {
127
- try {
128
- // Load PDF.js if not already loaded
129
- if (!window.pdfjsLib) {
130
- await new Promise((resolve, reject) => {
131
- const script = document.createElement('script');
132
- script.src = PDF_JS_URL;
133
- script.onload = () => {
134
- window.pdfjsLib.GlobalWorkerOptions.workerSrc = WORKER_URL;
135
- resolve(true);
136
- };
137
- script.onerror = reject;
138
- document.head.appendChild(script);
139
- });
140
- }
141
-
142
- // Extract text from PDF
143
- const arrayBuffer = await file.arrayBuffer();
144
- const pdf = await window.pdfjsLib.getDocument({ data: arrayBuffer })
145
- .promise;
146
- let text = '';
147
-
148
- // Iterate through each page and extract text
149
- for (let i = 1; i <= pdf.numPages; i++) {
150
- const page = await pdf.getPage(i);
151
- const content = await page.getTextContent();
152
- const pageText = content.items
153
- .filter((item: any) => item.str && typeof item.str === 'string')
154
- .map((item: any) => item.str)
155
- .join(' ');
156
- text += pageText + '\n';
157
- }
158
-
159
- return text;
160
- } catch (error) {
161
- console.error('PDF extraction failed:', error);
162
- throw new Error(
163
- `PDF extraction failed: ${
164
- error instanceof Error ? error.message : 'Unknown error'
165
- }`
166
- );
167
- }
168
- };
169
-
170
- const loadXLSXLibrary = async (): Promise<void> => {
171
- if (window.XLSX) return;
172
-
173
- await new Promise((resolve, reject) => {
174
- const script = document.createElement('script');
175
- script.src = XLSX_URL;
176
- script.onload = resolve;
177
- script.onerror = reject;
178
- document.head.appendChild(script);
179
- });
180
- };
181
-
182
- const readXLSXWorkbook = async (file: File) => {
183
- await loadXLSXLibrary();
184
-
185
- const arrayBuffer = await file.arrayBuffer();
186
- return window.XLSX.read(arrayBuffer, {
187
- type: 'array',
188
- cellFormula: true,
189
- cellNF: true,
190
- cellText: true,
191
- cellDates: true,
192
- });
193
- };
194
-
195
- const formatXLSXWorkbookForDisplay = (workbook: {
196
- SheetNames: string[];
197
- Sheets: Record<string, unknown>;
198
- }): string => {
199
- let text = '';
200
-
201
- for (const sheetName of workbook.SheetNames) {
202
- const worksheet = workbook.Sheets[sheetName];
203
- const data = window.XLSX.utils.sheet_to_json(worksheet, {
204
- header: 1,
205
- raw: false,
206
- });
207
-
208
- const colWidths = data.reduce((widths: number[], row: any[]) => {
209
- row.forEach((cell, i) => {
210
- const cellWidth = (cell || '').toString().length;
211
- widths[i] = Math.max(widths[i] || 0, cellWidth);
212
- });
213
- return widths;
214
- }, []);
215
-
216
- const formattedText = data.map((row: any[]) => {
217
- return row
218
- .map((cell, i) => {
219
- const cellStr = (cell || '').toString();
220
- return cellStr.padEnd(colWidths[i] + 2);
221
- })
222
- .join('|')
223
- .trim();
224
- });
225
-
226
- if (formattedText.length > 0) {
227
- const separator = colWidths
228
- .map((w: number) => '-'.repeat(w + 2))
229
- .join('+');
230
- formattedText.splice(1, 0, separator);
231
- }
232
-
233
- text += `Sheet: ${sheetName}\n${formattedText.join('\n')}\n\n`;
234
- }
235
-
236
- return text;
237
- };
238
-
239
- const formatXLSXWorkbookAsCsv = (workbook: {
240
- SheetNames: string[];
241
- Sheets: Record<string, unknown>;
242
- }): string => {
243
- let text = '';
244
-
245
- for (const sheetName of workbook.SheetNames) {
246
- const worksheet = workbook.Sheets[sheetName];
247
- const csv = window.XLSX.utils.sheet_to_csv(worksheet, { raw: false });
248
- if (csv.trim()) {
249
- text += `Sheet: ${sheetName}\n${csv}\n\n`;
250
- }
251
- }
252
-
253
- return text;
254
- };
255
-
256
- const extractTextFromXLSX = async (
257
- file: File
258
- ): Promise<{ display: string; asset: string }> => {
259
- try {
260
- const workbook = await readXLSXWorkbook(file);
261
- return {
262
- display: formatXLSXWorkbookForDisplay(workbook),
263
- asset: formatXLSXWorkbookAsCsv(workbook),
264
- };
265
- } catch (error) {
266
- console.error('XLSX extraction failed:', error);
267
- throw new Error(
268
- `XLSX extraction failed: ${
269
- error instanceof Error ? error.message : 'Unknown error'
270
- }`
271
- );
272
- }
273
- };
274
-
275
117
  const processDocumentFile = async (
276
118
  file: File
277
119
  ): Promise<{
278
120
  text: string | null;
279
- textForAsset?: string;
280
121
  uploadAsOriginal?: boolean;
281
122
  }> => {
282
123
  if (isOfficeNativeFilename(file.name)) {
283
124
  return { text: null, uploadAsOriginal: true };
284
125
  }
285
126
 
286
- const ext = file.name.split('.').pop()?.toLowerCase() || '';
287
127
  try {
288
- let text: string | null = null;
289
- let textForAsset: string | undefined;
290
-
291
- if (ext === 'pdf') {
292
- text = await extractTextFromPDF(file);
293
- } else if (['txt', 'md', 'json', 'csv', 'html'].includes(ext)) {
294
- text = await file.text();
295
- } else if (ext === 'xlsx') {
296
- const extracted = await extractTextFromXLSX(file);
297
- text = extracted.display;
298
- textForAsset = extracted.asset;
299
- }
300
-
301
- return { text, textForAsset };
128
+ const text = await convertDocument(file, sessionID, baseUrl);
129
+ return { text };
302
130
  } catch (error) {
303
131
  console.error('Document processing failed:', error);
304
132
  throw new Error(
@@ -414,8 +242,7 @@ const UploadDocuments: React.FC<UploadDocumentsProps> = ({
414
242
  const fileId = Math.random().toString(36).substr(2, 9);
415
243
 
416
244
  try {
417
- const { text, textForAsset, uploadAsOriginal } =
418
- await processDocumentFile(file);
245
+ const { text, uploadAsOriginal } = await processDocumentFile(file);
419
246
 
420
247
  if (uploadAsOriginal) {
421
248
  // Office native format: upload the original file as asset, no text extraction
@@ -448,8 +275,7 @@ const UploadDocuments: React.FC<UploadDocumentsProps> = ({
448
275
  });
449
276
  } else if (text) {
450
277
  const baseName = file.name.replace(/\.[^/.]+$/, '') || file.name;
451
- const assetText = textForAsset ?? text;
452
- const textFile = new File([assetText], `${baseName}.txt`, {
278
+ const textFile = new File([text], `${baseName}.txt`, {
453
279
  type: 'text/plain',
454
280
  });
455
281
 
@@ -514,9 +340,9 @@ const UploadDocuments: React.FC<UploadDocumentsProps> = ({
514
340
  <input
515
341
  ref={documentInputRef}
516
342
  type="file"
517
- accept={`.pdf,.txt,.md,.json,.xlsx,.csv,.html,${officeNativeExtensions.join(
343
+ accept={[...documentConversionExtensions, ...officeNativeExtensions].join(
518
344
  ','
519
- )}`}
345
+ )}
520
346
  multiple
521
347
  className="memori--upload-file-input"
522
348
  onChange={handleDocumentUpload}
@@ -6,7 +6,7 @@ exports[`renders UploadButton unchanged 1`] = `
6
6
  class="memori--unified-upload-wrapper"
7
7
  >
8
8
  <input
9
- accept=".jpg,.jpeg,.png,.pdf,.txt,.json,.xlsx,.csv,.md,.html,.doc,.docx,.dotx,.xltx,.potx"
9
+ accept=".jpg,.jpeg,.png,.pdf,.docm,.xlsx,.xlsm,.xls,.ods,.pptx,.pptm,.html,.htm,.xhtml,.csv,.tsv,.txt,.md,.markdown,.json,.xml,.log,.yml,.yaml,.doc,.docx,.dotx,.xltx,.potx"
10
10
  class="memori--upload-file-input"
11
11
  multiple=""
12
12
  style="display: none;"
@@ -52,7 +52,7 @@ exports[`renders UploadButton unchanged 1`] = `
52
52
  class="memori--document-upload-wrapper"
53
53
  >
54
54
  <input
55
- accept=".pdf,.txt,.md,.json,.xlsx,.csv,.html,.doc,.docx,.dotx,.xltx,.potx"
55
+ accept=".pdf,.docm,.xlsx,.xlsm,.xls,.ods,.pptx,.pptm,.html,.htm,.xhtml,.csv,.tsv,.txt,.md,.markdown,.json,.xml,.log,.yml,.yaml,.doc,.docx,.dotx,.xltx,.potx"
56
56
  class="memori--upload-file-input"
57
57
  multiple=""
58
58
  type="file"
@@ -1,5 +1,9 @@
1
1
  import * as React from 'react';
2
- const PrintIcon: React.FC<{ className?: string, title?: string }> = ({ className, title }) => (
2
+
3
+ const PrintIcon: React.FC<{ className?: string; title?: string }> = ({
4
+ className,
5
+ title,
6
+ }) => (
3
7
  <svg
4
8
  {...(!title ? { 'aria-hidden': 'true' } : {})}
5
9
  aria-label={title}
@@ -14,7 +18,7 @@ const PrintIcon: React.FC<{ className?: string, title?: string }> = ({ className
14
18
  <g
15
19
  id="Page-1"
16
20
  stroke="none"
17
- stroke-width="1"
21
+ strokeWidth="1"
18
22
  fill="none"
19
23
  fill-rule="evenodd"
20
24
  >
@@ -52,6 +52,30 @@ export const officeNativeExtensions = [
52
52
  '.potx',
53
53
  ] as const;
54
54
 
55
+ export const documentConversionExtensions = [
56
+ '.pdf',
57
+ '.docm',
58
+ '.xlsx',
59
+ '.xlsm',
60
+ '.xls',
61
+ '.ods',
62
+ '.pptx',
63
+ '.pptm',
64
+ '.html',
65
+ '.htm',
66
+ '.xhtml',
67
+ '.csv',
68
+ '.tsv',
69
+ '.txt',
70
+ '.md',
71
+ '.markdown',
72
+ '.json',
73
+ '.xml',
74
+ '.log',
75
+ '.yml',
76
+ '.yaml',
77
+ ] as const;
78
+
55
79
  export const allowedMediaTypes = [
56
80
  'image/jpeg',
57
81
  'image/png',
@@ -0,0 +1,67 @@
1
+ import { convertDocument } from './convertDocument';
2
+
3
+ describe('convertDocument', () => {
4
+ const fetchMock = jest.fn();
5
+
6
+ beforeEach(() => {
7
+ fetchMock.mockReset();
8
+ globalThis.fetch = fetchMock as unknown as typeof fetch;
9
+ });
10
+
11
+ it('uploads a file through the session-gated endpoint', async () => {
12
+ fetchMock.mockResolvedValue({
13
+ ok: true,
14
+ json: jest.fn().mockResolvedValue({ text: '# Converted document' }),
15
+ });
16
+ const file = new File(['document'], 'contract.pdf', {
17
+ type: 'application/pdf',
18
+ });
19
+
20
+ await expect(
21
+ convertDocument(file, 'session/id', 'https://www.aisuru.com/')
22
+ ).resolves.toBe('# Converted document');
23
+
24
+ expect(fetchMock).toHaveBeenCalledWith(
25
+ 'https://www.aisuru.com/api/convert/session%2Fid',
26
+ expect.objectContaining({
27
+ method: 'POST',
28
+ body: expect.any(FormData),
29
+ })
30
+ );
31
+ const body = fetchMock.mock.calls[0][1].body as FormData;
32
+ expect(body.get('file')).toBe(file);
33
+ expect(fetchMock.mock.calls[0][1].headers).toBeUndefined();
34
+ });
35
+
36
+ it('uses the current origin when baseUrl is omitted', async () => {
37
+ fetchMock.mockResolvedValue({
38
+ ok: true,
39
+ json: jest.fn().mockResolvedValue({ text: 'Converted' }),
40
+ });
41
+
42
+ await convertDocument(new File(['text'], 'notes.txt'), 'session');
43
+
44
+ expect(fetchMock).toHaveBeenCalledWith(
45
+ '/api/convert/session',
46
+ expect.any(Object)
47
+ );
48
+ });
49
+
50
+ it('surfaces conversion API errors', async () => {
51
+ fetchMock.mockResolvedValue({
52
+ ok: false,
53
+ json: jest.fn().mockResolvedValue({ error: 'Formato non supportato' }),
54
+ });
55
+
56
+ await expect(
57
+ convertDocument(new File(['document'], 'contract.pages'), 'session')
58
+ ).rejects.toThrow('Formato non supportato');
59
+ });
60
+
61
+ it('requires a session before uploading', async () => {
62
+ await expect(
63
+ convertDocument(new File(['document'], 'contract.pdf'), '')
64
+ ).rejects.toThrow('Session ID is required');
65
+ expect(fetchMock).not.toHaveBeenCalled();
66
+ });
67
+ });
@@ -0,0 +1,35 @@
1
+ type ConvertDocumentResponse = {
2
+ text?: string;
3
+ error?: string;
4
+ };
5
+
6
+ export const convertDocument = async (
7
+ file: File,
8
+ sessionID: string,
9
+ baseUrl = ''
10
+ ): Promise<string> => {
11
+ if (!sessionID) {
12
+ throw new Error('Session ID is required to convert documents');
13
+ }
14
+
15
+ const body = new FormData();
16
+ body.append('file', file);
17
+
18
+ const origin = baseUrl.replace(/\/+$/, '');
19
+ const response = await fetch(
20
+ `${origin}/api/convert/${encodeURIComponent(sessionID)}`,
21
+ {
22
+ method: 'POST',
23
+ body,
24
+ }
25
+ );
26
+ const payload = (await response
27
+ .json()
28
+ .catch(() => null)) as ConvertDocumentResponse | null;
29
+
30
+ if (!response.ok || !payload?.text) {
31
+ throw new Error(payload?.error || 'Document conversion failed');
32
+ }
33
+
34
+ return payload.text;
35
+ };
@@ -43,10 +43,46 @@ describe('Media URL helper', () => {
43
43
  resourceURI:
44
44
  'https://api.lorem.space/image/game?w=150&h=220&hash=8B7BCDC2',
45
45
  apiURL: 'https://backend.memori.ai/api/v2',
46
+ sessionID: sessionID,
46
47
  })
47
48
  ).toBe('https://api.lorem.space/image/game?w=150&h=220&hash=8B7BCDC2');
48
49
  });
49
50
 
51
+ it('appends session ID for aisuru.ai asset URLs', () => {
52
+ expect(
53
+ getResourceUrl({
54
+ resourceURI:
55
+ 'https://backend-ws-bologna.aisuru.ai/api/v2/asset/ad10ce11-914b-4b9b-a033-ba06cb4b4042.pdf',
56
+ sessionID: sessionID,
57
+ })
58
+ ).toBe(
59
+ `https://backend-ws-bologna.aisuru.ai/api/v2/asset/ad10ce11-914b-4b9b-a033-ba06cb4b4042.pdf/${sessionID}`
60
+ );
61
+ });
62
+
63
+ it('appends session ID for /api/v2/asset/ paths on unknown hosts', () => {
64
+ expect(
65
+ getResourceUrl({
66
+ resourceURI:
67
+ 'https://custom-backend.example.com/api/v2/asset/abc123.pdf',
68
+ sessionID: sessionID,
69
+ })
70
+ ).toBe(
71
+ `https://custom-backend.example.com/api/v2/asset/abc123.pdf/${sessionID}`
72
+ );
73
+ });
74
+
75
+ it('appends session ID when resource host matches apiURL host', () => {
76
+ expect(
77
+ getResourceUrl({
78
+ resourceURI: 'https://my-api.example.com/files/doc.pdf',
79
+ sessionID: sessionID,
80
+ apiURL: 'https://my-api.example.com/api/v2',
81
+ })
82
+ ).toBe(`https://my-api.example.com/files/doc.pdf/${sessionID}`);
83
+ });
84
+
85
+
50
86
  it('Get correct URL for old memoriai/memory media', async () => {
51
87
  expect(
52
88
  getResourceUrl({
@@ -6,6 +6,38 @@ export interface ResourceURLParams {
6
6
  apiURL?: string;
7
7
  tenantID?: string;
8
8
  }
9
+
10
+ /**
11
+ * Whether this HTTP(S) URL should get a session ID appended for auth.
12
+ * Matches Memori asset API paths on any host, known Memori/AIsuru hosts,
13
+ * and the configured API host — instead of a hard hostname allowlist only.
14
+ */
15
+ const shouldAppendSessionId = (
16
+ resourceURI: string,
17
+ apiURL?: string
18
+ ): boolean => {
19
+ const url = new URL(resourceURI);
20
+ const { hostname, pathname } = url;
21
+
22
+ // Memori asset endpoints require session auth regardless of host
23
+ // (e.g. backend-ws-bologna.aisuru.ai/api/v2/asset/…)
24
+ if (/\/api\/v\d+\/asset\//i.test(pathname)) {
25
+ return true;
26
+ }
27
+
28
+ if (apiURL) {
29
+ try {
30
+ if (new URL(apiURL).hostname === hostname) {
31
+ return true;
32
+ }
33
+ } catch {
34
+ // ignore invalid apiURL
35
+ }
36
+ }
37
+
38
+ return false;
39
+ };
40
+
9
41
  export const getResourceUrl = ({
10
42
  type,
11
43
  resourceURI,
@@ -30,21 +62,16 @@ export const getResourceUrl = ({
30
62
  } else if (
31
63
  (resourceURI.startsWith('https://') ||
32
64
  resourceURI.startsWith('http://')) &&
33
- (new URL(resourceURI).hostname.includes('memori.ai') ||
34
- new URL(resourceURI).hostname.includes('aclambda.online') ||
35
- new URL(resourceURI).hostname.includes('localhost'))
65
+ shouldAppendSessionId(resourceURI, apiURL)
36
66
  ) {
37
- return `${resourceURI}${
38
- resourceURI.endsWith('/') || !sessionID ? '' : '/'
39
- }${sessionID || ''}`;
67
+ return `${resourceURI}${resourceURI.endsWith('/') || !sessionID ? '' : '/'
68
+ }${sessionID || ''}`;
40
69
  } else if (resourceURI.startsWith('cloud://')) {
41
- return `${
42
- apiURL?.replace(/v2/, 'v1') || ''
43
- }/CloudAsset/${resourceURI.replace('cloud://', '')}`;
70
+ return `${apiURL?.replace(/v2/, 'v1') || ''
71
+ }/CloudAsset/${resourceURI.replace('cloud://', '')}`;
44
72
  } else if (resourceURI.startsWith('guid://')) {
45
- return `${
46
- apiURL?.replace(/v2/, 'v1') || ''
47
- }/GuidAsset/${resourceURI.replace('guid://', '')}`;
73
+ return `${apiURL?.replace(/v2/, 'v1') || ''
74
+ }/GuidAsset/${resourceURI.replace('guid://', '')}`;
48
75
  } else {
49
76
  return resourceURI || defaultUri;
50
77
  }
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // This file is auto-generated. Do not edit manually.
2
- export const version = '8.41.6';
2
+ export const version = '8.43.0';
@@ -1,8 +0,0 @@
1
- import { ArtifactEdit } from '../types/artifact.types';
2
- export interface ApplyEditsResult {
3
- content: string;
4
- failedEdits: ArtifactEdit[];
5
- appliedCount: number;
6
- }
7
- export declare const applyEdits: (content: string, edits: ArtifactEdit[]) => ApplyEditsResult;
8
- export declare const parseEdits: (body: string) => ArtifactEdit[] | null;