55 replaceDescriptorCurrentValue ,
66 selectableProviderOptionChoices ,
77 REASONING_SELECT_DESCRIPTOR_IDS ,
8- ULTRATHINK_PROMPT_PREFIX ,
98} from "@t3tools/client-runtime/model-traits" ;
109import {
1110 type ModelSelection ,
@@ -258,7 +257,8 @@ export function getReasoningTraitStep(input: {
258257 const descriptor = selected . selectDescriptors . find ( ( entry ) =>
259258 REASONING_SELECT_DESCRIPTOR_IDS . has ( entry . id ) ,
260259 ) ;
261- if ( ! descriptor || descriptor . options . length < 2 ) return null ;
260+ const choices = descriptor ? selectableProviderOptionChoices ( descriptor ) : [ ] ;
261+ if ( ! descriptor || choices . length < 2 ) return null ;
262262 const isPrimary = descriptor . id === selected . primarySelectDescriptor ?. id ;
263263 const current =
264264 isPrimary && selected . ultrathinkPromptControlled
@@ -268,26 +268,17 @@ export function getReasoningTraitStep(input: {
268268 { instanceId : input . instanceId , model : input . model , options : input . modelOptions ?? [ ] } ,
269269 input . reportedModelSelection ,
270270 ) ;
271+ // Walk the full catalog order so a typed Ultrathink keeps its place, then land on a pickable level.
271272 const ordered = input . direction > 0 ? descriptor . options : descriptor . options . toReversed ( ) ;
272273 const position =
273274 [ current , getDescriptorStringValue ( descriptor ) ]
274275 . map ( ( value ) => ordered . findIndex ( ( option ) => option . id === value ) )
275276 . find ( ( index ) => index >= 0 ) ?? - 1 ;
276- for ( const option of [
277- ...ordered . slice ( position + 1 ) ,
278- ...ordered . slice ( 0 , Math . max ( position , 0 ) ) ,
279- ] ) {
280- const change = getTraitSelectChange ( selected , descriptor , input . prompt , option . id ) ;
281- if ( ! change ) return null ;
282- if ( "modelOptions" in change ) {
283- return change . modelOptions
284- ? { prompt : change . prompt , modelOptions : change . modelOptions }
285- : null ;
286- }
287- // A slash command refuses the Ultrathink prefix, so skip that level.
288- if ( change . prompt . startsWith ( ULTRATHINK_PROMPT_PREFIX ) ) return change ;
289- }
290- return null ;
277+ const next = [ ...ordered . slice ( position + 1 ) , ...ordered . slice ( 0 , Math . max ( position , 0 ) ) ] . find (
278+ ( option ) => choices . includes ( option ) ,
279+ ) ;
280+ const change = next && getTraitSelectChange ( selected , descriptor , input . prompt , next . id ) ;
281+ return change ?. modelOptions ? { prompt : change . prompt , modelOptions : change . modelOptions } : null ;
291282}
292283
293284export interface TraitsMenuContentProps {
@@ -368,7 +359,7 @@ export function useTraitsSelection({
368359 onPromptEdit ?.(
369360 ( prompt ) => getTraitSelectChange ( selected , descriptor , prompt , value ) ?. prompt ?? prompt ,
370361 ) ;
371- if ( "modelOptions" in change ) updateModelOptions ( change . modelOptions ) ;
362+ updateModelOptions ( change . modelOptions ) ;
372363 } ,
373364 changeBoolean : ( descriptorId : string , value : boolean ) => {
374365 updateModelOptions (
0 commit comments