ui: Add a "Default" option for the reasoning selector (#25846)
* ui: add Default reasoning option that defers to the server The webui always injected enable_thinking, overriding the chat template default and the --reasoning flag, breaking models that reason unconditionally (e.g. Gemma 4 E4B) on a fresh client. Default sends nothing so the server decides, Off and effort levels force the value as before. All choices are remembered. Also remove the boolean thinking API from the conversations store and drop ChatFormReasoningEffortSubmenu.svelte (dead code). * ui: close the whole menu tree on reasoning level selection The reasoning levels were raw buttons inside the SubContent, so selecting one only closed the submenu via manual state while the root dropdown stayed open. DropdownMenu.Item closes the full tree on select like the sibling entries and brings native keyboard navigation. * ui: prevent the add menu tooltip from flashing when the dropdown closes
This commit is contained in:
@@ -17,6 +17,7 @@ import { isRouterMode } from '$lib/stores/server.svelte';
|
||||
export interface UseReasoningMenuReturn {
|
||||
readonly modelSupportsThinking: boolean;
|
||||
readonly thinkingEnabled: boolean;
|
||||
readonly isOff: boolean;
|
||||
readonly currentEffort: ReasoningEffort;
|
||||
readonly levels: ReasoningEffortLevel[];
|
||||
isSelected(level: ReasoningEffortLevel): boolean;
|
||||
@@ -59,8 +60,10 @@ export function useReasoningMenu(): UseReasoningMenuReturn {
|
||||
return supportsThinking() || modelSupportsThinkingFromMessages;
|
||||
});
|
||||
|
||||
const thinkingEnabled = $derived(conversationsStore.getThinkingEnabled());
|
||||
const currentEffort = $derived(conversationsStore.getReasoningEffort());
|
||||
const thinkingEnabled = $derived(
|
||||
currentEffort !== ReasoningEffort.OFF && currentEffort !== ReasoningEffort.DEFAULT
|
||||
);
|
||||
|
||||
return {
|
||||
get modelSupportsThinking() {
|
||||
@@ -69,6 +72,9 @@ export function useReasoningMenu(): UseReasoningMenuReturn {
|
||||
get thinkingEnabled() {
|
||||
return thinkingEnabled;
|
||||
},
|
||||
get isOff() {
|
||||
return currentEffort === ReasoningEffort.OFF;
|
||||
},
|
||||
get currentEffort() {
|
||||
return currentEffort;
|
||||
},
|
||||
@@ -76,20 +82,15 @@ export function useReasoningMenu(): UseReasoningMenuReturn {
|
||||
return REASONING_EFFORT_LEVELS;
|
||||
},
|
||||
isSelected(level: ReasoningEffortLevel): boolean {
|
||||
if (level.isOff) return !thinkingEnabled;
|
||||
return thinkingEnabled && currentEffort === level.value;
|
||||
return currentEffort === level.value;
|
||||
},
|
||||
tokenLabel(level: ReasoningEffortLevel): string | null {
|
||||
if (level.isOff) return null;
|
||||
if (level.value === ReasoningEffort.DEFAULT) return 'Model default';
|
||||
const tokens = REASONING_EFFORT_TOKENS[level.value];
|
||||
if (tokens === undefined) return null;
|
||||
return tokens === -1 ? 'Unlimited' : `Max ${tokens.toLocaleString()} tokens`;
|
||||
},
|
||||
select(level: ReasoningEffortLevel): void {
|
||||
if (level.isOff) {
|
||||
conversationsStore.setThinkingEnabled(false);
|
||||
return;
|
||||
}
|
||||
conversationsStore.setThinkingEnabled(true);
|
||||
conversationsStore.setReasoningEffort(level.value as ReasoningEffort);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user