index.ts 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. import { v4 as uuidv4 } from 'uuid';
  2. import sha256 from 'js-sha256';
  3. //////////////////////////
  4. // Helper functions
  5. //////////////////////////
  6. export const splitStream = (splitOn) => {
  7. let buffer = '';
  8. return new TransformStream({
  9. transform(chunk, controller) {
  10. buffer += chunk;
  11. const parts = buffer.split(splitOn);
  12. parts.slice(0, -1).forEach((part) => controller.enqueue(part));
  13. buffer = parts[parts.length - 1];
  14. },
  15. flush(controller) {
  16. if (buffer) controller.enqueue(buffer);
  17. }
  18. });
  19. };
  20. export const convertMessagesToHistory = (messages) => {
  21. const history = {
  22. messages: {},
  23. currentId: null
  24. };
  25. let parentMessageId = null;
  26. let messageId = null;
  27. for (const message of messages) {
  28. messageId = uuidv4();
  29. if (parentMessageId !== null) {
  30. history.messages[parentMessageId].childrenIds = [
  31. ...history.messages[parentMessageId].childrenIds,
  32. messageId
  33. ];
  34. }
  35. history.messages[messageId] = {
  36. ...message,
  37. id: messageId,
  38. parentId: parentMessageId,
  39. childrenIds: []
  40. };
  41. parentMessageId = messageId;
  42. }
  43. history.currentId = messageId;
  44. return history;
  45. };
  46. export const getGravatarURL = (email) => {
  47. // Trim leading and trailing whitespace from
  48. // an email address and force all characters
  49. // to lower case
  50. const address = String(email).trim().toLowerCase();
  51. // Create a SHA256 hash of the final string
  52. const hash = sha256(address);
  53. // Grab the actual image URL
  54. return `https://www.gravatar.com/avatar/${hash}`;
  55. };
  56. export const copyToClipboard = (text) => {
  57. if (!navigator.clipboard) {
  58. const textArea = document.createElement('textarea');
  59. textArea.value = text;
  60. // Avoid scrolling to bottom
  61. textArea.style.top = '0';
  62. textArea.style.left = '0';
  63. textArea.style.position = 'fixed';
  64. document.body.appendChild(textArea);
  65. textArea.focus();
  66. textArea.select();
  67. try {
  68. const successful = document.execCommand('copy');
  69. const msg = successful ? 'successful' : 'unsuccessful';
  70. console.log('Fallback: Copying text command was ' + msg);
  71. } catch (err) {
  72. console.error('Fallback: Oops, unable to copy', err);
  73. }
  74. document.body.removeChild(textArea);
  75. return;
  76. }
  77. navigator.clipboard.writeText(text).then(
  78. function () {
  79. console.log('Async: Copying to clipboard was successful!');
  80. },
  81. function (err) {
  82. console.error('Async: Could not copy text: ', err);
  83. }
  84. );
  85. };
  86. export const checkVersion = (required, current) => {
  87. // Returns true when current version is below required
  88. return current === '0.0.0'
  89. ? false
  90. : current.localeCompare(required, undefined, {
  91. numeric: true,
  92. sensitivity: 'case',
  93. caseFirst: 'upper'
  94. }) < 0;
  95. };
  96. export const findWordIndices = (text) => {
  97. const regex = /\[([^\]]+)\]/g;
  98. const matches = [];
  99. let match;
  100. while ((match = regex.exec(text)) !== null) {
  101. matches.push({
  102. word: match[1],
  103. startIndex: match.index,
  104. endIndex: regex.lastIndex - 1
  105. });
  106. }
  107. return matches;
  108. };
  109. export const removeFirstHashWord = (inputString) => {
  110. // Split the string into an array of words
  111. const words = inputString.split(' ');
  112. // Find the index of the first word that starts with #
  113. const index = words.findIndex((word) => word.startsWith('#'));
  114. // Remove the first word with #
  115. if (index !== -1) {
  116. words.splice(index, 1);
  117. }
  118. // Join the remaining words back into a string
  119. const resultString = words.join(' ');
  120. return resultString;
  121. };
  122. export const transformFileName = (fileName) => {
  123. // Convert to lowercase
  124. const lowerCaseFileName = fileName.toLowerCase();
  125. // Remove special characters using regular expression
  126. const sanitizedFileName = lowerCaseFileName.replace(/[^\w\s]/g, '');
  127. // Replace spaces with dashes
  128. const finalFileName = sanitizedFileName.replace(/\s+/g, '-');
  129. return finalFileName;
  130. };
  131. export const calculateSHA256 = async (file) => {
  132. // Create a FileReader to read the file asynchronously
  133. const reader = new FileReader();
  134. // Define a promise to handle the file reading
  135. const readFile = new Promise((resolve, reject) => {
  136. reader.onload = () => resolve(reader.result);
  137. reader.onerror = reject;
  138. });
  139. // Read the file as an ArrayBuffer
  140. reader.readAsArrayBuffer(file);
  141. try {
  142. // Wait for the FileReader to finish reading the file
  143. const buffer = await readFile;
  144. // Convert the ArrayBuffer to a Uint8Array
  145. const uint8Array = new Uint8Array(buffer);
  146. // Calculate the SHA-256 hash using Web Crypto API
  147. const hashBuffer = await crypto.subtle.digest('SHA-256', uint8Array);
  148. // Convert the hash to a hexadecimal string
  149. const hashArray = Array.from(new Uint8Array(hashBuffer));
  150. const hashHex = hashArray.map((byte) => byte.toString(16).padStart(2, '0')).join('');
  151. return `${hashHex}`;
  152. } catch (error) {
  153. console.error('Error calculating SHA-256 hash:', error);
  154. throw error;
  155. }
  156. };
  157. export const getImportOrigin = (_chats) => {
  158. // Check what external service chat imports are from
  159. if ('mapping' in _chats[0]) {
  160. return 'openai';
  161. }
  162. return 'webui';
  163. };
  164. const convertOpenAIMessages = (convo) => {
  165. // Parse OpenAI chat messages and create chat dictionary for creating new chats
  166. const mapping = convo['mapping'];
  167. const messages = [];
  168. let currentId = '';
  169. for (let message_id in mapping) {
  170. const message = mapping[message_id];
  171. currentId = message_id;
  172. if (message['message'] == null || message['message']['content']['parts'][0] == '') {
  173. // Skip chat messages with no content
  174. continue;
  175. } else {
  176. const new_chat = {
  177. id: message_id,
  178. parentId: messages.length > 0 && message['parent'] in mapping ? message['parent'] : null,
  179. childrenIds: message['children'] || [],
  180. role: message['message']?.['author']?.['role'] !== 'user' ? 'assistant' : 'user',
  181. content: message['message']?.['content']?.['parts']?.[0] || '',
  182. model: 'gpt-3.5-turbo',
  183. done: true,
  184. context: null
  185. };
  186. messages.push(new_chat);
  187. }
  188. }
  189. let history = {};
  190. messages.forEach((obj) => (history[obj.id] = obj));
  191. const chat = {
  192. history: {
  193. currentId: currentId,
  194. messages: history // Need to convert this to not a list and instead a json object
  195. },
  196. models: ['gpt-3.5-turbo'],
  197. messages: messages,
  198. options: {},
  199. timestamp: convo['create_time'],
  200. title: convo['title'] ?? 'New Chat'
  201. };
  202. return chat;
  203. };
  204. export const convertOpenAIChats = (_chats) => {
  205. // Create a list of dictionaries with each conversation from import
  206. const chats = [];
  207. for (let convo of _chats) {
  208. const chat = convertOpenAIMessages(convo);
  209. if (Object.keys(chat.history.messages).length > 0) {
  210. chats.push({
  211. id: convo['id'],
  212. user_id: '',
  213. title: convo['title'],
  214. chat: chat,
  215. timestamp: convo['timestamp']
  216. });
  217. }
  218. }
  219. return chats;
  220. };