11import { browser } from '$app/environment' ;
22import { ModelsService } from '$lib/services/models' ;
33import type { ApiModelDataEntry , ApiModelDetails } from '$lib/types/api' ;
4+ import { SELECTED_MODEL_LOCALSTORAGE_KEY } from '$lib/constants/localstorage-keys' ;
45
56export interface ModelOption {
67 id : string ;
@@ -17,8 +18,6 @@ type PersistedModelSelection = {
1718 model : string ;
1819} ;
1920
20- const STORAGE_KEY = 'llama.cpp:selectedModel' ;
21-
2221class ModelsStore {
2322 private _models = $state < ModelOption [ ] > ( [ ] ) ;
2423 private _loading = $state ( false ) ;
@@ -79,9 +78,7 @@ class ModelsStore {
7978
8079 const models : ModelOption [ ] = response . data . map ( ( item , index ) => {
8180 const details = response . models ?. [ index ] ;
82- const rawCapabilities = Array . isArray ( details ?. capabilities )
83- ? [ ...( details ?. capabilities ?? [ ] ) ]
84- : [ ] ;
81+ const rawCapabilities = Array . isArray ( details ?. capabilities ) ? details ?. capabilities : [ ] ;
8582 const displayNameSource =
8683 details ?. name && details . name . trim ( ) . length > 0 ? details . name : item . id ;
8784 const displayName = this . toDisplayName ( displayNameSource ) ;
@@ -99,36 +96,17 @@ class ModelsStore {
9996
10097 this . _models = models ;
10198
102- const persisted = this . readPersistedSelection ( ) ;
103- let nextSelectionId = this . _selectedModelId ?? persisted ?. id ?? null ;
104- let nextSelectionName = this . _selectedModelName ?? persisted ?. model ?? null ;
105- if ( nextSelectionId ) {
106- const match = models . find ( ( model ) => model . id === nextSelectionId ) ;
107- if ( match ) {
108- nextSelectionId = match . id ;
109- nextSelectionName = match . model ;
110- } else if ( models [ 0 ] ) {
111- nextSelectionId = models [ 0 ] . id ;
112- nextSelectionName = models [ 0 ] . model ;
113- } else {
114- nextSelectionId = null ;
115- nextSelectionName = null ;
116- }
117- } else if ( models [ 0 ] ) {
118- nextSelectionId = models [ 0 ] . id ;
119- nextSelectionName = models [ 0 ] . model ;
120- }
99+ const selection = this . determineInitialSelection ( models ) ;
121100
122- this . _selectedModelId = nextSelectionId ;
123- this . _selectedModelName = nextSelectionName ;
101+ this . _selectedModelId = selection . id ;
102+ this . _selectedModelName = selection . model ;
124103 this . persistSelection (
125- nextSelectionId && nextSelectionName
126- ? { id : nextSelectionId , model : nextSelectionName }
127- : null
104+ selection . id && selection . model ? { id : selection . id , model : selection . model } : null
128105 ) ;
129106 } catch ( error ) {
130107 this . _models = [ ] ;
131108 this . _error = error instanceof Error ? error . message : 'Failed to load models' ;
109+
132110 throw error ;
133111 } finally {
134112 this . _loading = false ;
@@ -167,13 +145,45 @@ class ModelsStore {
167145 return candidate && candidate . trim ( ) . length > 0 ? candidate : id ;
168146 }
169147
148+ /**
149+ * Determines which model should be selected after fetching the models list.
150+ * Priority: current selection > persisted selection > first available model > none
151+ */
152+ private determineInitialSelection ( models : ModelOption [ ] ) : {
153+ id : string | null ;
154+ model : string | null ;
155+ } {
156+ const persisted = this . readPersistedSelection ( ) ;
157+ let nextSelectionId = this . _selectedModelId ?? persisted ?. id ?? null ;
158+ let nextSelectionName = this . _selectedModelName ?? persisted ?. model ?? null ;
159+
160+ if ( nextSelectionId ) {
161+ const match = models . find ( ( m ) => m . id === nextSelectionId ) ;
162+ if ( match ) {
163+ nextSelectionId = match . id ;
164+ nextSelectionName = match . model ;
165+ } else if ( models [ 0 ] ) {
166+ nextSelectionId = models [ 0 ] . id ;
167+ nextSelectionName = models [ 0 ] . model ;
168+ } else {
169+ nextSelectionId = null ;
170+ nextSelectionName = null ;
171+ }
172+ } else if ( models [ 0 ] ) {
173+ nextSelectionId = models [ 0 ] . id ;
174+ nextSelectionName = models [ 0 ] . model ;
175+ }
176+
177+ return { id : nextSelectionId , model : nextSelectionName } ;
178+ }
179+
170180 private readPersistedSelection ( ) : PersistedModelSelection | null {
171181 if ( ! browser ) {
172182 return null ;
173183 }
174184
175185 try {
176- const raw = localStorage . getItem ( STORAGE_KEY ) ;
186+ const raw = localStorage . getItem ( SELECTED_MODEL_LOCALSTORAGE_KEY ) ;
177187 if ( ! raw ) {
178188 return null ;
179189 }
@@ -183,6 +193,7 @@ class ModelsStore {
183193 const id = parsed . id ;
184194 const model =
185195 typeof parsed . model === 'string' && parsed . model . length > 0 ? parsed . model : id ;
196+
186197 return { id, model } ;
187198 }
188199 } catch ( error ) {
@@ -199,9 +210,9 @@ class ModelsStore {
199210
200211 try {
201212 if ( selection ) {
202- localStorage . setItem ( STORAGE_KEY , JSON . stringify ( selection ) ) ;
213+ localStorage . setItem ( SELECTED_MODEL_LOCALSTORAGE_KEY , JSON . stringify ( selection ) ) ;
203214 } else {
204- localStorage . removeItem ( STORAGE_KEY ) ;
215+ localStorage . removeItem ( SELECTED_MODEL_LOCALSTORAGE_KEY ) ;
205216 }
206217 } catch ( error ) {
207218 console . warn ( 'Failed to persist model selection to localStorage:' , error ) ;
0 commit comments