{#if dragged}
{/if}
{#if autoScroll === false && messages.length > 0}
{ autoScroll = true; scrollToBottom(); }} >
{/if}
{#if prompt.charAt(0) === '/'}
{:else if prompt.charAt(0) === '#'}
{ console.log(e); uploadYoutubeTranscription(e.detail); }} on:url={(e) => { console.log(e); uploadWeb(e.detail); }} on:select={(e) => { console.log(e); files = [ ...files, { type: e?.detail?.type ?? 'doc', ...e.detail, upload_status: true } ]; }} /> {/if}
{ atSelectedModel = e.detail; chatTextAreaElement?.focus(); }} /> {#if atSelectedModel !== undefined}
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}
{ atSelectedModel = undefined; }} >
{/if}
{ if (inputFiles && inputFiles.length > 0) { const _inputFiles = Array.from(inputFiles); _inputFiles.forEach((file) => { if (['image/gif', 'image/webp', 'image/jpeg', 'image/png'].includes(file['type'])) { if (visionCapableModels.length === 0) { toast.error($i18n.t('Selected model(s) do not support image inputs')); inputFiles = null; filesInputElement.value = ''; return; } let reader = new FileReader(); reader.onload = (event) => { files = [ ...files, { type: 'image', url: `${event.target.result}` } ]; inputFiles = null; filesInputElement.value = ''; }; reader.readAsDataURL(file); } else if ( SUPPORTED_FILE_TYPE.includes(file['type']) || SUPPORTED_FILE_EXTENSIONS.includes(file.name.split('.').at(-1)) ) { uploadDoc(file); filesInputElement.value = ''; } else { toast.error( $i18n.t( `Unknown File Type '{{file_type}}', but accepting and treating as plain text`, { file_type: file['type'] } ) ); uploadDoc(file); filesInputElement.value = ''; } }); } else { toast.error($i18n.t(`File not found.`)); } }} /> {#if recording}
{ recording = false; await tick(); document.getElementById('chat-textarea')?.focus(); }} on:confirm={async (e) => { const response = e.detail; prompt = `${prompt}${response} `; recording = false; await tick(); document.getElementById('chat-textarea')?.focus(); if ($settings?.speechAutoSend ?? false) { submitPrompt(prompt, user); } }} /> {:else}
{ // check if selectedModels support image input submitPrompt(prompt, user); }} >
{#if files.length > 0}
{#each files as file, fileIdx}
{#if file.type === 'image'}
{#if atSelectedModel ? visionCapableModels.length === 0 : selectedModels.length !== visionCapableModels.length}
!visionCapableModels.includes(id)) .join(', ') })} >
{/if}
{:else if file.type === 'doc'}
{#if file.upload_status}
{:else}
{/if}
{file.name}
{$i18n.t('Document')}
{:else if file.type === 'collection'}
{file?.title ?? `#${file.name}`}
{$i18n.t('Collection')}
{/if}
{ files.splice(fileIdx, 1); files = files; }} >
{/each}
{/if}
{ filesInputElement.click(); }} onClose={async () => { await tick(); chatTextAreaElement?.focus(); }} >
{ if ( !$mobile || !( 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0 ) ) { // Prevent Enter key from creating a new line if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); } // Submit the prompt when Enter key is pressed if (prompt !== '' && e.key === 'Enter' && !e.shiftKey) { submitPrompt(prompt, user); } } }} on:keydown={async (e) => { const isCtrlPressed = e.ctrlKey || e.metaKey; // metaKey is for Cmd key on Mac // 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 (['/', '#', '@'].includes(prompt.charAt(0)) && e.key === 'ArrowUp') { e.preventDefault(); (promptsElement || documentsElement || modelsElement).selectUp(); const commandOptionButton = [ ...document.getElementsByClassName('selected-command-option-button') ]?.at(-1); commandOptionButton.scrollIntoView({ block: 'center' }); } if (['/', '#', '@'].includes(prompt.charAt(0)) && e.key === 'ArrowDown') { e.preventDefault(); (promptsElement || documentsElement || modelsElement).selectDown(); const commandOptionButton = [ ...document.getElementsByClassName('selected-command-option-button') ]?.at(-1); commandOptionButton.scrollIntoView({ block: 'center' }); } if (['/', '#', '@'].includes(prompt.charAt(0)) && 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 (['/', '#', '@'].includes(prompt.charAt(0)) && e.key === 'Tab') { e.preventDefault(); const commandOptionButton = [ ...document.getElementsByClassName('selected-command-option-button') ]?.at(-1); commandOptionButton?.click(); } else if (e.key === 'Tab') { const words = findWordIndices(prompt); if (words.length > 0) { const word = words.at(0); const fullPrompt = prompt; prompt = prompt.substring(0, word?.endIndex + 1); await tick(); e.target.scrollTop = e.target.scrollHeight; prompt = fullPrompt; await tick(); e.preventDefault(); e.target.setSelectionRange(word?.startIndex, word.endIndex + 1); } e.target.style.height = ''; e.target.style.height = Math.min(e.target.scrollHeight, 200) + 'px'; } if (e.key === 'Escape') { console.log('Escape'); atSelectedModel = undefined; } }} rows="1" on:input={(e) => { e.target.style.height = ''; e.target.style.height = Math.min(e.target.scrollHeight, 200) + 'px'; user = null; }} on:focus={(e) => { e.target.style.height = ''; e.target.style.height = Math.min(e.target.scrollHeight, 200) + 'px'; }} on:paste={(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); } } } }} />
{#if messages.length == 0 || messages.at(-1).done == true}
{ try { const res = await navigator.mediaDevices .getUserMedia({ audio: true }) .catch(function (err) { toast.error( $i18n.t( `Permission denied when accessing microphone: {{error}}`, { error: err } ) ); return null; }); if (res) { recording = true; } } catch { toast.error($i18n.t('Permission denied when accessing microphone')); } }} >
{/if}
{#if messages.length == 0 || messages.at(-1).done == true} {#if prompt === ''}
{ if (selectedModels.length > 1) { toast.error($i18n.t('Select only one model to call')); return; } if ($config.audio.stt.engine === 'web') { toast.error( $i18n.t('Call feature is not supported when using Web STT engine') ); return; } // check if user has access to getUserMedia try { await navigator.mediaDevices.getUserMedia({ audio: true, video: true }); // If the user grants the permission, proceed to show the call overlay showCallOverlay.set(true); } catch (err) { // If the user denies the permission or an error occurs, show an error message toast.error($i18n.t('Permission denied when accessing media devices')); } }} >
{:else}
{/if} {:else}
{ stopResponse(); }} >
{/if}
{/if}
{$i18n.t('LLMs can make mistakes. Verify important information.')}