Skip to content

Commit 286ca88

Browse files
webui: address review feedback from allozaur
1 parent 122acbf commit 286ca88

File tree

4 files changed

+46
-33
lines changed

4 files changed

+46
-33
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export const SERVER_PROPS_LOCALSTORAGE_KEY = 'LlamaCppWebui.serverProps';
2+
export const SELECTED_MODEL_LOCALSTORAGE_KEY = 'llama.cpp:selectedModel';

tools/server/webui/src/lib/stores/chat.svelte.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ class ChatStore {
323323
});
324324
}
325325
};
326+
326327
slotsService.startStreaming();
327328

328329
await chatService.sendMessage(allMessages, {

tools/server/webui/src/lib/stores/models.svelte.ts

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { browser } from '$app/environment';
22
import { ModelsService } from '$lib/services/models';
33
import type { ApiModelDataEntry, ApiModelDetails } from '$lib/types/api';
4+
import { SELECTED_MODEL_LOCALSTORAGE_KEY } from '$lib/constants/localstorage-keys';
45

56
export interface ModelOption {
67
id: string;
@@ -17,8 +18,6 @@ type PersistedModelSelection = {
1718
model: string;
1819
};
1920

20-
const STORAGE_KEY = 'llama.cpp:selectedModel';
21-
2221
class 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);

tools/server/webui/src/routes/+layout.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@
148148

149149
<ModeWatcher />
150150

151-
<Toaster position="top-center" richColors />
151+
<Toaster richColors />
152152

153153
<ConversationTitleUpdateDialog
154154
bind:open={titleUpdateDialogOpen}

0 commit comments

Comments
 (0)