diff --git a/tools/server/public/index.html.gz b/tools/server/public/index.html.gz index 48e341dbd12..e70327a5c1e 100644 Binary files a/tools/server/public/index.html.gz and b/tools/server/public/index.html.gz differ diff --git a/tools/server/webui/src/app.css b/tools/server/webui/src/app.css index 2ca1536409b..6f35911d5f6 100644 --- a/tools/server/webui/src/app.css +++ b/tools/server/webui/src/app.css @@ -114,6 +114,9 @@ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); --color-sidebar-border: var(--sidebar-border); --color-sidebar-ring: var(--sidebar-ring); + --breakpoint-3xl: 120rem; /* 1920px */ + --breakpoint-4xl: 150rem; /* 2400px */ + --breakpoint-5xl: 180rem; /* 2880px */ } @layer base { diff --git a/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatForm.svelte b/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatForm.svelte index 6c9a11849c3..4af4101f0a0 100644 --- a/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatForm.svelte +++ b/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatForm.svelte @@ -7,6 +7,7 @@ ChatFormHelperText, ChatFormTextarea } from '$lib/components/app'; + import { MAX_WIDTH_CLASSES, DEFAULT_MAX_WIDTH_CLASS } from '$lib/constants/width-classes'; import { INPUT_CLASSES } from '$lib/constants/input-classes'; import { config } from '$lib/stores/settings.svelte'; import { FileTypeCategory, MimeTypeApplication } from '$lib/enums/files'; @@ -62,6 +63,9 @@ let previousIsLoading = $state(isLoading); let recordingSupported = $state(false); let textareaRef: ChatFormTextarea | undefined = $state(undefined); + let maxWidthClass = $derived( + currentConfig.responsiveChatWidth ? MAX_WIDTH_CLASSES : DEFAULT_MAX_WIDTH_CLASS + ); function getAcceptStringForFileType(fileType: FileTypeCategory): string { switch (fileType) { @@ -230,7 +234,7 @@
+
{processingState.getProcessingMessage()} @@ -220,7 +225,7 @@
{:else if message.role === 'assistant'} {#if config().disableReasoningFormat} -
{messageContent || ''}
+
{messageContent || ''}
{:else} {/if} @@ -375,7 +380,6 @@ .raw-output { width: 100%; - max-width: 48rem; margin-top: 1.5rem; padding: 1rem 1.25rem; border-radius: 1rem; diff --git a/tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessages.svelte b/tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessages.svelte index 45efeeb436f..1dc4a49a54b 100644 --- a/tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessages.svelte +++ b/tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessages.svelte @@ -9,7 +9,9 @@ editAssistantMessage, regenerateMessageWithBranching } from '$lib/stores/chat.svelte'; + import { config } from '$lib/stores/settings.svelte'; import { getMessageSiblings } from '$lib/utils/branching'; + import { MAX_WIDTH_CLASSES, DEFAULT_MAX_WIDTH_CLASS } from '$lib/constants/width-classes'; interface Props { class?: string; @@ -21,6 +23,10 @@ let allConversationMessages = $state([]); + let maxWidthClass = $derived( + config().responsiveChatWidth ? MAX_WIDTH_CLASSES : DEFAULT_MAX_WIDTH_CLASS + ); + function refreshAllMessages() { const conversation = activeConversation(); @@ -103,7 +109,7 @@
{#each displayMessages as { message, siblingInfo } (message.id)} { @@ -77,7 +81,7 @@
-
+
{#each processingDetails as detail (detail)} {detail} {/each} @@ -108,7 +112,6 @@ align-items: center; gap: 1rem; justify-content: center; - max-width: 48rem; margin: 0 auto; } diff --git a/tools/server/webui/src/lib/components/app/chat/ChatScreen/ChatScreen.svelte b/tools/server/webui/src/lib/components/app/chat/ChatScreen/ChatScreen.svelte index 0c754faa882..552101e3c91 100644 --- a/tools/server/webui/src/lib/components/app/chat/ChatScreen/ChatScreen.svelte +++ b/tools/server/webui/src/lib/components/app/chat/ChatScreen/ChatScreen.svelte @@ -14,6 +14,8 @@ ConfirmationDialog } from '$lib/components/app'; import * as AlertDialog from '$lib/components/ui/alert-dialog'; + import { config } from '$lib/stores/settings.svelte'; + import { MAX_WIDTH_CLASSES, DEFAULT_MAX_WIDTH_CLASS } from '$lib/constants/width-classes'; import { AUTO_SCROLL_AT_BOTTOM_THRESHOLD, AUTO_SCROLL_INTERVAL, @@ -85,6 +87,10 @@ let isCurrentConversationLoading = $derived(isLoading()); + let maxWidthClass = $derived( + config().responsiveChatWidth ? MAX_WIDTH_CLASSES : DEFAULT_MAX_WIDTH_CLASS + ); + async function handleDeleteConfirm() { const conversation = activeConversation(); if (conversation) { @@ -302,7 +308,7 @@ {#if serverWarning()} - + {/if}
@@ -333,7 +339,7 @@ ondrop={handleDrop} role="main" > -
+

llama.cpp

diff --git a/tools/server/webui/src/lib/components/app/chat/ChatSettings/ChatSettingsDialog.svelte b/tools/server/webui/src/lib/components/app/chat/ChatSettings/ChatSettingsDialog.svelte index d2a0a739c54..cd4a8cf3c6d 100644 --- a/tools/server/webui/src/lib/components/app/chat/ChatSettings/ChatSettingsDialog.svelte +++ b/tools/server/webui/src/lib/components/app/chat/ChatSettings/ChatSettingsDialog.svelte @@ -52,6 +52,11 @@ { value: 'dark', label: 'Dark', icon: Moon } ] }, + { + key: 'responsiveChatWidth', + label: 'Responsive chat width', + type: 'checkbox' + }, { key: 'showMessageStats', label: 'Show message generation statistics', diff --git a/tools/server/webui/src/lib/constants/settings-config.ts b/tools/server/webui/src/lib/constants/settings-config.ts index 7547832d95a..350186ebeb0 100644 --- a/tools/server/webui/src/lib/constants/settings-config.ts +++ b/tools/server/webui/src/lib/constants/settings-config.ts @@ -9,6 +9,7 @@ export const SETTING_CONFIG_DEFAULT: Record = showToolCalls: false, disableReasoningFormat: false, keepStatsVisible: false, + responsiveChatWidth: false, showMessageStats: true, askForTitleConfirmation: false, pasteLongTextToFileLen: 2500, @@ -86,6 +87,8 @@ export const SETTING_CONFIG_INFO: Record = { disableReasoningFormat: 'Show raw LLM output without backend parsing and frontend Markdown rendering to inspect streaming across different models.', keepStatsVisible: 'Keep processing statistics visible after generation finishes.', + responsiveChatWidth: + 'Enable responsive chat width that adapts to your screen size. When disabled, uses a fixed width optimized for readability.', showMessageStats: 'Display generation statistics (tokens/second, token count, duration) below each assistant message.', askForTitleConfirmation: diff --git a/tools/server/webui/src/lib/constants/width-classes.ts b/tools/server/webui/src/lib/constants/width-classes.ts new file mode 100644 index 00000000000..12cca05d850 --- /dev/null +++ b/tools/server/webui/src/lib/constants/width-classes.ts @@ -0,0 +1,4 @@ +export const MAX_WIDTH_CLASSES = + 'max-w-[48rem] md:max-w-[60rem] xl:max-w-[70rem] 2xl:max-w-[80rem] 3xl:max-w-[90rem] 4xl:max-w-[100rem] 5xl:max-w-[150rem]'; + +export const DEFAULT_MAX_WIDTH_CLASS = 'max-w-[48rem]';