open-webui/src/lib/utils/index.ts

263 lines
6.4 KiB
TypeScript
Raw Normal View History

2023-11-20 02:47:07 +01:00
import { v4 as uuidv4 } from 'uuid';
import sha256 from 'js-sha256';
//////////////////////////
// Helper functions
//////////////////////////
export const splitStream = (splitOn) => {
let buffer = '';
return new TransformStream({
transform(chunk, controller) {
buffer += chunk;
const parts = buffer.split(splitOn);
parts.slice(0, -1).forEach((part) => controller.enqueue(part));
buffer = parts[parts.length - 1];
},
flush(controller) {
if (buffer) controller.enqueue(buffer);
}
});
};
export const convertMessagesToHistory = (messages) => {
const history = {
2023-11-20 02:47:07 +01:00
messages: {},
currentId: null
};
let parentMessageId = null;
let messageId = null;
for (const message of messages) {
messageId = uuidv4();
if (parentMessageId !== null) {
history.messages[parentMessageId].childrenIds = [
...history.messages[parentMessageId].childrenIds,
messageId
];
}
history.messages[messageId] = {
...message,
id: messageId,
parentId: parentMessageId,
childrenIds: []
};
parentMessageId = messageId;
}
history.currentId = messageId;
return history;
};
export const getGravatarURL = (email) => {
// Trim leading and trailing whitespace from
// an email address and force all characters
// to lower case
const address = String(email).trim().toLowerCase();
// Create a SHA256 hash of the final string
const hash = sha256(address);
// Grab the actual image URL
return `https://www.gravatar.com/avatar/${hash}`;
};
2023-12-19 03:48:51 +01:00
2023-12-26 21:50:52 +01:00
export const copyToClipboard = (text) => {
2023-12-19 03:48:51 +01:00
if (!navigator.clipboard) {
2023-12-26 21:50:52 +01:00
const textArea = document.createElement('textarea');
2023-12-19 03:48:51 +01:00
textArea.value = text;
// Avoid scrolling to bottom
textArea.style.top = '0';
textArea.style.left = '0';
textArea.style.position = 'fixed';
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
2023-12-26 21:50:52 +01:00
const successful = document.execCommand('copy');
const msg = successful ? 'successful' : 'unsuccessful';
2023-12-19 03:48:51 +01:00
console.log('Fallback: Copying text command was ' + msg);
} catch (err) {
console.error('Fallback: Oops, unable to copy', err);
}
document.body.removeChild(textArea);
return;
}
navigator.clipboard.writeText(text).then(
function () {
console.log('Async: Copying to clipboard was successful!');
},
function (err) {
console.error('Async: Could not copy text: ', err);
}
);
};
2023-12-26 22:10:50 +01:00
export const checkVersion = (required, current) => {
2023-12-27 07:52:53 +01:00
// Returns true when current version is below required
return current === '0.0.0'
2023-12-27 07:52:53 +01:00
? false
: current.localeCompare(required, undefined, {
numeric: true,
sensitivity: 'case',
caseFirst: 'upper'
}) < 0;
2023-12-26 22:10:50 +01:00
};
2024-01-02 09:55:28 +01:00
export const findWordIndices = (text) => {
const regex = /\[([^\]]+)\]/g;
const matches = [];
2024-01-02 09:55:28 +01:00
let match;
while ((match = regex.exec(text)) !== null) {
matches.push({
word: match[1],
startIndex: match.index,
endIndex: regex.lastIndex - 1
});
}
return matches;
};
2024-01-07 09:57:10 +01:00
2024-01-08 08:43:32 +01:00
export const removeFirstHashWord = (inputString) => {
// Split the string into an array of words
const words = inputString.split(' ');
// Find the index of the first word that starts with #
const index = words.findIndex((word) => word.startsWith('#'));
// Remove the first word with #
if (index !== -1) {
words.splice(index, 1);
}
// Join the remaining words back into a string
const resultString = words.join(' ');
return resultString;
};
2024-01-08 10:32:55 +01:00
export const transformFileName = (fileName) => {
// Convert to lowercase
const lowerCaseFileName = fileName.toLowerCase();
// Remove special characters using regular expression
const sanitizedFileName = lowerCaseFileName.replace(/[^\w\s]/g, '');
// Replace spaces with dashes
const finalFileName = sanitizedFileName.replace(/\s+/g, '-');
return finalFileName;
};
2024-01-07 09:57:10 +01:00
export const calculateSHA256 = async (file) => {
// Create a FileReader to read the file asynchronously
const reader = new FileReader();
// Define a promise to handle the file reading
const readFile = new Promise((resolve, reject) => {
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
});
// Read the file as an ArrayBuffer
reader.readAsArrayBuffer(file);
try {
// Wait for the FileReader to finish reading the file
const buffer = await readFile;
// Convert the ArrayBuffer to a Uint8Array
const uint8Array = new Uint8Array(buffer);
// Calculate the SHA-256 hash using Web Crypto API
const hashBuffer = await crypto.subtle.digest('SHA-256', uint8Array);
// Convert the hash to a hexadecimal string
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray.map((byte) => byte.toString(16).padStart(2, '0')).join('');
2024-01-07 10:40:36 +01:00
return `${hashHex}`;
2024-01-07 09:57:10 +01:00
} catch (error) {
console.error('Error calculating SHA-256 hash:', error);
throw error;
}
};
export const getImportOrigin = (_chats) => {
// Check what external service chat imports are from
if ('mapping' in _chats[0]) {
return 'gpt';
}
return 'webui';
}
const convertGptMessages = (convo) => {
// Parse OpenAI chat messages and create chat dictionary for creating new chats
const mapping = convo["mapping"];
const messages = [];
let currentId = "";
for (let message_id in mapping) {
const message = mapping[message_id];
currentId = message_id;
if (message["message"] == null || message["message"]["content"]["parts"][0] == "") {
// Skip chat messages with no content
continue;
} else {
const new_chat = {
"id": message_id,
"parentId": messages.length > 0 ? message["parent"] : null,
"childrenIds": message["children"] || [],
"role": message["message"]?.["author"]?.["role"] !== "user" ? "assistant" : "user",
"content": message["message"]?.["content"]?.['parts']?.[0] || "",
"model": '',
"done": true,
"context": null,
}
messages.push(new_chat)
}
}
let history = {};
messages.forEach(obj => history[obj.id] = obj);
const chat = {
"history": {
"currentId": currentId,
"messages": history, // Need to convert this to not a list and instead a json object
},
"models": [""],
"messages": messages,
"options": {},
"timestamp": convo["create_time"],
"title": convo["title"],
}
return chat;
}
export const convertGptChats = (_chats) => {
// Create a list of dictionaries with each conversation from import
const chats = [];
for (let convo of _chats) {
const chat = {
"id": convo["id"],
"user_id": '',
"title": convo["title"],
"chat": convertGptMessages(convo),
"timestamp": convo["timestamp"],
}
chats.push(chat)
}
return chats;
}