diff --git a/tools/server/public/index.html.gz b/tools/server/public/index.html.gz
index ae2c8f77a7..f4ff57b4c9 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/docs/flows/settings-flow.md b/tools/server/webui/docs/flows/settings-flow.md
index 578e01e6e1..474aef01b0 100644
--- a/tools/server/webui/docs/flows/settings-flow.md
+++ b/tools/server/webui/docs/flows/settings-flow.md
@@ -139,6 +139,6 @@ sequenceDiagram
Note over settingsStore: UI-only (not synced):
rect rgb(255, 240, 240)
- Note over settingsStore: systemMessage, custom (JSON)
showStatistics, enableContinueGeneration
autoMicOnEmpty, disableAutoScroll
apiKey, pdfAsImage, disableReasoningFormat
+ Note over settingsStore: systemMessage, custom (JSON)
showStatistics, enableContinueGeneration
autoMicOnEmpty, disableAutoScroll
apiKey, pdfAsImage, disableReasoningParsing, showRawOutputSwitch
end
```
diff --git a/tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessageActions.svelte b/tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessageActions.svelte
index 3cb48157d8..dbd9b98228 100644
--- a/tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessageActions.svelte
+++ b/tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessageActions.svelte
@@ -5,6 +5,7 @@
ChatMessageBranchingControls,
DialogConfirmation
} from '$lib/components/app';
+ import { Switch } from '$lib/components/ui/switch';
interface Props {
role: 'user' | 'assistant';
@@ -26,6 +27,9 @@
onConfirmDelete: () => void;
onNavigateToSibling?: (siblingId: string) => void;
onShowDeleteDialogChange: (show: boolean) => void;
+ showRawOutputSwitch?: boolean;
+ rawOutputEnabled?: boolean;
+ onRawOutputToggle?: (enabled: boolean) => void;
}
let {
@@ -42,7 +46,10 @@
onRegenerate,
role,
siblingInfo = null,
- showDeleteDialog
+ showDeleteDialog,
+ showRawOutputSwitch = false,
+ rawOutputEnabled = false,
+ onRawOutputToggle
}: Props = $props();
function handleConfirmDelete() {
@@ -51,9 +58,9 @@
}
-
+
+
+ {#if showRawOutputSwitch}
+
+ Show raw output
+ onRawOutputToggle?.(checked)}
+ />
+
+ {/if}
{
@@ -238,7 +241,7 @@
{:else if message.role === 'assistant'}
- {#if config().disableReasoningFormat}
+ {#if showRawOutput}
{messageContent || ''}
{:else}
@@ -352,6 +355,9 @@
{onConfirmDelete}
{onNavigateToSibling}
{onShowDeleteDialogChange}
+ showRawOutputSwitch={currentConfig.showRawOutputSwitch}
+ rawOutputEnabled={showRawOutput}
+ onRawOutputToggle={(enabled) => (showRawOutput = enabled)}
/>
{/if}
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 6e26d510cd..a5450e6af8 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
@@ -21,6 +21,7 @@
chatStore,
errorDialog,
isLoading,
+ isChatStreaming,
isEditing,
getAddFilesHandler
} from '$lib/stores/chat.svelte';
@@ -81,7 +82,7 @@
let isServerLoading = $derived(serverLoading());
let hasPropsError = $derived(!!serverError());
- let isCurrentConversationLoading = $derived(isLoading());
+ let isCurrentConversationLoading = $derived(isLoading() || isChatStreaming());
let isRouter = $derived(isRouterMode());
diff --git a/tools/server/webui/src/lib/components/app/chat/ChatSettings/ChatSettings.svelte b/tools/server/webui/src/lib/components/app/chat/ChatSettings/ChatSettings.svelte
index 5a668aa300..967f19bbce 100644
--- a/tools/server/webui/src/lib/components/app/chat/ChatSettings/ChatSettings.svelte
+++ b/tools/server/webui/src/lib/components/app/chat/ChatSettings/ChatSettings.svelte
@@ -254,8 +254,13 @@
type: 'checkbox'
},
{
- key: 'disableReasoningFormat',
- label: 'Show raw LLM output',
+ key: 'disableReasoningParsing',
+ label: 'Disable reasoning content parsing',
+ type: 'checkbox'
+ },
+ {
+ key: 'showRawOutputSwitch',
+ label: 'Enable raw output toggle',
type: 'checkbox'
},
{
diff --git a/tools/server/webui/src/lib/constants/settings-config.ts b/tools/server/webui/src/lib/constants/settings-config.ts
index cac48a557c..1b959f3b69 100644
--- a/tools/server/webui/src/lib/constants/settings-config.ts
+++ b/tools/server/webui/src/lib/constants/settings-config.ts
@@ -7,7 +7,8 @@ export const SETTING_CONFIG_DEFAULT: Record =
theme: 'system',
showThoughtInProgress: false,
showToolCalls: false,
- disableReasoningFormat: false,
+ disableReasoningParsing: false,
+ showRawOutputSwitch: false,
keepStatsVisible: false,
showMessageStats: true,
askForTitleConfirmation: false,
@@ -92,8 +93,10 @@ export const SETTING_CONFIG_INFO: Record = {
showThoughtInProgress: 'Expand thought process by default when generating messages.',
showToolCalls:
'Display tool call labels and payloads from Harmony-compatible delta.tool_calls data below assistant messages.',
- disableReasoningFormat:
- 'Show raw LLM output without backend parsing and frontend Markdown rendering to inspect streaming across different models.',
+ disableReasoningParsing:
+ 'Send reasoning_format=none to prevent server-side extraction of reasoning tokens into separate field',
+ showRawOutputSwitch:
+ 'Show toggle button to display messages as plain text instead of Markdown-formatted content',
keepStatsVisible: 'Keep processing statistics visible after generation finishes.',
showMessageStats:
'Display generation statistics (tokens/second, token count, duration) below each assistant message.',
diff --git a/tools/server/webui/src/lib/services/chat.ts b/tools/server/webui/src/lib/services/chat.ts
index 02fc6381c0..55af0ce816 100644
--- a/tools/server/webui/src/lib/services/chat.ts
+++ b/tools/server/webui/src/lib/services/chat.ts
@@ -90,7 +90,7 @@ export class ChatService {
custom,
timings_per_token,
// Config options
- disableReasoningFormat
+ disableReasoningParsing
} = options;
const normalizedMessages: ApiChatMessageData[] = messages
@@ -127,7 +127,7 @@ export class ChatService {
requestBody.model = options.model;
}
- requestBody.reasoning_format = disableReasoningFormat ? 'none' : 'auto';
+ requestBody.reasoning_format = disableReasoningParsing ? 'none' : 'auto';
if (temperature !== undefined) requestBody.temperature = temperature;
if (max_tokens !== undefined) {
diff --git a/tools/server/webui/src/lib/services/parameter-sync.ts b/tools/server/webui/src/lib/services/parameter-sync.ts
index d124cf5c8d..333260701f 100644
--- a/tools/server/webui/src/lib/services/parameter-sync.ts
+++ b/tools/server/webui/src/lib/services/parameter-sync.ts
@@ -70,12 +70,6 @@ export const SYNCABLE_PARAMETERS: SyncableParameter[] = [
canSync: true
},
{ key: 'showToolCalls', serverKey: 'showToolCalls', type: 'boolean', canSync: true },
- {
- key: 'disableReasoningFormat',
- serverKey: 'disableReasoningFormat',
- type: 'boolean',
- canSync: true
- },
{ key: 'keepStatsVisible', serverKey: 'keepStatsVisible', type: 'boolean', canSync: true },
{ key: 'showMessageStats', serverKey: 'showMessageStats', type: 'boolean', canSync: true },
{
diff --git a/tools/server/webui/src/lib/stores/chat.svelte.ts b/tools/server/webui/src/lib/stores/chat.svelte.ts
index 89de4f080c..f00f418b4c 100644
--- a/tools/server/webui/src/lib/stores/chat.svelte.ts
+++ b/tools/server/webui/src/lib/stores/chat.svelte.ts
@@ -118,6 +118,16 @@ class ChatStore {
this.isLoading = this.isChatLoading(convId);
const streamingState = this.getChatStreaming(convId);
this.currentResponse = streamingState?.response || '';
+ this.isStreamingActive = streamingState !== undefined;
+ this.setActiveProcessingConversation(convId);
+
+ // Sync streaming content to activeMessages so UI displays current content
+ if (streamingState?.response && streamingState?.messageId) {
+ const idx = conversationsStore.findMessageIndex(streamingState.messageId);
+ if (idx !== -1) {
+ conversationsStore.updateMessageAtIndex(idx, { content: streamingState.response });
+ }
+ }
}
/**
@@ -1639,7 +1649,7 @@ class ChatStore {
// Config options needed by ChatService
if (currentConfig.systemMessage) apiOptions.systemMessage = currentConfig.systemMessage;
- if (currentConfig.disableReasoningFormat) apiOptions.disableReasoningFormat = true;
+ if (currentConfig.disableReasoningParsing) apiOptions.disableReasoningParsing = true;
if (hasValue(currentConfig.temperature))
apiOptions.temperature = Number(currentConfig.temperature);
diff --git a/tools/server/webui/src/lib/types/settings.d.ts b/tools/server/webui/src/lib/types/settings.d.ts
index 38b3047dd0..d894245ec3 100644
--- a/tools/server/webui/src/lib/types/settings.d.ts
+++ b/tools/server/webui/src/lib/types/settings.d.ts
@@ -18,8 +18,8 @@ export interface SettingsChatServiceOptions {
model?: string;
// System message to inject
systemMessage?: string;
- // Disable reasoning format (use 'none' instead of 'auto')
- disableReasoningFormat?: boolean;
+ // Disable reasoning parsing (use 'none' instead of 'auto')
+ disableReasoningParsing?: boolean;
// Generation parameters
temperature?: number;
max_tokens?: number;
diff --git a/tools/server/webui/tests/stories/ChatMessage.stories.svelte b/tools/server/webui/tests/stories/ChatMessage.stories.svelte
index 5f4de7d476..a3579cf04e 100644
--- a/tools/server/webui/tests/stories/ChatMessage.stories.svelte
+++ b/tools/server/webui/tests/stories/ChatMessage.stories.svelte
@@ -93,7 +93,7 @@
}}
play={async () => {
const { settingsStore } = await import('$lib/stores/settings.svelte');
- settingsStore.updateConfig('disableReasoningFormat', false);
+ settingsStore.updateConfig('showRawOutputSwitch', false);
}}
/>
@@ -105,7 +105,7 @@
}}
play={async () => {
const { settingsStore } = await import('$lib/stores/settings.svelte');
- settingsStore.updateConfig('disableReasoningFormat', false);
+ settingsStore.updateConfig('showRawOutputSwitch', false);
}}
/>
@@ -117,7 +117,7 @@
}}
play={async () => {
const { settingsStore } = await import('$lib/stores/settings.svelte');
- settingsStore.updateConfig('disableReasoningFormat', false);
+ settingsStore.updateConfig('showRawOutputSwitch', false);
}}
/>
@@ -129,7 +129,7 @@
}}
play={async () => {
const { settingsStore } = await import('$lib/stores/settings.svelte');
- settingsStore.updateConfig('disableReasoningFormat', true);
+ settingsStore.updateConfig('showRawOutputSwitch', true);
}}
/>
@@ -141,7 +141,7 @@
asChild
play={async () => {
const { settingsStore } = await import('$lib/stores/settings.svelte');
- settingsStore.updateConfig('disableReasoningFormat', false);
+ settingsStore.updateConfig('showRawOutputSwitch', false);
// Phase 1: Stream reasoning content in chunks
let reasoningText =
'I need to think about this carefully. Let me break down the problem:\n\n1. The user is asking for help with something complex\n2. I should provide a thorough and helpful response\n3. I need to consider multiple approaches\n4. The best solution would be to explain step by step\n\nThis approach will ensure clarity and understanding.';
@@ -193,7 +193,7 @@
}}
play={async () => {
const { settingsStore } = await import('$lib/stores/settings.svelte');
- settingsStore.updateConfig('disableReasoningFormat', false);
+ settingsStore.updateConfig('showRawOutputSwitch', false);
// Import the chat store to simulate loading state
const { chatStore } = await import('$lib/stores/chat.svelte');