diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index f0a90c2ac..61631c333 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -32,6 +32,7 @@ import Commands from './MessageInput/Commands.svelte'; import XMark from '../icons/XMark.svelte'; import RichTextInput from '../common/RichTextInput.svelte'; + import { getTools } from '$lib/apis/tools'; const i18n = getContext('i18n'); @@ -53,6 +54,7 @@ export let selectedToolIds = []; export let webSearchEnabled = false; + let loaded = false; let recording = false; let chatInputContainerElement; @@ -228,7 +230,11 @@ dragged = false; }; - onMount(() => { + onMount(async () => { + await tools.set(await getTools(localStorage.token)); + + loaded = true; + window.setTimeout(() => { const chatInput = document.getElementById('chat-input'); chatInput?.focus(); @@ -256,385 +262,537 @@ -
-
-
-
- {#if autoScroll === false && history?.currentId} -
- -
- {/if} -
- -
- {#if atSelectedModel !== undefined || selectedToolIds.length > 0 || webSearchEnabled} -
- {#if atSelectedModel !== undefined} -
-
- model profile model.id === atSelectedModel.id)?.info?.meta - ?.profile_image_url ?? - ($i18n.language === 'dg-DG' - ? `/doge.png` - : `${WEBUI_BASE_URL}/static/favicon.png`)} - /> -
- Talking to {atSelectedModel.name} -
-
-
- -
-
- {/if} - - {#if selectedToolIds.length > 0} -
-
-
- - - -
-
- {selectedToolIds - .map((id) => { - return $tools.find((tool) => tool.id === id)?.name; - }) - .join(', ')} -
-
-
- -
-
- {/if} - - {#if webSearchEnabled} -
-
-
- - - -
-
{$i18n.t('Search the web')}
-
-
- -
-
- {/if} -
- {/if} - - { - dispatch('upload', e.detail); - }} - on:select={(e) => { - const data = e.detail; - - if (data?.type === 'model') { - atSelectedModel = data.data; - } - - const chatInputElement = document.getElementById('chat-input'); - chatInputElement?.focus(); - }} - /> -
-
-
- -
-
-
- { - if (inputFiles && inputFiles.length > 0) { - const _inputFiles = Array.from(inputFiles); - inputFilesHandler(_inputFiles); - } else { - toast.error($i18n.t(`File not found.`)); - } - - filesInputElement.value = ''; - }} - /> - - {#if recording} - { - recording = false; - - await tick(); - document.getElementById('chat-input')?.focus(); - }} - on:confirm={async (e) => { - const { text, filename } = e.detail; - prompt = `${prompt}${text} `; - - recording = false; - - await tick(); - document.getElementById('chat-input')?.focus(); - - if ($settings?.speechAutoSend ?? false) { - dispatch('submit', prompt); - } - }} - /> - {:else} -
{ - // check if selectedModels support image input - dispatch('submit', prompt); - }} - > +{#if loaded} +
+
+
+
+ {#if autoScroll === false && history?.currentId}
- {#if files.length > 0} -
- {#each files as file, fileIdx} - {#if file.type === 'image'} -
-
- input - {#if atSelectedModel ? visionCapableModels.length === 0 : selectedModels.length !== visionCapableModels.length} - !visionCapableModels.includes(id)) - .join(', ') - })} - > - - - - - {/if} -
-
- -
-
- {:else} - { - files.splice(fileIdx, 1); - files = files; - }} - on:click={() => { - console.log(file); - }} - /> - {/if} - {/each} + +
+ {/if} +
+ +
+ {#if atSelectedModel !== undefined || selectedToolIds.length > 0 || webSearchEnabled} +
+ {#if atSelectedModel !== undefined} +
+
+ model profile model.id === atSelectedModel.id)?.info?.meta + ?.profile_image_url ?? + ($i18n.language === 'dg-DG' + ? `/doge.png` + : `${WEBUI_BASE_URL}/static/favicon.png`)} + /> +
+ Talking to {atSelectedModel.name} +
+
+
+ +
{/if} -
-
- { - filesInputElement.click(); - }} - onClose={async () => { - await tick(); - - const chatInput = document.getElementById('chat-input'); - chatInput?.focus(); - }} - > - - +
+ {/if} - {#if $settings?.richTextInput ?? true} -
- +
+
+ + + +
+
{$i18n.t('Search the web')}
+
+
+ +
+
+ {/if} +
+ {/if} + + { + dispatch('upload', e.detail); + }} + on:select={(e) => { + const data = e.detail; + + if (data?.type === 'model') { + atSelectedModel = data.data; + } + + const chatInputElement = document.getElementById('chat-input'); + chatInputElement?.focus(); + }} + /> +
+
+
+ +
+
+
+ { + if (inputFiles && inputFiles.length > 0) { + const _inputFiles = Array.from(inputFiles); + inputFilesHandler(_inputFiles); + } else { + toast.error($i18n.t(`File not found.`)); + } + + filesInputElement.value = ''; + }} + /> + + {#if recording} + { + recording = false; + + await tick(); + document.getElementById('chat-input')?.focus(); + }} + on:confirm={async (e) => { + const { text, filename } = e.detail; + prompt = `${prompt}${text} `; + + recording = false; + + await tick(); + document.getElementById('chat-input')?.focus(); + + if ($settings?.speechAutoSend ?? false) { + dispatch('submit', prompt); + } + }} + /> + {:else} + { + // check if selectedModels support image input + dispatch('submit', prompt); + }} + > +
+ {#if files.length > 0} +
+ {#each files as file, fileIdx} + {#if file.type === 'image'} +
+
+ input + {#if atSelectedModel ? visionCapableModels.length === 0 : selectedModels.length !== visionCapableModels.length} + !visionCapableModels.includes(id)) + .join(', ') + })} + > + + + + + {/if} +
+
+ +
+
+ {:else} + { + files.splice(fileIdx, 1); + files = files; + }} + on:click={() => { + console.log(file); + }} + /> + {/if} + {/each} +
+ {/if} + +
+
+ { + filesInputElement.click(); + }} + onClose={async () => { + await tick(); + + const chatInput = document.getElementById('chat-input'); + chatInput?.focus(); + }} + > + + +
+ + {#if $settings?.richTextInput ?? true} +
+ 0 || + navigator.msMaxTouchPoints > 0 + )} + on:enter={async (e) => { + if (prompt !== '') { + dispatch('submit', prompt); + } + }} + on:input={async (e) => { + if (chatInputContainerElement) { + chatInputContainerElement.style.height = ''; + chatInputContainerElement.style.height = + Math.min(chatInputContainerElement.scrollHeight, 200) + 'px'; + } + }} + on:focus={async (e) => { + if (chatInputContainerElement) { + chatInputContainerElement.style.height = ''; + chatInputContainerElement.style.height = + Math.min(chatInputContainerElement.scrollHeight, 200) + 'px'; + } + }} + on:keypress={(e) => { + e = e.detail.event; + }} + on:keydown={async (e) => { + e = e.detail.event; + + if (chatInputContainerElement) { + chatInputContainerElement.style.height = ''; + chatInputContainerElement.style.height = + Math.min(chatInputContainerElement.scrollHeight, 200) + 'px'; + } + + const isCtrlPressed = e.ctrlKey || e.metaKey; // metaKey is for Cmd key on Mac + const commandsContainerElement = + document.getElementById('commands-container'); + + // Command/Ctrl + Shift + Enter to submit a message pair + if (isCtrlPressed && e.key === 'Enter' && e.shiftKey) { + e.preventDefault(); + createMessagePair(prompt); + } + + // Check if Ctrl + R is pressed + if (prompt === '' && isCtrlPressed && e.key.toLowerCase() === 'r') { + e.preventDefault(); + console.log('regenerate'); + + const regenerateButton = [ + ...document.getElementsByClassName('regenerate-response-button') + ]?.at(-1); + + regenerateButton?.click(); + } + + if (prompt === '' && e.key == 'ArrowUp') { + e.preventDefault(); + + const userMessageElement = [ + ...document.getElementsByClassName('user-message') + ]?.at(-1); + + const editButton = [ + ...document.getElementsByClassName('edit-user-message-button') + ]?.at(-1); + + console.log(userMessageElement); + + userMessageElement.scrollIntoView({ block: 'center' }); + editButton?.click(); + } + + if (commandsContainerElement && e.key === 'ArrowUp') { + e.preventDefault(); + commandsElement.selectUp(); + + const commandOptionButton = [ + ...document.getElementsByClassName('selected-command-option-button') + ]?.at(-1); + commandOptionButton.scrollIntoView({ block: 'center' }); + } + + if (commandsContainerElement && e.key === 'ArrowDown') { + e.preventDefault(); + commandsElement.selectDown(); + + const commandOptionButton = [ + ...document.getElementsByClassName('selected-command-option-button') + ]?.at(-1); + commandOptionButton.scrollIntoView({ block: 'center' }); + } + + if (commandsContainerElement && e.key === 'Enter') { + e.preventDefault(); + + const commandOptionButton = [ + ...document.getElementsByClassName('selected-command-option-button') + ]?.at(-1); + + if (e.shiftKey) { + prompt = `${prompt}\n`; + } else if (commandOptionButton) { + commandOptionButton?.click(); + } else { + document.getElementById('send-message-button')?.click(); + } + } + + if (commandsContainerElement && e.key === 'Tab') { + e.preventDefault(); + + const commandOptionButton = [ + ...document.getElementsByClassName('selected-command-option-button') + ]?.at(-1); + + commandOptionButton?.click(); + } + + if (e.key === 'Escape') { + console.log('Escape'); + atSelectedModel = undefined; + selectedToolIds = []; + webSearchEnabled = false; + } + }} + on:paste={async (e) => { + e = e.detail.event; + console.log(e); + + const clipboardData = e.clipboardData || window.clipboardData; + + if (clipboardData && clipboardData.items) { + for (const item of clipboardData.items) { + if (item.type.indexOf('image') !== -1) { + const blob = item.getAsFile(); + const reader = new FileReader(); + + reader.onload = function (e) { + files = [ + ...files, + { + type: 'image', + url: `${e.target.result}` + } + ]; + }; + + reader.readAsDataURL(blob); + } + } + } + }} + /> +
+ {:else} +