Unverified Commit 9bcd4ce5 authored by Timothy Jaeryang Baek's avatar Timothy Jaeryang Baek Committed by GitHub
Browse files

Merge pull request #3559 from open-webui/dev

0.3.8
parents 824966ad b38abf23
...@@ -662,10 +662,11 @@ ...@@ -662,10 +662,11 @@
: rmsLevel * 100 > 1 : rmsLevel * 100 > 1
? 'size-14' ? 'size-14'
: 'size-12'} transition-all rounded-full {(model?.info?.meta : 'size-12'} transition-all rounded-full {(model?.info?.meta
?.profile_image_url ?? '/favicon.png') !== '/favicon.png' ?.profile_image_url ?? '/static/favicon.png') !== '/static/favicon.png'
? ' bg-cover bg-center bg-no-repeat' ? ' bg-cover bg-center bg-no-repeat'
: 'bg-black dark:bg-white'} bg-black dark:bg-white" : 'bg-black dark:bg-white'} bg-black dark:bg-white"
style={(model?.info?.meta?.profile_image_url ?? '/favicon.png') !== '/favicon.png' style={(model?.info?.meta?.profile_image_url ?? '/static/favicon.png') !==
'/static/favicon.png'
? `background-image: url('${model?.info?.meta?.profile_image_url}');` ? `background-image: url('${model?.info?.meta?.profile_image_url}');`
: ''} : ''}
/> />
...@@ -743,10 +744,11 @@ ...@@ -743,10 +744,11 @@
: rmsLevel * 100 > 1 : rmsLevel * 100 > 1
? 'size-[11.5rem]' ? 'size-[11.5rem]'
: 'size-44'} transition-all rounded-full {(model?.info?.meta : 'size-44'} transition-all rounded-full {(model?.info?.meta
?.profile_image_url ?? '/favicon.png') !== '/favicon.png' ?.profile_image_url ?? '/static/favicon.png') !== '/static/favicon.png'
? ' bg-cover bg-center bg-no-repeat' ? ' bg-cover bg-center bg-no-repeat'
: 'bg-black dark:bg-white'} " : 'bg-black dark:bg-white'} "
style={(model?.info?.meta?.profile_image_url ?? '/favicon.png') !== '/favicon.png' style={(model?.info?.meta?.profile_image_url ?? '/static/favicon.png') !==
'/static/favicon.png'
? `background-image: url('${model?.info?.meta?.profile_image_url}');` ? `background-image: url('${model?.info?.meta?.profile_image_url}');`
: ''} : ''}
/> />
......
...@@ -162,7 +162,7 @@ ...@@ -162,7 +162,7 @@
.substring(1) .substring(1)
.startsWith('https://youtu.be'))} .startsWith('https://youtu.be'))}
<button <button
class="px-3 py-1.5 rounded-xl w-full text-left bg-gray-100 selected-command-option-button" class="px-3 py-1.5 rounded-xl w-full text-left bg-gray-50 dark:bg-gray-850 dark:text-gray-100 selected-command-option-button"
type="button" type="button"
on:click={() => { on:click={() => {
const url = prompt.split(' ')?.at(0)?.substring(1); const url = prompt.split(' ')?.at(0)?.substring(1);
...@@ -177,7 +177,7 @@ ...@@ -177,7 +177,7 @@
} }
}} }}
> >
<div class=" font-medium text-black line-clamp-1"> <div class=" font-medium text-black dark:text-gray-100 line-clamp-1">
{prompt.split(' ')?.at(0)?.substring(1)} {prompt.split(' ')?.at(0)?.substring(1)}
</div> </div>
...@@ -185,7 +185,7 @@ ...@@ -185,7 +185,7 @@
</button> </button>
{:else if prompt.split(' ')?.at(0)?.substring(1).startsWith('http')} {:else if prompt.split(' ')?.at(0)?.substring(1).startsWith('http')}
<button <button
class="px-3 py-1.5 rounded-xl w-full text-left bg-gray-100 selected-command-option-button" class="px-3 py-1.5 rounded-xl w-full text-left bg-gray-50 dark:bg-gray-850 dark:text-gray-100 selected-command-option-button"
type="button" type="button"
on:click={() => { on:click={() => {
const url = prompt.split(' ')?.at(0)?.substring(1); const url = prompt.split(' ')?.at(0)?.substring(1);
...@@ -200,7 +200,7 @@ ...@@ -200,7 +200,7 @@
} }
}} }}
> >
<div class=" font-medium text-black line-clamp-1"> <div class=" font-medium text-black dark:text-gray-100 line-clamp-1">
{prompt.split(' ')?.at(0)?.substring(1)} {prompt.split(' ')?.at(0)?.substring(1)}
</div> </div>
......
...@@ -250,7 +250,8 @@ __builtins__.input = input`); ...@@ -250,7 +250,8 @@ __builtins__.input = input`);
stderr || stderr ||
result) && result) &&
'border-bottom-left-radius: 0px; border-bottom-right-radius: 0px;'}"><code 'border-bottom-left-radius: 0px; border-bottom-right-radius: 0px;'}"><code
class="language-{lang} rounded-t-none whitespace-pre">{@html highlightedCode || code}</code class="language-{lang} rounded-t-none whitespace-pre"
>{#if highlightedCode}{@html highlightedCode}{:else}{code}{/if}</code
></pre> ></pre>
<div <div
......
...@@ -100,64 +100,68 @@ ...@@ -100,64 +100,68 @@
class="flex snap-x snap-mandatory overflow-x-auto scrollbar-hidden" class="flex snap-x snap-mandatory overflow-x-auto scrollbar-hidden"
id="responses-container-{parentMessage.id}" id="responses-container-{parentMessage.id}"
> >
{#each Object.keys(groupedMessages) as model} {#key currentMessageId}
{#if groupedMessagesIdx[model] !== undefined && groupedMessages[model].messages.length > 0} {#each Object.keys(groupedMessages) as model}
<!-- svelte-ignore a11y-no-static-element-interactions --> {#if groupedMessagesIdx[model] !== undefined && groupedMessages[model].messages.length > 0}
<!-- svelte-ignore a11y-click-events-have-key-events --> <!-- svelte-ignore a11y-no-static-element-interactions -->
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div {@const message = groupedMessages[model].messages[groupedMessagesIdx[model]]}
class=" snap-center min-w-80 w-full max-w-full m-1 border {history.messages[
currentMessageId <div
].model === model class=" snap-center min-w-80 w-full max-w-full m-1 border {history.messages[
? 'border-gray-100 dark:border-gray-850 border-[1.5px]' currentMessageId
: 'border-gray-50 dark:border-gray-850 '} transition p-5 rounded-3xl" ].model === model
on:click={() => { ? 'border-gray-100 dark:border-gray-800 border-[1.5px]'
currentMessageId = groupedMessages[model].messages[groupedMessagesIdx[model]].id; : 'border-gray-50 dark:border-gray-850 '} transition p-5 rounded-3xl"
on:click={() => {
let messageId = groupedMessages[model].messages[groupedMessagesIdx[model]].id; if (currentMessageId != message.id) {
currentMessageId = message.id;
console.log(messageId); let messageId = message.id;
let messageChildrenIds = history.messages[messageId].childrenIds; console.log(messageId);
while (messageChildrenIds.length !== 0) { //
messageId = messageChildrenIds.at(-1); let messageChildrenIds = history.messages[messageId].childrenIds;
messageChildrenIds = history.messages[messageId].childrenIds; while (messageChildrenIds.length !== 0) {
} messageId = messageChildrenIds.at(-1);
messageChildrenIds = history.messages[messageId].childrenIds;
history.currentId = messageId; }
dispatch('change');
}} history.currentId = messageId;
> dispatch('change');
<ResponseMessage }
message={groupedMessages[model].messages[groupedMessagesIdx[model]]}
siblings={groupedMessages[model].messages.map((m) => m.id)}
isLastMessage={true}
{updateChatMessages}
{confirmEditResponseMessage}
showPreviousMessage={() => showPreviousMessage(model)}
showNextMessage={() => showNextMessage(model)}
{readOnly}
{rateMessage}
{copyToClipboard}
{continueGeneration}
regenerateResponse={async (message) => {
regenerateResponse(message);
await tick();
groupedMessagesIdx[model] = groupedMessages[model].messages.length - 1;
}} }}
on:save={async (e) => { >
console.log('save', e); <ResponseMessage
message={groupedMessages[model].messages[groupedMessagesIdx[model]]}
const message = e.detail; siblings={groupedMessages[model].messages.map((m) => m.id)}
history.messages[message.id] = message; isLastMessage={true}
await updateChatById(localStorage.token, chatId, { {updateChatMessages}
messages: messages, {confirmEditResponseMessage}
history: history showPreviousMessage={() => showPreviousMessage(model)}
}); showNextMessage={() => showNextMessage(model)}
}} {readOnly}
/> {rateMessage}
</div> {copyToClipboard}
{/if} {continueGeneration}
{/each} regenerateResponse={async (message) => {
regenerateResponse(message);
await tick();
groupedMessagesIdx[model] = groupedMessages[model].messages.length - 1;
}}
on:save={async (e) => {
console.log('save', e);
const message = e.detail;
history.messages[message.id] = message;
await updateChatById(localStorage.token, chatId, {
messages: messages,
history: history
});
}}
/>
</div>
{/if}
{/each}
{/key}
</div> </div>
</div> </div>
<div class=" self-center font-bold mb-0.5 line-clamp-1 contents"> <div class=" self-center font-semibold mb-0.5 line-clamp-1 contents">
<slot /> <slot />
</div> </div>
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
</div> </div>
<div <div
class=" mt-2 mb-4 text-3xl text-gray-800 dark:text-gray-100 font-semibold text-left flex items-center gap-4" class=" mt-2 mb-4 text-3xl text-gray-800 dark:text-gray-100 font-semibold text-left flex items-center gap-4 font-primary"
> >
<div> <div>
<div class=" capitalize line-clamp-1" in:fade={{ duration: 200 }}> <div class=" capitalize line-clamp-1" in:fade={{ duration: 200 }}>
...@@ -102,7 +102,7 @@ ...@@ -102,7 +102,7 @@
</div> </div>
{/if} {/if}
{:else} {:else}
<div class=" font-medium text-gray-400 dark:text-gray-500 line-clamp-1"> <div class=" font-medium text-gray-400 dark:text-gray-500 line-clamp-1 font-p">
{$i18n.t('How can I help you today?')} {$i18n.t('How can I help you today?')}
</div> </div>
{/if} {/if}
...@@ -110,7 +110,7 @@ ...@@ -110,7 +110,7 @@
</div> </div>
</div> </div>
<div class=" w-full" in:fade={{ duration: 200, delay: 300 }}> <div class=" w-full font-primary" in:fade={{ duration: 200, delay: 300 }}>
<Suggestions <Suggestions
suggestionPrompts={models[selectedModelIdx]?.info?.meta?.suggestion_prompts ?? suggestionPrompts={models[selectedModelIdx]?.info?.meta?.suggestion_prompts ??
$config.default_prompt_suggestions} $config.default_prompt_suggestions}
......
...@@ -152,7 +152,10 @@ ...@@ -152,7 +152,10 @@
} }
tooltipInstance = tippy(`#info-${message.id}`, { tooltipInstance = tippy(`#info-${message.id}`, {
content: `<span class="text-xs" id="tooltip-${message.id}">${tooltipContent}</span>`, content: `<span class="text-xs" id="tooltip-${message.id}">${tooltipContent}</span>`,
allowHTML: true allowHTML: true,
theme: 'dark',
arrow: false,
offset: [0, 4]
}); });
} }
}; };
......
...@@ -2,32 +2,25 @@ ...@@ -2,32 +2,25 @@
import ChevronDown from '$lib/components/icons/ChevronDown.svelte'; import ChevronDown from '$lib/components/icons/ChevronDown.svelte';
import ChevronUp from '$lib/components/icons/ChevronUp.svelte'; import ChevronUp from '$lib/components/icons/ChevronUp.svelte';
import MagnifyingGlass from '$lib/components/icons/MagnifyingGlass.svelte'; import MagnifyingGlass from '$lib/components/icons/MagnifyingGlass.svelte';
import { Collapsible } from 'bits-ui'; import Collapsible from '$lib/components/common/Collapsible.svelte';
import { slide } from 'svelte/transition';
export let status = { urls: [], query: '' }; export let status = { urls: [], query: '' };
let state = false; let state = false;
</script> </script>
<Collapsible.Root class="w-full space-y-1" bind:open={state}> <Collapsible bind:open={state} className="w-full space-y-1">
<Collapsible.Trigger> <div
<div class="flex items-center gap-2 text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition"
class="flex items-center gap-2 text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition"
>
<slot />
{#if state}
<ChevronUp strokeWidth="3.5" className="size-3.5 " />
{:else}
<ChevronDown strokeWidth="3.5" className="size-3.5 " />
{/if}
</div>
</Collapsible.Trigger>
<Collapsible.Content
class=" text-sm border border-gray-300/30 dark:border-gray-700/50 rounded-xl"
transition={slide}
> >
<slot />
{#if state}
<ChevronUp strokeWidth="3.5" className="size-3.5 " />
{:else}
<ChevronDown strokeWidth="3.5" className="size-3.5 " />
{/if}
</div>
<div class="text-sm border border-gray-300/30 dark:border-gray-700/50 rounded-xl" slot="content">
{#if status?.query} {#if status?.query}
<a <a
href="https://www.google.com/search?q={status.query}" href="https://www.google.com/search?q={status.query}"
...@@ -93,5 +86,5 @@ ...@@ -93,5 +86,5 @@
</div> </div>
</a> </a>
{/each} {/each}
</Collapsible.Content> </div>
</Collapsible.Root> </Collapsible>
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
} }
</script> </script>
<div class="flex flex-col w-full items-center md:items-start"> <div class="flex flex-col w-full items-start">
{#each selectedModels as selectedModel, selectedModelIdx} {#each selectedModels as selectedModel, selectedModelIdx}
<div class="flex w-full max-w-fit"> <div class="flex w-full max-w-fit">
<div class="overflow-hidden w-full"> <div class="overflow-hidden w-full">
...@@ -103,7 +103,7 @@ ...@@ -103,7 +103,7 @@
</div> </div>
{#if showSetDefault && !$mobile} {#if showSetDefault && !$mobile}
<div class="text-left mt-0.5 ml-1 text-[0.7rem] text-gray-500"> <div class="text-left mt-0.5 ml-1 text-[0.7rem] text-gray-500 font-primary">
<button on:click={saveDefaultModel}> {$i18n.t('Set as default')}</button> <button on:click={saveDefaultModel}> {$i18n.t('Set as default')}</button>
</div> </div>
{/if} {/if}
...@@ -206,7 +206,7 @@ ...@@ -206,7 +206,7 @@
}} }}
closeFocus={false} closeFocus={false}
> >
<DropdownMenu.Trigger class="relative w-full" aria-label={placeholder}> <DropdownMenu.Trigger class="relative w-full font-primary" aria-label={placeholder}>
<div <div
class="flex w-full text-left px-0.5 outline-none bg-transparent truncate text-lg font-semibold placeholder-gray-400 focus:outline-none" class="flex w-full text-left px-0.5 outline-none bg-transparent truncate text-lg font-semibold placeholder-gray-400 focus:outline-none"
> >
...@@ -222,7 +222,7 @@ ...@@ -222,7 +222,7 @@
<DropdownMenu.Content <DropdownMenu.Content
class=" z-40 {$mobile class=" z-40 {$mobile
? `w-full` ? `w-full`
: `${className}`} max-w-[calc(100vw-1rem)] justify-start rounded-xl bg-white dark:bg-gray-850 dark:text-white shadow-lg border border-gray-300/30 dark:border-gray-850/50 outline-none " : `${className}`} max-w-[calc(100vw-1rem)] justify-start rounded-xl bg-white dark:bg-gray-850 dark:text-white shadow-lg border border-gray-300/30 dark:border-gray-700/40 outline-none"
transition={flyAndScale} transition={flyAndScale}
side={$mobile ? 'bottom' : 'bottom-start'} side={$mobile ? 'bottom' : 'bottom-start'}
sideOffset={4} sideOffset={4}
...@@ -260,7 +260,7 @@ ...@@ -260,7 +260,7 @@
<div class="flex gap-0.5 self-start h-full mb-0.5 -translate-x-1"> <div class="flex gap-0.5 self-start h-full mb-0.5 -translate-x-1">
{#each item.model?.info?.meta.tags as tag} {#each item.model?.info?.meta.tags as tag}
<div <div
class=" text-xs font-black px-1 rounded uppercase line-clamp-1 bg-gray-500/20 text-gray-700 dark:text-gray-200" class=" text-xs font-bold px-1 rounded uppercase line-clamp-1 bg-gray-500/20 text-gray-700 dark:text-gray-200"
> >
{tag.name} {tag.name}
</div> </div>
...@@ -299,7 +299,7 @@ ...@@ -299,7 +299,7 @@
<div class="flex gap-0.5 self-center items-center h-full translate-y-[0.5px]"> <div class="flex gap-0.5 self-center items-center h-full translate-y-[0.5px]">
{#each item.model?.info?.meta.tags as tag} {#each item.model?.info?.meta.tags as tag}
<div <div
class=" text-xs font-black px-1 rounded uppercase line-clamp-1 bg-gray-500/20 text-gray-700 dark:text-gray-200" class=" text-xs font-bold px-1 rounded uppercase line-clamp-1 bg-gray-500/20 text-gray-700 dark:text-gray-200"
> >
{tag.name} {tag.name}
</div> </div>
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Seed')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('Seed')}</div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.seed = (params?.seed ?? null) === null ? 0 : null; params.seed = (params?.seed ?? null) === null ? 0 : null;
...@@ -79,7 +79,7 @@ ...@@ -79,7 +79,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Stop Sequence')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('Stop Sequence')}</div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.stop = (params?.stop ?? null) === null ? '' : null; params.stop = (params?.stop ?? null) === null ? '' : null;
...@@ -113,7 +113,7 @@ ...@@ -113,7 +113,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Temperature')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('Temperature')}</div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.temperature = (params?.temperature ?? null) === null ? 0.8 : null; params.temperature = (params?.temperature ?? null) === null ? 0.8 : null;
...@@ -159,7 +159,7 @@ ...@@ -159,7 +159,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Mirostat')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('Mirostat')}</div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.mirostat = (params?.mirostat ?? null) === null ? 0 : null; params.mirostat = (params?.mirostat ?? null) === null ? 0 : null;
...@@ -205,7 +205,7 @@ ...@@ -205,7 +205,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Mirostat Eta')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('Mirostat Eta')}</div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.mirostat_eta = (params?.mirostat_eta ?? null) === null ? 0.1 : null; params.mirostat_eta = (params?.mirostat_eta ?? null) === null ? 0.1 : null;
...@@ -251,7 +251,7 @@ ...@@ -251,7 +251,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Mirostat Tau')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('Mirostat Tau')}</div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.mirostat_tau = (params?.mirostat_tau ?? null) === null ? 5.0 : null; params.mirostat_tau = (params?.mirostat_tau ?? null) === null ? 5.0 : null;
...@@ -297,7 +297,7 @@ ...@@ -297,7 +297,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Top K')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('Top K')}</div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.top_k = (params?.top_k ?? null) === null ? 40 : null; params.top_k = (params?.top_k ?? null) === null ? 40 : null;
...@@ -343,7 +343,7 @@ ...@@ -343,7 +343,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Top P')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('Top P')}</div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.top_p = (params?.top_p ?? null) === null ? 0.9 : null; params.top_p = (params?.top_p ?? null) === null ? 0.9 : null;
...@@ -389,7 +389,7 @@ ...@@ -389,7 +389,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Frequency Penalty')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('Frequency Penalty')}</div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.frequency_penalty = (params?.frequency_penalty ?? null) === null ? 1.1 : null; params.frequency_penalty = (params?.frequency_penalty ?? null) === null ? 1.1 : null;
...@@ -435,7 +435,7 @@ ...@@ -435,7 +435,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Repeat Last N')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('Repeat Last N')}</div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.repeat_last_n = (params?.repeat_last_n ?? null) === null ? 64 : null; params.repeat_last_n = (params?.repeat_last_n ?? null) === null ? 64 : null;
...@@ -481,7 +481,7 @@ ...@@ -481,7 +481,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Tfs Z')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('Tfs Z')}</div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.tfs_z = (params?.tfs_z ?? null) === null ? 1 : null; params.tfs_z = (params?.tfs_z ?? null) === null ? 1 : null;
...@@ -527,7 +527,7 @@ ...@@ -527,7 +527,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Context Length')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('Context Length')}</div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.num_ctx = (params?.num_ctx ?? null) === null ? 2048 : null; params.num_ctx = (params?.num_ctx ?? null) === null ? 2048 : null;
...@@ -572,7 +572,7 @@ ...@@ -572,7 +572,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Batch Size (num_batch)')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('Batch Size (num_batch)')}</div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.num_batch = (params?.num_batch ?? null) === null ? 512 : null; params.num_batch = (params?.num_batch ?? null) === null ? 512 : null;
...@@ -619,7 +619,7 @@ ...@@ -619,7 +619,7 @@
</div> </div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.num_keep = (params?.num_keep ?? null) === null ? 24 : null; params.num_keep = (params?.num_keep ?? null) === null ? 24 : null;
...@@ -664,7 +664,7 @@ ...@@ -664,7 +664,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Max Tokens (num_predict)')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('Max Tokens (num_predict)')}</div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.max_tokens = (params?.max_tokens ?? null) === null ? 128 : null; params.max_tokens = (params?.max_tokens ?? null) === null ? 128 : null;
...@@ -711,7 +711,7 @@ ...@@ -711,7 +711,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('use_mmap (Ollama)')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('use_mmap (Ollama)')}</div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.use_mmap = (params?.use_mmap ?? null) === null ? true : null; params.use_mmap = (params?.use_mmap ?? null) === null ? true : null;
...@@ -731,7 +731,7 @@ ...@@ -731,7 +731,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('use_mlock (Ollama)')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('use_mlock (Ollama)')}</div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.use_mlock = (params?.use_mlock ?? null) === null ? true : null; params.use_mlock = (params?.use_mlock ?? null) === null ? true : null;
...@@ -751,7 +751,7 @@ ...@@ -751,7 +751,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('num_thread (Ollama)')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('num_thread (Ollama)')}</div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.num_thread = (params?.num_thread ?? null) === null ? 2 : null; params.num_thread = (params?.num_thread ?? null) === null ? 2 : null;
...@@ -797,7 +797,7 @@ ...@@ -797,7 +797,7 @@
<div class=" self-center text-xs font-medium">{$i18n.t('Template')}</div> <div class=" self-center text-xs font-medium">{$i18n.t('Template')}</div>
<button <button
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition flex-shrink-0 outline-none"
type="button" type="button"
on:click={() => { on:click={() => {
params.template = (params?.template ?? null) === null ? '' : null; params.template = (params?.template ?? null) === null ? '' : null;
......
...@@ -95,6 +95,8 @@ ...@@ -95,6 +95,8 @@
} }
if (themeToApply === 'dark' && !_theme.includes('oled')) { if (themeToApply === 'dark' && !_theme.includes('oled')) {
document.documentElement.style.setProperty('--color-gray-800', '#333');
document.documentElement.style.setProperty('--color-gray-850', '#262626');
document.documentElement.style.setProperty('--color-gray-900', '#171717'); document.documentElement.style.setProperty('--color-gray-900', '#171717');
document.documentElement.style.setProperty('--color-gray-950', '#0d0d0d'); document.documentElement.style.setProperty('--color-gray-950', '#0d0d0d');
} }
...@@ -118,6 +120,8 @@ ...@@ -118,6 +120,8 @@
theme.set(_theme); theme.set(_theme);
localStorage.setItem('theme', _theme); localStorage.setItem('theme', _theme);
if (_theme.includes('oled')) { if (_theme.includes('oled')) {
document.documentElement.style.setProperty('--color-gray-800', '#101010');
document.documentElement.style.setProperty('--color-gray-850', '#050505');
document.documentElement.style.setProperty('--color-gray-900', '#000000'); document.documentElement.style.setProperty('--color-gray-900', '#000000');
document.documentElement.style.setProperty('--color-gray-950', '#000000'); document.documentElement.style.setProperty('--color-gray-950', '#000000');
document.documentElement.classList.add('dark'); document.documentElement.classList.add('dark');
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
import ManageModal from './Personalization/ManageModal.svelte'; import ManageModal from './Personalization/ManageModal.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte'; import Tooltip from '$lib/components/common/Tooltip.svelte';
import Spinner from '$lib/components/common/Spinner.svelte'; import Spinner from '$lib/components/common/Spinner.svelte';
import Switch from '$lib/components/common/Switch.svelte';
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
...@@ -185,7 +186,10 @@ ...@@ -185,7 +186,10 @@
class="p-1 px-3 text-xs flex rounded transition" class="p-1 px-3 text-xs flex rounded transition"
type="button" type="button"
on:click={() => { on:click={() => {
valves[property] = (valves[property] ?? null) === null ? '' : null; valves[property] =
(valves[property] ?? null) === null
? valvesSpec.properties[property]?.default ?? ''
: null;
}} }}
> >
{#if (valves[property] ?? null) === null} {#if (valves[property] ?? null) === null}
...@@ -203,16 +207,40 @@ ...@@ -203,16 +207,40 @@
</div> </div>
{#if (valves[property] ?? null) !== null} {#if (valves[property] ?? null) !== null}
<!-- {valves[property]} -->
<div class="flex mt-0.5 mb-1.5 space-x-2"> <div class="flex mt-0.5 mb-1.5 space-x-2">
<div class=" flex-1"> <div class=" flex-1">
<input {#if valvesSpec.properties[property]?.enum ?? null}
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none" <select
type="text" class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
placeholder={valvesSpec.properties[property].title} bind:value={valves[property]}
bind:value={valves[property]} >
autocomplete="off" {#each valvesSpec.properties[property].enum as option}
required <option value={option} selected={option === valves[property]}>
/> {option}
</option>
{/each}
</select>
{:else if (valvesSpec.properties[property]?.type ?? null) === 'boolean'}
<div class="flex justify-between items-center">
<div class="text-xs text-gray-500">
{valves[property] ? 'Enabled' : 'Disabled'}
</div>
<div class=" pr-2">
<Switch bind:state={valves[property]} />
</div>
</div>
{:else}
<input
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
type="text"
placeholder={valvesSpec.properties[property].title}
bind:value={valves[property]}
autocomplete="off"
required
/>
{/if}
</div> </div>
</div> </div>
{/if} {/if}
......
<script lang="ts"> <script lang="ts">
import { getContext } from 'svelte'; import { getContext, tick } from 'svelte';
import { toast } from 'svelte-sonner'; import { toast } from 'svelte-sonner';
import { models, settings, user } from '$lib/stores'; import { models, settings, user } from '$lib/stores';
import { updateUserSettings } from '$lib/apis/users';
import { getModels as _getModels } from '$lib/apis'; import { getModels as _getModels } from '$lib/apis';
import { goto } from '$app/navigation';
import Modal from '../common/Modal.svelte'; import Modal from '../common/Modal.svelte';
import Account from './Settings/Account.svelte'; import Account from './Settings/Account.svelte';
...@@ -14,8 +15,6 @@ ...@@ -14,8 +15,6 @@
import Chats from './Settings/Chats.svelte'; import Chats from './Settings/Chats.svelte';
import User from '../icons/User.svelte'; import User from '../icons/User.svelte';
import Personalization from './Settings/Personalization.svelte'; import Personalization from './Settings/Personalization.svelte';
import { updateUserSettings } from '$lib/apis/users';
import { goto } from '$app/navigation';
import Valves from './Settings/Valves.svelte'; import Valves from './Settings/Valves.svelte';
const i18n = getContext('i18n'); const i18n = getContext('i18n');
...@@ -34,6 +33,37 @@ ...@@ -34,6 +33,37 @@
}; };
let selectedTab = 'general'; let selectedTab = 'general';
// Function to handle sideways scrolling
const scrollHandler = (event) => {
const settingsTabsContainer = document.getElementById('settings-tabs-container');
if (settingsTabsContainer) {
event.preventDefault(); // Prevent default vertical scrolling
settingsTabsContainer.scrollLeft += event.deltaY; // Scroll sideways
}
};
const addScrollListener = async () => {
await tick();
const settingsTabsContainer = document.getElementById('settings-tabs-container');
if (settingsTabsContainer) {
settingsTabsContainer.addEventListener('wheel', scrollHandler);
}
};
const removeScrollListener = async () => {
await tick();
const settingsTabsContainer = document.getElementById('settings-tabs-container');
if (settingsTabsContainer) {
settingsTabsContainer.removeEventListener('wheel', scrollHandler);
}
};
$: if (show) {
addScrollListener();
} else {
removeScrollListener();
}
</script> </script>
<Modal bind:show> <Modal bind:show>
...@@ -61,6 +91,7 @@ ...@@ -61,6 +91,7 @@
<div class="flex flex-col md:flex-row w-full p-4 md:space-x-4"> <div class="flex flex-col md:flex-row w-full p-4 md:space-x-4">
<div <div
id="settings-tabs-container"
class="tabs flex flex-row overflow-x-auto space-x-1 md:space-x-0 md:space-y-1 md:flex-col flex-1 md:flex-none md:w-40 dark:text-gray-200 text-xs text-left mb-3 md:mb-0" class="tabs flex flex-row overflow-x-auto space-x-1 md:space-x-0 md:space-y-1 md:flex-col flex-1 md:flex-none md:w-40 dark:text-gray-200 text-xs text-left mb-3 md:mb-0"
> >
<button <button
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
getTagsById, getTagsById,
updateChatById updateChatById
} from '$lib/apis/chats'; } from '$lib/apis/chats';
import { tags as _tags, chats } from '$lib/stores'; import { tags as _tags, chats, pinnedChats } from '$lib/stores';
import { createEventDispatcher, onMount } from 'svelte'; import { createEventDispatcher, onMount } from 'svelte';
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
...@@ -19,9 +19,11 @@ ...@@ -19,9 +19,11 @@
let tags = []; let tags = [];
const getTags = async () => { const getTags = async () => {
return await getTagsById(localStorage.token, chatId).catch(async (error) => { return (
return []; await getTagsById(localStorage.token, chatId).catch(async (error) => {
}); return [];
})
).filter((tag) => tag.name !== 'pinned');
}; };
const addTag = async (tagName) => { const addTag = async (tagName) => {
...@@ -33,6 +35,7 @@ ...@@ -33,6 +35,7 @@
}); });
_tags.set(await getAllChatTags(localStorage.token)); _tags.set(await getAllChatTags(localStorage.token));
await pinnedChats.set(await getChatListByTagName(localStorage.token, 'pinned'));
}; };
const deleteTag = async (tagName) => { const deleteTag = async (tagName) => {
...@@ -44,19 +47,23 @@ ...@@ -44,19 +47,23 @@
}); });
console.log($_tags); console.log($_tags);
await _tags.set(await getAllChatTags(localStorage.token)); await _tags.set(await getAllChatTags(localStorage.token));
console.log($_tags); console.log($_tags);
if ($_tags.map((t) => t.name).includes(tagName)) { if ($_tags.map((t) => t.name).includes(tagName)) {
await chats.set(await getChatListByTagName(localStorage.token, tagName)); if (tagName === 'pinned') {
await pinnedChats.set(await getChatListByTagName(localStorage.token, 'pinned'));
} else {
await chats.set(await getChatListByTagName(localStorage.token, tagName));
}
if ($chats.find((chat) => chat.id === chatId)) { if ($chats.find((chat) => chat.id === chatId)) {
dispatch('close'); dispatch('close');
} }
} else { } else {
await chats.set(await getChatList(localStorage.token)); await chats.set(await getChatList(localStorage.token));
await pinnedChats.set(await getChatListByTagName(localStorage.token, 'pinned'));
} }
}; };
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
<div class=" flex flex-col md:flex-row md:items-center flex-1 text-sm w-fit gap-1.5"> <div class=" flex flex-col md:flex-row md:items-center flex-1 text-sm w-fit gap-1.5">
<div class="flex justify-between self-start"> <div class="flex justify-between self-start">
<div <div
class=" text-xs font-black {classNames[banner.type] ?? class=" text-xs font-bold {classNames[banner.type] ??
classNames['info']} w-fit px-2 rounded uppercase line-clamp-1 mr-0.5" classNames['info']} w-fit px-2 rounded uppercase line-clamp-1 mr-0.5"
> >
{banner.type} {banner.type}
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
{#if banner.url} {#if banner.url}
<div class="flex md:hidden group w-fit md:items-center"> <div class="flex md:hidden group w-fit md:items-center">
<a <a
class="text-gray-700 dark:text-white text-xs font-bold underline" class="text-gray-700 dark:text-white text-xs font-semibold underline"
href="/assets/files/whitepaper.pdf" href="/assets/files/whitepaper.pdf"
target="_blank">Learn More</a target="_blank">Learn More</a
> >
...@@ -88,7 +88,7 @@ ...@@ -88,7 +88,7 @@
{#if banner.url} {#if banner.url}
<div class="hidden md:flex group w-fit md:items-center"> <div class="hidden md:flex group w-fit md:items-center">
<a <a
class="text-gray-700 dark:text-white text-xs font-bold underline" class="text-gray-700 dark:text-white text-xs font-semibold underline"
href="/" href="/"
target="_blank">Learn More</a target="_blank">Learn More</a
> >
...@@ -116,7 +116,8 @@ ...@@ -116,7 +116,8 @@
on:click={() => { on:click={() => {
dismiss(banner.id); dismiss(banner.id);
}} }}
class=" -mt-[3px] ml-1.5 mr-1 text-gray-400 dark:hover:text-white h-1">&times;</button class=" -mt-1 -mb-2 -translate-y-[1px] ml-1.5 mr-1 text-gray-400 dark:hover:text-white"
>&times;</button
> >
{/if} {/if}
</div> </div>
......
<script lang="ts">
import { slide } from 'svelte/transition';
import { quintOut } from 'svelte/easing';
export let open = false;
export let className = '';
</script>
<div class={className}>
<button on:click={() => (open = !open)}>
<slot />
</button>
{#if open}
<div transition:slide={{ duration: 300, easing: quintOut, axis: 'y' }}>
<slot name="content" />
</div>
{/if}
</div>
...@@ -7,8 +7,8 @@ ...@@ -7,8 +7,8 @@
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
export let title = $i18n.t('Confirm your action'); export let title = '';
export let message = $i18n.t('This action cannot be undone. Do you wish to continue?'); export let message = '';
export let cancelLabel = $i18n.t('Cancel'); export let cancelLabel = $i18n.t('Cancel');
export let confirmLabel = $i18n.t('Confirm'); export let confirmLabel = $i18n.t('Confirm');
...@@ -58,11 +58,21 @@ ...@@ -58,11 +58,21 @@
}} }}
> >
<div class="px-[1.75rem] py-6"> <div class="px-[1.75rem] py-6">
<div class=" text-lg font-semibold dark:text-gray-200 mb-2.5">{title}</div> <div class=" text-lg font-semibold dark:text-gray-200 mb-2.5">
{#if title !== ''}
{title}
{:else}
{$i18n.t('Confirm your action')}
{/if}
</div>
<slot> <slot>
<div class=" text-sm text-gray-500"> <div class=" text-sm text-gray-500">
{message} {#if message !== ''}
{message}
{:else}
{$i18n.t('This action cannot be undone. Do you wish to continue?')}
{/if}
</div> </div>
</slot> </slot>
...@@ -71,6 +81,7 @@ ...@@ -71,6 +81,7 @@
class="bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-white font-medium w-full py-2.5 rounded-lg transition" class="bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-white font-medium w-full py-2.5 rounded-lg transition"
on:click={() => { on:click={() => {
show = false; show = false;
dispatch('cancel');
}} }}
type="button" type="button"
> >
......
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
<div <div
class=" m-auto rounded-2xl max-w-full {sizeToWidth( class=" m-auto rounded-2xl max-w-full {sizeToWidth(
size size
)} mx-2 bg-gray-50 dark:bg-gray-900 shadow-3xl" )} mx-2 bg-gray-50 dark:bg-gray-900 shadow-3xl max-h-[100dvh] overflow-y-auto scrollbar-hidden"
in:flyAndScale in:flyAndScale
on:mousedown={(e) => { on:mousedown={(e) => {
e.stopPropagation(); e.stopPropagation();
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
<ChevronDown className="absolute end-2 top-1/2 -translate-y-[45%] size-3.5" strokeWidth="2.5" /> <ChevronDown className="absolute end-2 top-1/2 -translate-y-[45%] size-3.5" strokeWidth="2.5" />
</Select.Trigger> </Select.Trigger>
<Select.Content <Select.Content
class="w-full rounded-lg bg-white dark:bg-gray-900 dark:text-white shadow-lg border border-gray-300/30 dark:border-gray-850/50 outline-none" class="w-full rounded-lg bg-white dark:bg-gray-900 dark:text-white shadow-lg border border-gray-300/30 dark:border-gray-700/40 outline-none"
transition={flyAndScale} transition={flyAndScale}
sideOffset={4} sideOffset={4}
> >
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment