char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
cae63579b
char/aliceai-t5-moe
1import { REASONING_EFFORT_LEVELS , REASONING_EFFORT_TOKENS } from '$lib/constants' ; 2import { ReasoningEffort } from '$lib/enums' ; 3import { conversationsStore , modelsStore , serverStore } from '$lib/stores' ; 4import type { ReasoningEffortLevel } from '$lib/types' ; 5import type { DatabaseMessage } from '$lib/types/database' ; 6import { getConversationModel } from '$lib/utils' ; 7 8export interface UseReasoningMenuReturn { 9readonly modelSupportsThinking :boolean ; 10readonly thinkingEnabled :boolean ; 11readonly isReasoningActive :boolean ; 12readonly isOff :boolean ; 13readonly currentEffort :ReasoningEffort ; 14readonly levels :ReasoningEffortLevel []; 15isSelected ( level :ReasoningEffortLevel ) :boolean ; 16tokenLabel ( level :ReasoningEffortLevel ) :string | null ; 17select ( level :ReasoningEffortLevel ) :void ; 18} 19 20/** 21* Shared reactive state and helpers for the reasoning effort menu. 22* 23* Used by both the desktop dropdown (`ChatFormActionAddReasoningSubmenu`) 24* and the mobile sheet (`ChatFormActionAddSheet`) to avoid duplicating the 25* thinking-support derivation and the effort selection logic. 26*/ 27export function useReasoningMenu () :UseReasoningMenuReturn { 28const conversationModel = $derived ( 29getConversationModel ( conversationsStore . activeMessages as DatabaseMessage []) 30); 31// a router chat can carry reasoning from an earlier turn before the props 32// cache is primed, so a model that already produced thinking still qualifies 33const modelSupportsThinkingFromMessages = $derived . by (() => { 34const modelId = serverStore . isRouterMode 35 ?modelsStore . selectedModelName || conversationModel 36 :null ; 37 38if ( ! modelId ) return false ; 39 40return conversationsStore . activeMessages . some ( 41( m ) => m . role === 'assistant' && m . model === modelId && !! m . reasoningContent 42); 43}); 44const modelSupportsThinking = $derived . by (() => { 45void modelsStore . loadedModelIds ; 46void modelsStore . props . cacheVersion ; 47 48if ( serverStore . isRouterMode ) { 49const modelId = modelsStore . selectedModelName || conversationModel ; 50 51return ( 52modelsStore . props . checkModelSupportsThinking ( modelId ?? '' ) || 53modelSupportsThinkingFromMessages 54); 55} 56 57return modelsStore . props . supportsThinking || modelSupportsThinkingFromMessages ; 58}); 59const currentEffort = $derived ( conversationsStore . preferences . getReasoningEffort ()); 60const thinkingEnabled = $derived ( 61currentEffort !== ReasoningEffort . OFF && currentEffort !== ReasoningEffort . DEFAULT 62); 63// Thinking is effectively on (lightbulb lit) either when an explicit effort 64// is selected, or when the effort is left at "Default" and the model 65// supports thinking. 66const isReasoningActive = $derived ( 67thinkingEnabled || ( currentEffort === ReasoningEffort . DEFAULT && modelSupportsThinking ) 68); 69 70return { 71get currentEffort () { 72return currentEffort ; 73}, 74get isOff () { 75return currentEffort === ReasoningEffort . OFF ; 76}, 77get isReasoningActive () { 78return isReasoningActive ; 79}, 80isSelected ( level :ReasoningEffortLevel ) :boolean { 81return currentEffort === level . value ; 82}, 83get levels () { 84return REASONING_EFFORT_LEVELS ; 85}, 86get modelSupportsThinking () { 87return modelSupportsThinking ; 88}, 89select ( level :ReasoningEffortLevel ) :void { 90conversationsStore . preferences . setReasoningEffort ( level . value as ReasoningEffort ); 91}, 92get thinkingEnabled () { 93return thinkingEnabled ; 94}, 95tokenLabel ( level :ReasoningEffortLevel ) :string | null { 96if ( level . value === ReasoningEffort . DEFAULT ) return 'Model default' ; 97 98const tokens = REASONING_EFFORT_TOKENS [ level . value ]; 99 100if ( tokens === undefined ) return null ; 101 102return tokens === - 1 ?'Unlimited' :`Max ${ tokens . toLocaleString ()} tokens` ; 103} 104}; 105}