ui: Add Thinking mode toggle with reasoning effort levels + improvements for Chat Form Add Action UI (#23434)

* feat: Add "Thinking" toggle and status icon + redesign Chat Form Actions Add panel

* test: Update test reference

* fix: Icon

* fix: E2E test command

* fix: wait for greeting h1 to be visible in e2e test

* fix: remove duplicate PDF option in attachment dropdown

* fix: use label-based group toggle to avoid stale references

* refactor: inline MCP server and tool toggles in mobile sheet

* fix: serve correct build directory in e2e playwright config

* feat: add reasoning effort levels selector in model dropdown

* feat: Reasoning effort

* refactor: Make server origin configurable via environment variable

* feat: Add chat template thinking detector utility

* feat: Add thinking support detection to models store

* refactor: Update model selector components with thinking detection and message-specific indicators

* feat: Update chat form components for model selection and thinking support

* feat: Improve Reasoning controls UI

* refactor: Apply suggestions from code review

Co-authored-by: Aleksander Grygier <aleksander.grygier@gmail.com>

* fix: Model tags

* refactor: Cleanup

* refactor: Remove unneeded components

* refactor: Cleanup
This commit is contained in:
Aleksander Grygier
2026-06-02 10:23:19 +02:00
committed by GitHub
parent 2365315955
commit f8e67fc583
40 changed files with 1085 additions and 263 deletions
@@ -79,7 +79,9 @@ export const ATTACHMENT_FILE_ITEMS: AttachmentMenuItem[] = [
}
];
export const ATTACHMENT_EXTRA_ITEMS: AttachmentMenuItem[] = [
export const ATTACHMENT_EXTRA_ITEMS: AttachmentMenuItem[] = [];
export const ATTACHMENT_PROMPT_ITEMS: AttachmentMenuItem[] = [
{
id: AttachmentMenuItemId.SYSTEM_MESSAGE,
label: 'System Message',
@@ -87,10 +89,7 @@ export const ATTACHMENT_EXTRA_ITEMS: AttachmentMenuItem[] = [
enabledWhen: AttachmentItemEnabledWhen.ALWAYS,
hasEnabledTooltip: true,
action: AttachmentAction.SYSTEM_PROMPT_CLICK
}
];
export const ATTACHMENT_MCP_ITEMS: AttachmentMenuItem[] = [
},
{
id: AttachmentMenuItemId.MCP_PROMPT,
label: 'MCP Prompt',
@@ -98,7 +97,10 @@ export const ATTACHMENT_MCP_ITEMS: AttachmentMenuItem[] = [
enabledWhen: AttachmentItemEnabledWhen.ALWAYS,
action: AttachmentAction.MCP_PROMPT_CLICK,
visibleWhen: AttachmentItemVisibleWhen.HAS_MCP_PROMPTS_SUPPORT
},
}
];
export const ATTACHMENT_MCP_ITEMS: AttachmentMenuItem[] = [
{
id: AttachmentMenuItemId.MCP_RESOURCES,
label: 'MCP Resources',
+2
View File
@@ -5,6 +5,8 @@ export * from './agentic';
export * from './api-endpoints';
export * from './attachment-labels';
export * from './database';
export * from './reasoning-effort';
export * from './reasoning-effort-tokens';
export * from './storage';
export * from './attachment-menu';
export * from './auto-scroll';
@@ -0,0 +1,12 @@
import { ReasoningEffort } from '$lib/enums';
/**
* Reasoning effort to token budget mapping.
* Maps the ReasoningEffort enum values to concrete token counts for the server.
*/
export const REASONING_EFFORT_TOKENS: Record<string, number> = {
[ReasoningEffort.LOW]: 512,
[ReasoningEffort.MEDIUM]: 2048,
[ReasoningEffort.HIGH]: 8192,
[ReasoningEffort.MAX]: -1 // unlimited
};
@@ -0,0 +1,21 @@
import { ReasoningEffort } from '$lib/enums';
import type { ReasoningEffortLevel } from '$lib/types';
/**
* Reasoning effort UI labels.
* Keys match the ReasoningEffort enum values for type-safe lookups.
*/
export const REASONING_EFFORT_LABELS: Record<string, string> = {
[ReasoningEffort.LOW]: 'Low',
[ReasoningEffort.MEDIUM]: 'Medium',
[ReasoningEffort.HIGH]: 'High',
[ReasoningEffort.MAX]: 'Max'
};
export const REASONING_EFFORT_LEVELS: ReasoningEffortLevel[] = [
{ value: 'off', label: 'Off', isOff: true },
{ value: ReasoningEffort.LOW, label: 'Low' },
{ value: ReasoningEffort.MEDIUM, label: 'Medium' },
{ value: ReasoningEffort.HIGH, label: 'High' },
{ value: ReasoningEffort.MAX, label: 'Max', hasInfo: true }
];
@@ -29,6 +29,8 @@ export const SETTINGS_KEYS = {
ALWAYS_SHOW_SIDEBAR_ON_DESKTOP: 'alwaysShowSidebarOnDesktop',
FULL_HEIGHT_CODE_BLOCKS: 'fullHeightCodeBlocks',
SHOW_RAW_MODEL_NAMES: 'showRawModelNames',
SHOW_MODEL_QUANTIZATION: 'showModelQuantization',
SHOW_MODEL_TAGS: 'showModelTags',
SHOW_SYSTEM_MESSAGE: 'showSystemMessage',
// Sampling
TEMPERATURE: 'temperature',
@@ -64,6 +66,7 @@ export const SETTINGS_KEYS = {
// Developer
DISABLE_REASONING_PARSING: 'disableReasoningParsing',
EXCLUDE_REASONING_FROM_CONTEXT: 'excludeReasoningFromContext',
ENABLE_THINKING: 'enableThinking',
SHOW_RAW_OUTPUT_SWITCH: 'showRawOutputSwitch',
// PY_INTERPRETER_ENABLED: 'pyInterpreterEnabled',
CUSTOM_JSON: 'customJson',
@@ -330,6 +330,30 @@ const SETTINGS_REGISTRY: Record<string, SettingsSectionEntry> = {
paramType: SyncableParameterType.BOOLEAN
}
},
{
key: SETTINGS_KEYS.SHOW_MODEL_QUANTIZATION,
label: 'Show model quantization information',
help: 'Display quantization badges (e.g. Q8_0, Q4_K_M) next to model names throughout the interface.',
defaultValue: true,
type: SettingsFieldType.CHECKBOX,
section: SETTINGS_SECTION_SLUGS.DISPLAY,
sync: {
serverKey: SETTINGS_KEYS.SHOW_MODEL_QUANTIZATION,
paramType: SyncableParameterType.BOOLEAN
}
},
{
key: SETTINGS_KEYS.SHOW_MODEL_TAGS,
label: 'Show model tags',
help: 'Display model tags (e.g. "vision", "reasoning") next to model names throughout the interface.',
defaultValue: true,
type: SettingsFieldType.CHECKBOX,
section: SETTINGS_SECTION_SLUGS.DISPLAY,
sync: {
serverKey: SETTINGS_KEYS.SHOW_MODEL_TAGS,
paramType: SyncableParameterType.BOOLEAN
}
},
{
key: SETTINGS_KEYS.ALWAYS_SHOW_AGENTIC_TURNS,
label: 'Always show agentic turns in conversation',
@@ -646,6 +670,14 @@ const SETTINGS_REGISTRY: Record<string, SettingsSectionEntry> = {
paramType: SyncableParameterType.BOOLEAN
}
},
{
key: SETTINGS_KEYS.ENABLE_THINKING,
label: 'Enable thinking',
help: 'Enable model thinking/reasoning for each request. When off, the model will skip the thinking phase and go straight to the response.',
defaultValue: false,
type: SettingsFieldType.CHECKBOX,
section: SETTINGS_SECTION_SLUGS.DEVELOPER
},
{
key: SETTINGS_KEYS.SHOW_RAW_OUTPUT_SWITCH,
label: 'Enable raw output toggle',
+2
View File
@@ -19,6 +19,8 @@ export const CONFIG_LOCALSTORAGE_KEY = `${STORAGE_APP_NAME}.config`;
export const DISABLED_TOOLS_LOCALSTORAGE_KEY = `${STORAGE_APP_NAME}.disabledTools`;
export const FAVORITE_MODELS_LOCALSTORAGE_KEY = `${STORAGE_APP_NAME}.favoriteModels`;
export const MCP_DEFAULT_ENABLED_LOCALSTORAGE_KEY = `${STORAGE_APP_NAME}.mcpDefaultEnabled`;
export const THINKING_ENABLED_DEFAULT_LOCALSTORAGE_KEY = `${STORAGE_APP_NAME}.thinkingEnabledDefault`;
export const REASONING_EFFORT_DEFAULT_LOCALSTORAGE_KEY = `${STORAGE_APP_NAME}.reasoningEffortDefault`;
export const USER_OVERRIDES_LOCALSTORAGE_KEY = `${STORAGE_APP_NAME}.userOverrides`;
// Deprecated old key names (kept for backward compat while users migrate)