mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-09-17 20:31:47 +02:00
ui : keep the model selector mounted across backend switches
Assisted-by: pi:llama.cpp/DeepSeek-V4.1-Flash
This commit is contained in:
@@ -276,13 +276,6 @@
|
||||
class="w-full md:min-w-80 md:max-w-[26rem] max-w-[calc(100vw-2rem)] p-0!"
|
||||
onOpenAutoFocus={(event) => event.preventDefault()}
|
||||
>
|
||||
<ModelsSelectorBackendSwitcher
|
||||
activeId={ms.activeBackendId}
|
||||
backends={ms.backends}
|
||||
onAdd={handleAddBackend}
|
||||
onSelect={(backendId) => void ms.handleBackendChange(backendId)}
|
||||
/>
|
||||
|
||||
<DropdownMenuSearchable
|
||||
emptyMessage="No models found."
|
||||
isEmpty={ms.filteredOptions.length === 0 && ms.isCurrentModelInCache}
|
||||
@@ -292,6 +285,14 @@
|
||||
searchClass="bg-transparent"
|
||||
searchValue={ms.searchTerm}
|
||||
>
|
||||
<!-- Provider tabs sit under the search input, above the option list. -->
|
||||
<ModelsSelectorBackendSwitcher
|
||||
activeId={ms.activeBackendId}
|
||||
backends={ms.backends}
|
||||
onAdd={handleAddBackend}
|
||||
onSelect={(backendId) => void ms.handleBackendChange(backendId)}
|
||||
/>
|
||||
|
||||
<!-- Option list; the search header sticks to the top and the actions
|
||||
footer to the bottom of the content scrollport. -->
|
||||
<div class="models-list px-1.5">
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
? Math.round(modelLoadFraction(modelsStore.status.getLoadProgress(triggerModel)) * 100)
|
||||
: 0}
|
||||
|
||||
{#if ms.isMultiModel}
|
||||
{#if ms.isMultiModel || ms.switchingBackends}
|
||||
<button
|
||||
class={[
|
||||
`relative inline-flex cursor-pointer items-center gap-1.5 rounded-sm bg-background px-1.5 py-1 text-xs shadow-sm transition hover:bg-muted-foreground/20 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-60 max-sm:px-3 max-sm:py-2 max-sm:text-sm dark:bg-muted-foreground/15 dark:text-secondary-foreground`,
|
||||
@@ -127,7 +127,7 @@
|
||||
<Lightbulb class="h-3.5 w-3.5 shrink-0 text-amber-400" />
|
||||
{/if}
|
||||
|
||||
{#if ms.updating || ms.isLoadingModel}
|
||||
{#if ms.updating || ms.isLoadingModel || ms.switchingBackends}
|
||||
<Loader2 class="h-3 w-3.5 shrink-0 animate-spin" />
|
||||
{:else}
|
||||
<ChevronDown class="h-3 w-3.5 shrink-0" />
|
||||
@@ -149,13 +149,6 @@
|
||||
</Sheet.Header>
|
||||
|
||||
<div class="flex flex-col gap-1 pb-4">
|
||||
<ModelsSelectorBackendSwitcher
|
||||
activeId={ms.activeBackendId}
|
||||
backends={ms.backends}
|
||||
onAdd={handleAddBackend}
|
||||
onSelect={(backendId) => void ms.handleBackendChange(backendId)}
|
||||
/>
|
||||
|
||||
<div class="mb-3 px-4">
|
||||
<SearchInput
|
||||
onInput={(v) => ms.setSearchTerm(v)}
|
||||
@@ -164,6 +157,14 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Provider tabs sit under the search input, above the option list. -->
|
||||
<ModelsSelectorBackendSwitcher
|
||||
activeId={ms.activeBackendId}
|
||||
backends={ms.backends}
|
||||
onAdd={handleAddBackend}
|
||||
onSelect={(backendId) => void ms.handleBackendChange(backendId)}
|
||||
/>
|
||||
|
||||
<div class="max-h-[60vh] overflow-y-auto px-2">
|
||||
{#if !ms.isCurrentModelInCache && currentModel}
|
||||
<button
|
||||
|
||||
@@ -30,6 +30,7 @@ export interface UseModelsSelectorReturn {
|
||||
readonly filteredOptions: ModelOption[];
|
||||
readonly groupedFilteredOptions: ReturnType<typeof groupModelOptions>;
|
||||
readonly isLoadingModel: boolean;
|
||||
readonly switchingBackends: boolean;
|
||||
readonly searchTerm: string;
|
||||
readonly showModelDialog: boolean;
|
||||
readonly infoModelId: string | null;
|
||||
@@ -88,6 +89,7 @@ export function useModelsSelector(opts: UseModelsSelectorOptions): UseModelsSele
|
||||
});
|
||||
|
||||
let isLoadingModel = $state(false);
|
||||
let switchingBackends = $state(false);
|
||||
let searchTerm = $state('');
|
||||
let showModelDialog = $state(false);
|
||||
let infoModelId = $state<string | null>(null);
|
||||
@@ -141,11 +143,18 @@ export function useModelsSelector(opts: UseModelsSelectorOptions): UseModelsSele
|
||||
backendsStore.setActive(backendId);
|
||||
searchTerm = '';
|
||||
|
||||
// keep the multi-model selector mounted while the new backend's props and
|
||||
// models load; role flips (external MODEL mode -> local ROUTER mode) would
|
||||
// otherwise unmount and remount the open dropdown mid switch
|
||||
switchingBackends = true;
|
||||
|
||||
try {
|
||||
await backendsModelsStore.ensureLoaded(backendId);
|
||||
await modelsStore.switchBackend();
|
||||
} catch (error) {
|
||||
console.error('Failed to switch backend:', error);
|
||||
} finally {
|
||||
switchingBackends = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,6 +330,10 @@ export function useModelsSelector(opts: UseModelsSelectorOptions): UseModelsSele
|
||||
return showModelDialog;
|
||||
},
|
||||
|
||||
get switchingBackends() {
|
||||
return switchingBackends;
|
||||
},
|
||||
|
||||
get updating() {
|
||||
return updating;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user