{"version":3,"file":"Chat.67864e61.js","sources":["../../../../../../node_modules/bits-ui/dist/bits/menu/components/menu-sub.svelte","../../../../../../node_modules/bits-ui/dist/bits/menu/components/menu-sub-content.svelte","../../../../../../node_modules/bits-ui/dist/bits/menu/components/menu-sub-trigger.svelte","../../../../../../node_modules/eventsource-parser/dist/index.js","../../../../../../node_modules/eventsource-parser/dist/stream.js","../../../../../../src/lib/apis/streaming/index.ts","../../../../../../src/lib/components/common/Banner.svelte","../../../../../../src/lib/components/chat/MessageInput/PromptCommands.svelte","../../../../../../src/lib/components/chat/MessageInput/Documents.svelte","../../../../../../src/lib/components/chat/MessageInput/Models.svelte","../../../../../../src/lib/components/icons/XMark.svelte","../../../../../../src/lib/components/icons/DocumentArrowUpSolid.svelte","../../../../../../src/lib/components/icons/GlobeAltSolid.svelte","../../../../../../src/lib/components/icons/WrenchSolid.svelte","../../../../../../src/lib/components/chat/MessageInput/InputMenu.svelte","../../../../../../src/lib/components/icons/Headphone.svelte","../../../../../../src/lib/components/chat/MessageInput/VoiceRecording.svelte","../../../../../../src/lib/components/chat/MessageInput.svelte","../../../../../../src/lib/components/chat/ModelSelector.svelte","../../../../../../src/lib/components/layout/Navbar/Menu.svelte","../../../../../../src/lib/components/layout/Navbar.svelte","../../../../../../src/lib/components/chat/MessageInput/CallOverlay/VideoInputMenu.svelte","../../../../../../src/lib/components/chat/MessageInput/CallOverlay.svelte","../../../../../../src/lib/components/chat/Chat.svelte"],"sourcesContent":["\n\n\n","\n\n{#if asChild && $subOpen}\n\t\n{:else if transition && $subOpen}\n\t\n\t\t\n\t\n{:else if inTransition && outTransition && $subOpen}\n\t\n\t\t\n\t\n{:else if inTransition && $subOpen}\n\t\n\t\t\n\t\n{:else if outTransition && $subOpen}\n\t\n\t\t\n\t\n{:else if $subOpen}\n\t\n\t\t\n\t\n{/if}\n","\n\n{#if asChild}\n\t\n{:else}\n\t\n\t\t\n\t\n{/if}\n","function createParser(onParse) {\n let isFirstChunk;\n let buffer;\n let startingPosition;\n let startingFieldLength;\n let eventId;\n let eventName;\n let data;\n reset();\n return {\n feed,\n reset\n };\n function reset() {\n isFirstChunk = true;\n buffer = \"\";\n startingPosition = 0;\n startingFieldLength = -1;\n eventId = void 0;\n eventName = void 0;\n data = \"\";\n }\n function feed(chunk) {\n buffer = buffer ? buffer + chunk : chunk;\n if (isFirstChunk && hasBom(buffer)) {\n buffer = buffer.slice(BOM.length);\n }\n isFirstChunk = false;\n const length = buffer.length;\n let position = 0;\n let discardTrailingNewline = false;\n while (position < length) {\n if (discardTrailingNewline) {\n if (buffer[position] === \"\\n\") {\n ++position;\n }\n discardTrailingNewline = false;\n }\n let lineLength = -1;\n let fieldLength = startingFieldLength;\n let character;\n for (let index = startingPosition; lineLength < 0 && index < length; ++index) {\n character = buffer[index];\n if (character === \":\" && fieldLength < 0) {\n fieldLength = index - position;\n } else if (character === \"\\r\") {\n discardTrailingNewline = true;\n lineLength = index - position;\n } else if (character === \"\\n\") {\n lineLength = index - position;\n }\n }\n if (lineLength < 0) {\n startingPosition = length - position;\n startingFieldLength = fieldLength;\n break;\n } else {\n startingPosition = 0;\n startingFieldLength = -1;\n }\n parseEventStreamLine(buffer, position, fieldLength, lineLength);\n position += lineLength + 1;\n }\n if (position === length) {\n buffer = \"\";\n } else if (position > 0) {\n buffer = buffer.slice(position);\n }\n }\n function parseEventStreamLine(lineBuffer, index, fieldLength, lineLength) {\n if (lineLength === 0) {\n if (data.length > 0) {\n onParse({\n type: \"event\",\n id: eventId,\n event: eventName || void 0,\n data: data.slice(0, -1)\n // remove trailing newline\n });\n\n data = \"\";\n eventId = void 0;\n }\n eventName = void 0;\n return;\n }\n const noValue = fieldLength < 0;\n const field = lineBuffer.slice(index, index + (noValue ? lineLength : fieldLength));\n let step = 0;\n if (noValue) {\n step = lineLength;\n } else if (lineBuffer[index + fieldLength + 1] === \" \") {\n step = fieldLength + 2;\n } else {\n step = fieldLength + 1;\n }\n const position = index + step;\n const valueLength = lineLength - step;\n const value = lineBuffer.slice(position, position + valueLength).toString();\n if (field === \"data\") {\n data += value ? \"\".concat(value, \"\\n\") : \"\\n\";\n } else if (field === \"event\") {\n eventName = value;\n } else if (field === \"id\" && !value.includes(\"\\0\")) {\n eventId = value;\n } else if (field === \"retry\") {\n const retry = parseInt(value, 10);\n if (!Number.isNaN(retry)) {\n onParse({\n type: \"reconnect-interval\",\n value: retry\n });\n }\n }\n }\n}\nconst BOM = [239, 187, 191];\nfunction hasBom(buffer) {\n return BOM.every((charCode, index) => buffer.charCodeAt(index) === charCode);\n}\nexport { createParser };\n//# sourceMappingURL=index.js.map\n","import { createParser } from './index.js';\nclass EventSourceParserStream extends TransformStream {\n constructor() {\n let parser;\n super({\n start(controller) {\n parser = createParser(event => {\n if (event.type === \"event\") {\n controller.enqueue(event);\n }\n });\n },\n transform(chunk) {\n parser.feed(chunk);\n }\n });\n }\n}\nexport { EventSourceParserStream };\n//# sourceMappingURL=stream.js.map\n","import { EventSourceParserStream } from 'eventsource-parser/stream';\nimport type { ParsedEvent } from 'eventsource-parser';\n\ntype TextStreamUpdate = {\n\tdone: boolean;\n\tvalue: string;\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tcitations?: any;\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\terror?: any;\n\tusage?: ResponseUsage;\n};\n\ntype ResponseUsage = {\n\t/** Including images and tools if any */\n\tprompt_tokens: number;\n\t/** The tokens generated */\n\tcompletion_tokens: number;\n\t/** Sum of the above two fields */\n\ttotal_tokens: number;\n};\n\n// createOpenAITextStream takes a responseBody with a SSE response,\n// and returns an async generator that emits delta updates with large deltas chunked into random sized chunks\nexport async function createOpenAITextStream(\n\tresponseBody: ReadableStream,\n\tsplitLargeDeltas: boolean\n): Promise> {\n\tconst eventStream = responseBody\n\t\t.pipeThrough(new TextDecoderStream())\n\t\t.pipeThrough(new EventSourceParserStream())\n\t\t.getReader();\n\tlet iterator = openAIStreamToIterator(eventStream);\n\tif (splitLargeDeltas) {\n\t\titerator = streamLargeDeltasAsRandomChunks(iterator);\n\t}\n\treturn iterator;\n}\n\nasync function* openAIStreamToIterator(\n\treader: ReadableStreamDefaultReader\n): AsyncGenerator {\n\twhile (true) {\n\t\tconst { value, done } = await reader.read();\n\t\tif (done) {\n\t\t\tyield { done: true, value: '' };\n\t\t\tbreak;\n\t\t}\n\t\tif (!value) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst data = value.data;\n\t\tif (data.startsWith('[DONE]')) {\n\t\t\tyield { done: true, value: '' };\n\t\t\tbreak;\n\t\t}\n\n\t\ttry {\n\t\t\tconst parsedData = JSON.parse(data);\n\t\t\tconsole.log(parsedData);\n\n\t\t\tif (parsedData.error) {\n\t\t\t\tyield { done: true, value: '', error: parsedData.error };\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (parsedData.citations) {\n\t\t\t\tyield { done: false, value: '', citations: parsedData.citations };\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tyield {\n\t\t\t\tdone: false,\n\t\t\t\tvalue: parsedData.choices?.[0]?.delta?.content ?? '',\n\t\t\t\tusage: parsedData.usage\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tconsole.error('Error extracting delta from SSE event:', e);\n\t\t}\n\t}\n}\n\n// streamLargeDeltasAsRandomChunks will chunk large deltas (length > 5) into random sized chunks between 1-3 characters\n// This is to simulate a more fluid streaming, even though some providers may send large chunks of text at once\nasync function* streamLargeDeltasAsRandomChunks(\n\titerator: AsyncGenerator\n): AsyncGenerator {\n\tfor await (const textStreamUpdate of iterator) {\n\t\tif (textStreamUpdate.done) {\n\t\t\tyield textStreamUpdate;\n\t\t\treturn;\n\t\t}\n\t\tif (textStreamUpdate.citations) {\n\t\t\tyield textStreamUpdate;\n\t\t\tcontinue;\n\t\t}\n\t\tlet content = textStreamUpdate.value;\n\t\tif (content.length < 5) {\n\t\t\tyield { done: false, value: content };\n\t\t\tcontinue;\n\t\t}\n\t\twhile (content != '') {\n\t\t\tconst chunkSize = Math.min(Math.floor(Math.random() * 3) + 1, content.length);\n\t\t\tconst chunk = content.slice(0, chunkSize);\n\t\t\tyield { done: false, value: chunk };\n\t\t\t// Do not sleep if the tab is hidden\n\t\t\t// Timers are throttled to 1s in hidden tabs\n\t\t\tif (document?.visibilityState !== 'hidden') {\n\t\t\t\tawait sleep(5);\n\t\t\t}\n\t\t\tcontent = content.slice(chunkSize);\n\t\t}\n\t}\n}\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n","\n\n{#if !dismissed}\n\t{#if mounted}\n\t\t\n\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t\t{banner.type}\n\t\t\t\t\t
\n\n\t\t\t\t\t{#if banner.url}\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\tLearn More\n\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t{/if}\n\t\t\t\t\n\n\t\t\t\t
\n\t\t\t\t\t{banner.content}\n\t\t\t\t
\n\t\t\t\n\n\t\t\t{#if banner.url}\n\t\t\t\t
\n\t\t\t\t\tLearn More\n\n\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t{/if}\n\t\t\t
\n\t\t\t\t{#if banner.dismissible}\n\t\t\t\t\t {\n\t\t\t\t\t\t\tdismiss(banner.id);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclass=\" -mt-[3px] ml-1.5 mr-1 text-gray-400 dark:hover:text-white h-1\">×\n\t\t\t\t{/if}\n\t\t\t
\n\t\t\n\t{/if}\n{/if}\n","\n\n{#if filteredPromptCommands.length > 0}\n\t
\n\t\t
\n\t\t\t
\n\t\t\t\t
/
\n\t\t\t
\n\n\t\t\t\n\t\t\t\t
\n\t\t\t\t\t{#each filteredPromptCommands as command, commandIdx}\n\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\tconfirmCommand(command);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\ton:mousemove={() => {\n\t\t\t\t\t\t\t\tselectedCommandIdx = commandIdx;\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\ton:focus={() => {}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t{command.command}\n\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t{command.title}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t{/each}\n\t\t\t\t
\n\n\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t
\n\n\t\t\t\t\t
\n\t\t\t\t\t\t{$i18n.t(\n\t\t\t\t\t\t\t'Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.'\n\t\t\t\t\t\t)}\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t
\n\t\t\n\t\n{/if}\n","\n\n{#if filteredItems.length > 0 || prompt.split(' ')?.at(0)?.substring(1).startsWith('http')}\n\t
\n\t\t
\n\t\t\t
\n\t\t\t\t
#
\n\t\t\t
\n\n\t\t\t\n\t\t\t\t
\n\t\t\t\t\t{#each filteredItems as doc, docIdx}\n\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\tconsole.log(doc);\n\n\t\t\t\t\t\t\t\tconfirmSelect(doc);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\ton:mousemove={() => {\n\t\t\t\t\t\t\t\tselectedIdx = docIdx;\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\ton:focus={() => {}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{#if doc.type === 'collection'}\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t{doc?.title ?? `#${doc.name}`}\n\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t{$i18n.t('Collection')}\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t{:else}\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t#{doc.name} ({doc.filename})\n\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t{doc.title}\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t\n\t\t\t\t\t{/each}\n\n\t\t\t\t\t{#if prompt\n\t\t\t\t\t\t.split(' ')\n\t\t\t\t\t\t.some((s) => s.substring(1).startsWith('https://www.youtube.com') || s\n\t\t\t\t\t\t\t\t\t.substring(1)\n\t\t\t\t\t\t\t\t\t.startsWith('https://youtu.be'))}\n\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\tconst url = prompt.split(' ')?.at(0)?.substring(1);\n\t\t\t\t\t\t\t\tif (isValidHttpUrl(url)) {\n\t\t\t\t\t\t\t\t\tconfirmSelectYoutube(url);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\ttoast.error(\n\t\t\t\t\t\t\t\t\t\t$i18n.t(\n\t\t\t\t\t\t\t\t\t\t\t'Oops! Looks like the URL is invalid. Please double-check and try again.'\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t{prompt.split(' ')?.at(0)?.substring(1)}\n\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t
{$i18n.t('Youtube')}
\n\t\t\t\t\t\t\n\t\t\t\t\t{:else if prompt.split(' ')?.at(0)?.substring(1).startsWith('http')}\n\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\tconst url = prompt.split(' ')?.at(0)?.substring(1);\n\t\t\t\t\t\t\t\tif (isValidHttpUrl(url)) {\n\t\t\t\t\t\t\t\t\tconfirmSelectWeb(url);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\ttoast.error(\n\t\t\t\t\t\t\t\t\t\t$i18n.t(\n\t\t\t\t\t\t\t\t\t\t\t'Oops! Looks like the URL is invalid. Please double-check and try again.'\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t{prompt.split(' ')?.at(0)?.substring(1)}\n\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t
{$i18n.t('Web')}
\n\t\t\t\t\t\t\n\t\t\t\t\t{/if}\n\t\t\t\t
\n\t\t\t
\n\t\t
\n\t\n{/if}\n","\n\n{#if prompt.charAt(0) === '@'}\n\t{#if filteredModels.length > 0}\n\t\t
\n\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t
@
\n\t\t\t\t
\n\n\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t\t\t{#each filteredModels as model, modelIdx}\n\t\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\t\tconfirmSelect(model);\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\ton:mousemove={() => {\n\t\t\t\t\t\t\t\t\tselectedIdx = modelIdx;\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\ton:focus={() => {}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t{model.name}\n\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t{/each}\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t
\n\t\t\n\t{/if}\n{/if}\n","\n\n\n\t\n\n","\n\n\n\t\n\t\n\n","\n\n\n\t\n\n","\n\n\n\t\n\n","\n\n {\n\t\tif (e.detail === false) {\n\t\t\tonClose();\n\t\t}\n\t}}\n>\n\t\n\t\t\n\t\n\n\t
\n\t\t\n\t\t\t{#if Object.keys(tools).length > 0}\n\t\t\t\t
\n\t\t\t\t\t{#each Object.keys(tools) as toolId}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t
{tools[toolId].name}
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\t\tselectedToolIds = e.detail\n\t\t\t\t\t\t\t\t\t\t? [...selectedToolIds, toolId]\n\t\t\t\t\t\t\t\t\t\t: selectedToolIds.filter((id) => id !== toolId);\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t
\n\t\t\t\t\t{/each}\n\t\t\t\t
\n\n\t\t\t\t
\n\t\t\t{/if}\n\n\t\t\t{#if $config?.features?.enable_web_search}\n\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t\t
{$i18n.t('Web Search')}
\n\t\t\t\t\t
\n\n\t\t\t\t\t\n\t\t\t\t\n\n\t\t\t\t
\n\t\t\t{/if}\n\n\t\t\t {\n\t\t\t\t\tuploadFilesHandler();\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t\n\t\t\t\t
{$i18n.t('Upload Files')}
\n\t\t\t\n\t\t\n\t\n\n","\n\n\n\t\n\n","\n\n\n\t
\n\t\t {\n\t\t\t\tdispatch('cancel');\n\t\t\t\tstopRecording();\n\t\t\t}}\n\t\t>\n\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t\n\t
\n\n\t\n\t\t
\n\t\t\t{#each visualizerData.slice().reverse() as rms}\n\t\t\t\t\n\t\t\t{/each}\n\t\t
\n\t\n\n\t
\n\t\t\n\t\t\t{formatSeconds(durationSeconds)}\n\t\t
\n\t\n\n\t
\n\t\t{#if loading}\n\t\t\t
\n\t\t\t\t\n\t\t\t
\n\t\t{:else}\n\t\t\t {\n\t\t\t\t\tawait confirmRecording();\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t{/if}\n\t
\n\n\n\n","\n\n{#if dragged}\n\t\n\t\t
\n\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t
\n\t\t
\n\t\n{/if}\n\n
\n\t
\n\t\t
\n\t\t\t
\n\t\t\t\t{#if autoScroll === false && messages.length > 0}\n\t\t\t\t\t
\n\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\tautoScroll = true;\n\t\t\t\t\t\t\t\tscrollToBottom();\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t{/if}\n\t\t\t
\n\n\t\t\t
\n\t\t\t\t{#if prompt.charAt(0) === '/'}\n\t\t\t\t\t\n\t\t\t\t{:else if prompt.charAt(0) === '#'}\n\t\t\t\t\t {\n\t\t\t\t\t\t\tconsole.log(e);\n\t\t\t\t\t\t\tuploadYoutubeTranscription(e.detail);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\ton:url={(e) => {\n\t\t\t\t\t\t\tconsole.log(e);\n\t\t\t\t\t\t\tuploadWeb(e.detail);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\ton:select={(e) => {\n\t\t\t\t\t\t\tconsole.log(e);\n\t\t\t\t\t\t\tfiles = [\n\t\t\t\t\t\t\t\t...files,\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: e?.detail?.type ?? 'doc',\n\t\t\t\t\t\t\t\t\t...e.detail,\n\t\t\t\t\t\t\t\t\tupload_status: true\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t];\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t{/if}\n\n\t\t\t\t {\n\t\t\t\t\t\tatSelectedModel = e.detail;\n\t\t\t\t\t\tchatTextAreaElement?.focus();\n\t\t\t\t\t}}\n\t\t\t\t/>\n\n\t\t\t\t{#if atSelectedModel !== undefined}\n\t\t\t\t\t\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t model.id === atSelectedModel.id)?.info?.meta\n\t\t\t\t\t\t\t\t\t?.profile_image_url ??\n\t\t\t\t\t\t\t\t\t($i18n.language === 'dg-DG'\n\t\t\t\t\t\t\t\t\t\t? `/doge.png`\n\t\t\t\t\t\t\t\t\t\t: `${WEBUI_BASE_URL}/static/favicon.png`)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\tTalking to {atSelectedModel.name}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\t\tatSelectedModel = undefined;\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t{/if}\n\t\t\t
\n\t\t
\n\t
\n\n\t
\n\t\t
\n\t\t\t
\n\t\t\t\t {\n\t\t\t\t\t\tif (inputFiles && inputFiles.length > 0) {\n\t\t\t\t\t\t\tconst _inputFiles = Array.from(inputFiles);\n\t\t\t\t\t\t\t_inputFiles.forEach((file) => {\n\t\t\t\t\t\t\t\tif (['image/gif', 'image/webp', 'image/jpeg', 'image/png'].includes(file['type'])) {\n\t\t\t\t\t\t\t\t\tif (visionCapableModels.length === 0) {\n\t\t\t\t\t\t\t\t\t\ttoast.error($i18n.t('Selected model(s) do not support image inputs'));\n\t\t\t\t\t\t\t\t\t\tinputFiles = null;\n\t\t\t\t\t\t\t\t\t\tfilesInputElement.value = '';\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tlet reader = new FileReader();\n\t\t\t\t\t\t\t\t\treader.onload = (event) => {\n\t\t\t\t\t\t\t\t\t\tfiles = [\n\t\t\t\t\t\t\t\t\t\t\t...files,\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\ttype: 'image',\n\t\t\t\t\t\t\t\t\t\t\t\turl: `${event.target.result}`\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\t\t\tinputFiles = null;\n\t\t\t\t\t\t\t\t\t\tfilesInputElement.value = '';\n\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\treader.readAsDataURL(file);\n\t\t\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\t\t\tSUPPORTED_FILE_TYPE.includes(file['type']) ||\n\t\t\t\t\t\t\t\t\tSUPPORTED_FILE_EXTENSIONS.includes(file.name.split('.').at(-1))\n\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\tuploadDoc(file);\n\t\t\t\t\t\t\t\t\tfilesInputElement.value = '';\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\ttoast.error(\n\t\t\t\t\t\t\t\t\t\t$i18n.t(\n\t\t\t\t\t\t\t\t\t\t\t`Unknown File Type '{{file_type}}', but accepting and treating as plain text`,\n\t\t\t\t\t\t\t\t\t\t\t{ file_type: file['type'] }\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tuploadDoc(file);\n\t\t\t\t\t\t\t\t\tfilesInputElement.value = '';\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttoast.error($i18n.t(`File not found.`));\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t/>\n\n\t\t\t\t{#if recording}\n\t\t\t\t\t {\n\t\t\t\t\t\t\trecording = false;\n\n\t\t\t\t\t\t\tawait tick();\n\t\t\t\t\t\t\tdocument.getElementById('chat-textarea')?.focus();\n\t\t\t\t\t\t}}\n\t\t\t\t\t\ton:confirm={async (e) => {\n\t\t\t\t\t\t\tconst response = e.detail;\n\t\t\t\t\t\t\tprompt = `${prompt}${response} `;\n\n\t\t\t\t\t\t\trecording = false;\n\n\t\t\t\t\t\t\tawait tick();\n\t\t\t\t\t\t\tdocument.getElementById('chat-textarea')?.focus();\n\n\t\t\t\t\t\t\tif ($settings?.speechAutoSend ?? false) {\n\t\t\t\t\t\t\t\tsubmitPrompt(prompt);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t{:else}\n\t\t\t\t\t {\n\t\t\t\t\t\t\t// check if selectedModels support image input\n\t\t\t\t\t\t\tsubmitPrompt(prompt);\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{#if files.length > 0}\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t{#each files as file, fileIdx}\n\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t{#if file.type === 'image'}\n\t\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t{#if atSelectedModel ? visionCapableModels.length === 0 : selectedModels.length !== visionCapableModels.length}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t !visionCapableModels.includes(id))\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.join(', ')\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t{:else if file.type === 'doc'}\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{#if file.upload_status}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{:else}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{file.name}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t
{$i18n.t('Document')}
\n\t\t\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t{:else if file.type === 'collection'}\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{file?.title ?? `#${file.name}`}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t
{$i18n.t('Collection')}
\n\t\t\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t{/if}\n\n\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfiles.splice(fileIdx, 1);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfiles = files;\n\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t{/each}\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t{/if}\n\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\t\t\t\tif (availableToolIds.includes(e.id) || ($_user?.role ?? 'user') === 'admin') {\n\t\t\t\t\t\t\t\t\t\t\t\ta[e.id] = {\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: e.name,\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: e.meta.description,\n\t\t\t\t\t\t\t\t\t\t\t\t\tenabled: false\n\t\t\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\treturn a;\n\t\t\t\t\t\t\t\t\t\t}, {})}\n\t\t\t\t\t\t\t\t\t\tuploadFilesHandler={() => {\n\t\t\t\t\t\t\t\t\t\t\tfilesInputElement.click();\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\tonClose={async () => {\n\t\t\t\t\t\t\t\t\t\t\tawait tick();\n\t\t\t\t\t\t\t\t\t\t\tchatTextAreaElement?.focus();\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t
\n\n\t\t\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\t\t!$mobile ||\n\t\t\t\t\t\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t\t\t\t\t\t'ontouchstart' in window ||\n\t\t\t\t\t\t\t\t\t\t\t\tnavigator.maxTouchPoints > 0 ||\n\t\t\t\t\t\t\t\t\t\t\t\tnavigator.msMaxTouchPoints > 0\n\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\t// Prevent Enter key from creating a new line\n\t\t\t\t\t\t\t\t\t\t\tif (e.key === 'Enter' && !e.shiftKey) {\n\t\t\t\t\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t// Submit the prompt when Enter key is pressed\n\t\t\t\t\t\t\t\t\t\t\tif (prompt !== '' && e.key === 'Enter' && !e.shiftKey) {\n\t\t\t\t\t\t\t\t\t\t\t\tsubmitPrompt(prompt);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\ton:keydown={async (e) => {\n\t\t\t\t\t\t\t\t\t\tconst isCtrlPressed = e.ctrlKey || e.metaKey; // metaKey is for Cmd key on Mac\n\n\t\t\t\t\t\t\t\t\t\t// Check if Ctrl + R is pressed\n\t\t\t\t\t\t\t\t\t\tif (prompt === '' && isCtrlPressed && e.key.toLowerCase() === 'r') {\n\t\t\t\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\t\t\t\tconsole.log('regenerate');\n\n\t\t\t\t\t\t\t\t\t\t\tconst regenerateButton = [\n\t\t\t\t\t\t\t\t\t\t\t\t...document.getElementsByClassName('regenerate-response-button')\n\t\t\t\t\t\t\t\t\t\t\t]?.at(-1);\n\n\t\t\t\t\t\t\t\t\t\t\tregenerateButton?.click();\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif (prompt === '' && e.key == 'ArrowUp') {\n\t\t\t\t\t\t\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t\t\t\t\t\t\tconst userMessageElement = [\n\t\t\t\t\t\t\t\t\t\t\t\t...document.getElementsByClassName('user-message')\n\t\t\t\t\t\t\t\t\t\t\t]?.at(-1);\n\n\t\t\t\t\t\t\t\t\t\t\tconst editButton = [\n\t\t\t\t\t\t\t\t\t\t\t\t...document.getElementsByClassName('edit-user-message-button')\n\t\t\t\t\t\t\t\t\t\t\t]?.at(-1);\n\n\t\t\t\t\t\t\t\t\t\t\tconsole.log(userMessageElement);\n\n\t\t\t\t\t\t\t\t\t\t\tuserMessageElement.scrollIntoView({ block: 'center' });\n\t\t\t\t\t\t\t\t\t\t\teditButton?.click();\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif (['/', '#', '@'].includes(prompt.charAt(0)) && e.key === 'ArrowUp') {\n\t\t\t\t\t\t\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t\t\t\t\t\t\t(promptsElement || documentsElement || modelsElement).selectUp();\n\n\t\t\t\t\t\t\t\t\t\t\tconst commandOptionButton = [\n\t\t\t\t\t\t\t\t\t\t\t\t...document.getElementsByClassName('selected-command-option-button')\n\t\t\t\t\t\t\t\t\t\t\t]?.at(-1);\n\t\t\t\t\t\t\t\t\t\t\tcommandOptionButton.scrollIntoView({ block: 'center' });\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif (['/', '#', '@'].includes(prompt.charAt(0)) && e.key === 'ArrowDown') {\n\t\t\t\t\t\t\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t\t\t\t\t\t\t(promptsElement || documentsElement || modelsElement).selectDown();\n\n\t\t\t\t\t\t\t\t\t\t\tconst commandOptionButton = [\n\t\t\t\t\t\t\t\t\t\t\t\t...document.getElementsByClassName('selected-command-option-button')\n\t\t\t\t\t\t\t\t\t\t\t]?.at(-1);\n\t\t\t\t\t\t\t\t\t\t\tcommandOptionButton.scrollIntoView({ block: 'center' });\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif (['/', '#', '@'].includes(prompt.charAt(0)) && e.key === 'Enter') {\n\t\t\t\t\t\t\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t\t\t\t\t\t\tconst commandOptionButton = [\n\t\t\t\t\t\t\t\t\t\t\t\t...document.getElementsByClassName('selected-command-option-button')\n\t\t\t\t\t\t\t\t\t\t\t]?.at(-1);\n\n\t\t\t\t\t\t\t\t\t\t\tif (e.shiftKey) {\n\t\t\t\t\t\t\t\t\t\t\t\tprompt = `${prompt}\\n`;\n\t\t\t\t\t\t\t\t\t\t\t} else if (commandOptionButton) {\n\t\t\t\t\t\t\t\t\t\t\t\tcommandOptionButton?.click();\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tdocument.getElementById('send-message-button')?.click();\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif (['/', '#', '@'].includes(prompt.charAt(0)) && e.key === 'Tab') {\n\t\t\t\t\t\t\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t\t\t\t\t\t\tconst commandOptionButton = [\n\t\t\t\t\t\t\t\t\t\t\t\t...document.getElementsByClassName('selected-command-option-button')\n\t\t\t\t\t\t\t\t\t\t\t]?.at(-1);\n\n\t\t\t\t\t\t\t\t\t\t\tcommandOptionButton?.click();\n\t\t\t\t\t\t\t\t\t\t} else if (e.key === 'Tab') {\n\t\t\t\t\t\t\t\t\t\t\tconst words = findWordIndices(prompt);\n\n\t\t\t\t\t\t\t\t\t\t\tif (words.length > 0) {\n\t\t\t\t\t\t\t\t\t\t\t\tconst word = words.at(0);\n\t\t\t\t\t\t\t\t\t\t\t\tconst fullPrompt = prompt;\n\n\t\t\t\t\t\t\t\t\t\t\t\tprompt = prompt.substring(0, word?.endIndex + 1);\n\t\t\t\t\t\t\t\t\t\t\t\tawait tick();\n\n\t\t\t\t\t\t\t\t\t\t\t\te.target.scrollTop = e.target.scrollHeight;\n\t\t\t\t\t\t\t\t\t\t\t\tprompt = fullPrompt;\n\t\t\t\t\t\t\t\t\t\t\t\tawait tick();\n\n\t\t\t\t\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\t\t\t\t\te.target.setSelectionRange(word?.startIndex, word.endIndex + 1);\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\te.target.style.height = '';\n\t\t\t\t\t\t\t\t\t\t\te.target.style.height = Math.min(e.target.scrollHeight, 200) + 'px';\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif (e.key === 'Escape') {\n\t\t\t\t\t\t\t\t\t\t\tconsole.log('Escape');\n\t\t\t\t\t\t\t\t\t\t\tatSelectedModel = undefined;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\trows=\"1\"\n\t\t\t\t\t\t\t\t\ton:input={(e) => {\n\t\t\t\t\t\t\t\t\t\te.target.style.height = '';\n\t\t\t\t\t\t\t\t\t\te.target.style.height = Math.min(e.target.scrollHeight, 200) + 'px';\n\t\t\t\t\t\t\t\t\t\tuser = null;\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\ton:focus={(e) => {\n\t\t\t\t\t\t\t\t\t\te.target.style.height = '';\n\t\t\t\t\t\t\t\t\t\te.target.style.height = Math.min(e.target.scrollHeight, 200) + 'px';\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\ton:paste={(e) => {\n\t\t\t\t\t\t\t\t\t\tconst clipboardData = e.clipboardData || window.clipboardData;\n\n\t\t\t\t\t\t\t\t\t\tif (clipboardData && clipboardData.items) {\n\t\t\t\t\t\t\t\t\t\t\tfor (const item of clipboardData.items) {\n\t\t\t\t\t\t\t\t\t\t\t\tif (item.type.indexOf('image') !== -1) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst blob = item.getAsFile();\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst reader = new FileReader();\n\n\t\t\t\t\t\t\t\t\t\t\t\t\treader.onload = function (e) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfiles = [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t...files,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: 'image',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\turl: `${e.target.result}`\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\t\t\t\t\t\treader.readAsDataURL(blob);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t{#if messages.length == 0 || messages.at(-1).done == true}\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst res = await navigator.mediaDevices\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.getUserMedia({ audio: true })\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t.catch(function (err) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttoast.error(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$i18n.t(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t`Permission denied when accessing microphone: {{error}}`,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\terror: err\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (res) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trecording = true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttoast.error($i18n.t('Permission denied when accessing microphone'));\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t{#if messages.length == 0 || messages.at(-1).done == true}\n\t\t\t\t\t\t\t\t{#if prompt === ''}\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (selectedModels.length > 1) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttoast.error($i18n.t('Select only one model to call'));\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\tif ($config.audio.stt.engine === 'web') {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttoast.error(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t$i18n.t('Call feature is not supported when using Web STT engine')\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t// check if user has access to getUserMedia\n\t\t\t\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tawait navigator.mediaDevices.getUserMedia({ audio: true });\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// If the user grants the permission, proceed to show the call overlay\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tshowCallOverlay.set(true);\n\t\t\t\t\t\t\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// If the user denies the permission or an error occurs, show an error message\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttoast.error($i18n.t('Permission denied when accessing media devices'));\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t{:else}\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t\t{:else}\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\t\t\t\tstopResponse();\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t{/if}\n\n\t\t\t\t
\n\t\t\t\t\t{$i18n.t('LLMs can make mistakes. Verify important information.')}\n\t\t\t\t
\n\t\t\t\n\t\t\n\t\n\n\n\n","\n\n
\n\t{#each selectedModels as selectedModel, selectedModelIdx}\n\t\t
\n\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t ({\n\t\t\t\t\t\t\tvalue: model.id,\n\t\t\t\t\t\t\tlabel: model.name,\n\t\t\t\t\t\t\tmodel: model\n\t\t\t\t\t\t}))}\n\t\t\t\t\t\tbind:value={selectedModel}\n\t\t\t\t\t/>\n\t\t\t\t
\n\t\t\t
\n\n\t\t\t{#if selectedModelIdx === 0}\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\tselectedModels = [...selectedModels, ''];\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t{:else}\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\tselectedModels.splice(selectedModelIdx, 1);\n\t\t\t\t\t\t\t\tselectedModels = selectedModels;\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t{/if}\n\t\t
\n\t{/each}\n
\n\n{#if showSetDefault && !$mobile}\n\t
\n\t\t\n\t
\n{/if}\n","\n\n {\n\t\tif (e.detail === false) {\n\t\t\tonClose();\n\t\t}\n\t}}\n>\n\t\n\n\t
\n\t\t\n\t\t\t\n\n\t\t\t {\n\t\t\t\t\tshareHandler();\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t
{$i18n.t('Share')}
\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\n\t\t\t\t\t
{$i18n.t('Download')}
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t {\n\t\t\t\t\t\t\tdownloadJSONExport();\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t
{$i18n.t('Export chat (.json)')}
\n\t\t\t\t\t\n\t\t\t\t\t {\n\t\t\t\t\t\t\tdownloadTxt();\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t
{$i18n.t('Plain text (.txt)')}
\n\t\t\t\t\t\n\n\t\t\t\t\t {\n\t\t\t\t\t\t\tdownloadPdf();\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t
{$i18n.t('PDF document (.pdf)')}
\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\n\t\t\t
\n\n\t\t\t
\n\t\t\t\t\n\t\t\t
\n\t\t\n\t
\n\n","\n\n\n\n","\n\n {\n\t\tif (e.detail === false) {\n\t\t\tonClose();\n\t\t}\n\t}}\n>\n\t\n\n\t
\n\t\t\n\t\t\t{#each devices as device}\n\t\t\t\t {\n\t\t\t\t\t\tdispatch('change', device.deviceId);\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t{device?.label ?? 'Camera'}\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\n\t\t\t{/each}\n\t\t\n\t
\n\n","\n\n{#if $showCallOverlay}\n\t
\n\t\t\n\t\t\t
\n\t\t\t\t{#if camera}\n\t\t\t\t\t {\n\t\t\t\t\t\t\tif (assistantSpeaking) {\n\t\t\t\t\t\t\t\tstopAllAudio();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{#if emoji}\n\t\t\t\t\t\t\t 4\n\t\t\t\t\t\t\t\t\t? '4.5'\n\t\t\t\t\t\t\t\t\t: rmsLevel * 100 > 2\n\t\t\t\t\t\t\t\t\t? '4.25'\n\t\t\t\t\t\t\t\t\t: rmsLevel * 100 > 1\n\t\t\t\t\t\t\t\t\t? '3.75'\n\t\t\t\t\t\t\t\t\t: '3.5'}rem;width: 100%; text-align:center;\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{emoji}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t{:else if loading || assistantSpeaking}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t{:else}\n\t\t\t\t\t\t\t 4\n\t\t\t\t\t\t\t\t\t? ' size-[4.5rem]'\n\t\t\t\t\t\t\t\t\t: rmsLevel * 100 > 2\n\t\t\t\t\t\t\t\t\t? ' size-16'\n\t\t\t\t\t\t\t\t\t: rmsLevel * 100 > 1\n\t\t\t\t\t\t\t\t\t? 'size-14'\n\t\t\t\t\t\t\t\t\t: 'size-12'} transition-all bg-black dark:bg-white rounded-full\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t{/if}\n\n\t\t\t\t
\n\t\t\t\t\t{#if !camera}\n\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\tif (assistantSpeaking) {\n\t\t\t\t\t\t\t\t\tstopAllAudio();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{#if emoji}\n\t\t\t\t\t\t\t\t 4\n\t\t\t\t\t\t\t\t\t\t? '13'\n\t\t\t\t\t\t\t\t\t\t: rmsLevel * 100 > 2\n\t\t\t\t\t\t\t\t\t\t? '12'\n\t\t\t\t\t\t\t\t\t\t: rmsLevel * 100 > 1\n\t\t\t\t\t\t\t\t\t\t? '11.5'\n\t\t\t\t\t\t\t\t\t\t: '11'}rem;width:100%;text-align:center;\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{emoji}\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t{:else if loading || assistantSpeaking}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t{:else}\n\t\t\t\t\t\t\t\t 4\n\t\t\t\t\t\t\t\t\t\t? ' size-52'\n\t\t\t\t\t\t\t\t\t\t: rmsLevel * 100 > 2\n\t\t\t\t\t\t\t\t\t\t? 'size-48'\n\t\t\t\t\t\t\t\t\t\t: rmsLevel * 100 > 1\n\t\t\t\t\t\t\t\t\t\t? 'size-[11.5rem]'\n\t\t\t\t\t\t\t\t\t\t: 'size-44'} transition-all bg-black dark:bg-white rounded-full\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t\n\t\t\t\t\t{:else}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\n\t\t\t\t\t\t\t\n\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\t\t\tstopCamera();\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t{/if}\n\t\t\t\t\n\n\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t{#if camera}\n\t\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\t\tconsole.log(e.detail);\n\t\t\t\t\t\t\t\t\tselectedVideoInputDeviceId = e.detail;\n\t\t\t\t\t\t\t\t\tawait stopVideoStream();\n\t\t\t\t\t\t\t\t\tawait startVideoStream();\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t{:else}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\t\t\tawait navigator.mediaDevices.getUserMedia({ video: true });\n\t\t\t\t\t\t\t\t\t\tstartCamera();\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t{/if}\n\t\t\t\t\t
\n\n\t\t\t\t\t
\n\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\tif (assistantSpeaking) {\n\t\t\t\t\t\t\t\t\tstopAllAudio();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t{#if loading}\n\t\t\t\t\t\t\t\t\t{$i18n.t('Thinking...')}\n\t\t\t\t\t\t\t\t{:else if assistantSpeaking}\n\t\t\t\t\t\t\t\t\t{$i18n.t('Tap to interrupt')}\n\t\t\t\t\t\t\t\t{:else}\n\t\t\t\t\t\t\t\t\t{$i18n.t('Listening...')}\n\t\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t
\n\n\t\t\t\t\t
\n\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\tshowCallOverlay.set(false);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\n\t\t\n\t\n{/if}\n","\n\n\n\t\n\t\t{title\n\t\t\t? `${title.length > 30 ? `${title.slice(0, 30)}...` : title} | ${$WEBUI_NAME}`\n\t\t\t: `${$WEBUI_NAME}`}\n\t\n\n\n