diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index f6ddf2beb..566a58ddb 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -790,100 +790,106 @@ ////////////////////////// const submitPrompt = async (userPrompt, { _raw = false } = {}) => { - let _responses = []; - console.log('submitPrompt', $chatId); - const messages = createMessagesList(history.currentId); + console.log('submitPrompt', userPrompt, $chatId); + const messages = createMessagesList(history.currentId); selectedModels = selectedModels.map((modelId) => $models.map((m) => m.id).includes(modelId) ? modelId : '' ); + if (userPrompt === '') { + toast.error($i18n.t('Please enter a prompt')); + return; + } if (selectedModels.includes('')) { toast.error($i18n.t('Model not selected')); - } else if (messages.length != 0 && messages.at(-1).done != true) { + return; + } + + if (messages.length != 0 && messages.at(-1).done != true) { // Response not done - console.log('wait'); - } else if (messages.length != 0 && messages.at(-1).error) { + return; + } + if (messages.length != 0 && messages.at(-1).error) { // Error in response - toast.error( - $i18n.t( - `Oops! There was an error in the previous response. Please try again or contact admin.` - ) - ); - } else if ( + toast.error($i18n.t(`Oops! There was an error in the previous response.`)); + return; + } + if ( files.length > 0 && files.filter((file) => file.type !== 'image' && file.status === 'uploading').length > 0 ) { - // Upload not done toast.error( - $i18n.t( - `Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.` - ) + $i18n.t(`Oops! There are files still uploading. Please wait for the upload to complete.`) ); - } else if ( + return; + } + if ( ($config?.file?.max_count ?? null) !== null && files.length + chatFiles.length > $config?.file?.max_count ) { - console.log(chatFiles.length, files.length); toast.error( $i18n.t(`You can only chat with a maximum of {{maxCount}} file(s) at a time.`, { maxCount: $config?.file?.max_count }) ); - } else { - prompt = ''; - - // Reset chat input textarea - const chatInputContainer = document.getElementById('chat-input-container'); - - if (chatInputContainer) { - chatInputContainer.value = ''; - chatInputContainer.style.height = ''; - } - - const _files = JSON.parse(JSON.stringify(files)); - chatFiles.push(..._files.filter((item) => ['doc', 'file', 'collection'].includes(item.type))); - chatFiles = chatFiles.filter( - // Remove duplicates - (item, index, array) => - array.findIndex((i) => JSON.stringify(i) === JSON.stringify(item)) === index - ); - - files = []; - prompt = ''; - - // Create user message - let userMessageId = uuidv4(); - let userMessage = { - id: userMessageId, - parentId: messages.length !== 0 ? messages.at(-1).id : null, - childrenIds: [], - role: 'user', - content: userPrompt, - files: _files.length > 0 ? _files : undefined, - timestamp: Math.floor(Date.now() / 1000), // Unix epoch - models: selectedModels - }; - - // Add message to history and Set currentId to messageId - history.messages[userMessageId] = userMessage; - history.currentId = userMessageId; - - // Append messageId to childrenIds of parent message - if (messages.length !== 0) { - history.messages[messages.at(-1).id].childrenIds.push(userMessageId); - } - - // Wait until history/message have been updated - await tick(); - - // focus on chat input - const chatInput = document.getElementById('chat-input'); - chatInput?.focus(); - - _responses = await sendPrompt(userPrompt, userMessageId, { newChat: true }); + return; } + let _responses = []; + prompt = ''; + await tick(); + + // Reset chat input textarea + const chatInputContainer = document.getElementById('chat-input-container'); + + if (chatInputContainer) { + chatInputContainer.value = ''; + chatInputContainer.style.height = ''; + } + + const _files = JSON.parse(JSON.stringify(files)); + chatFiles.push(..._files.filter((item) => ['doc', 'file', 'collection'].includes(item.type))); + chatFiles = chatFiles.filter( + // Remove duplicates + (item, index, array) => + array.findIndex((i) => JSON.stringify(i) === JSON.stringify(item)) === index + ); + + files = []; + prompt = ''; + + // Create user message + let userMessageId = uuidv4(); + let userMessage = { + id: userMessageId, + parentId: messages.length !== 0 ? messages.at(-1).id : null, + childrenIds: [], + role: 'user', + content: userPrompt, + files: _files.length > 0 ? _files : undefined, + timestamp: Math.floor(Date.now() / 1000), // Unix epoch + models: selectedModels + }; + + // Add message to history and Set currentId to messageId + history.messages[userMessageId] = userMessage; + history.currentId = userMessageId; + + // Append messageId to childrenIds of parent message + if (messages.length !== 0) { + history.messages[messages.at(-1).id].childrenIds.push(userMessageId); + } + + // Wait until history/message have been updated + await tick(); + + // focus on chat input + const chatInput = document.getElementById('chat-input'); + chatInput?.focus(); + + _responses = await sendPrompt(userPrompt, userMessageId, { newChat: true }); + return _responses; }; diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index 419629476..d135004cf 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -517,6 +517,7 @@ <RichTextInput bind:this={chatInputElement} id="chat-input" + trim={true} placeholder={placeholder ? placeholder : $i18n.t('Send a Message')} bind:value={prompt} shiftEnter={!$mobile || diff --git a/src/lib/components/common/Collapsible.svelte b/src/lib/components/common/Collapsible.svelte index 50fe9bb84..e514d92a6 100644 --- a/src/lib/components/common/Collapsible.svelte +++ b/src/lib/components/common/Collapsible.svelte @@ -31,8 +31,10 @@ } }} > - <div class=" w-fit font-medium transition flex items-center justify-between gap-2"> - <div> + <div + class=" w-fit font-medium flex items-center justify-between gap-2 text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition" + > + <div class=" "> {title} </div> @@ -56,9 +58,7 @@ } }} > - <div - class="flex items-center gap-2 text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition" - > + <div> <slot /> </div> </div> diff --git a/src/lib/components/common/RichTextInput.svelte b/src/lib/components/common/RichTextInput.svelte index fccf9ed0c..45cdd6e2d 100644 --- a/src/lib/components/common/RichTextInput.svelte +++ b/src/lib/components/common/RichTextInput.svelte @@ -30,6 +30,7 @@ export let id = ''; export let value = ''; export let placeholder = 'Type here...'; + export let trim = false; let element: HTMLElement; // Element where ProseMirror will attach let state; @@ -128,7 +129,11 @@ // Utility function to convert ProseMirror content back to markdown text function serializeEditorContent(doc) { const markdown = customMarkdownSerializer.serialize(doc); - return unescapeMarkdown(markdown); + if (trim) { + return unescapeMarkdown(markdown).trim(); + } else { + return unescapeMarkdown(markdown); + } } // ---- Input Rules ---- @@ -381,6 +386,8 @@ value = serializeEditorContent(newState.doc); // Convert ProseMirror content to markdown text eventDispatch('input', { value }); + + console.log('Editor content:', value); }, handleDOMEvents: { focus: (view, event) => {