ui : group the manager sections by capability

Assisted-by: pi:llama.cpp/DeepSeek-V4.1-Flash
This commit is contained in:
Aleksander Grygier
2026-09-28 12:10:12 +02:00
parent 07aabcbb7a
commit 5f6aa1b91f
3 changed files with 74 additions and 23 deletions
@@ -13,7 +13,14 @@
saveOverrides
} from './utils';
import { LOCAL_BACKEND_ID } from '$lib/constants';
import { backendsStore, conversationsStore, modelsStore, uiStore } from '$lib/stores';
import { ModelGroupingMode } from '$lib/enums/settings.enums';
import {
backendsStore,
conversationsStore,
modelsStore,
settingsStore,
uiStore
} from '$lib/stores';
import type { ModelOption } from '$lib/types/models';
import { getBackend } from '$lib/utils/api-base';
import { getBackendCapabilities } from '$lib/utils/backend';
@@ -108,34 +115,75 @@
});
}
const localItems = byBackend.get(LOCAL_BACKEND_ID);
// by capability: one block whose models can load and unload, one that is chat only
if (settingsStore.config.modelGrouping === ModelGroupingMode.COMPAT) {
const local = (entry: ModelQuantGroup) => entry.base.backendId === LOCAL_BACKEND_ID;
const loadable: ModelQuantGroup[] = [];
const chatOnly: ModelQuantGroup[] = [];
if (localItems?.length) {
ordered.push({
backendId: LOCAL_BACKEND_ID,
isLocal: true,
items: localItems,
key: LOCAL_BACKEND_ID,
kind: 'local',
label: 'Local models'
});
}
for (const entry of entries) {
if (claimed.has(entry.key) || hiddenKeys.has(entry.key)) continue;
for (const backend of backendsStore.enabled) {
if (backend.id === LOCAL_BACKEND_ID) continue;
const canLoad = getBackendCapabilities(getBackend(entry.base.backendId)).loadUnload;
const items = byBackend.get(backend.id);
(canLoad ? loadable : chatOnly).push(entry);
}
if (items?.length) {
// the bundled server leads the block it belongs to
const leading = (list: ModelQuantGroup[]) =>
[...list].sort((a, b) => Number(local(b)) - Number(local(a)));
if (loadable.length) {
ordered.push({
backendId: backend.id,
backendId: null,
isLocal: false,
items,
key: backend.id,
kind: 'provider',
label: backend.name
items: leading(loadable),
key: 'llama-compat',
kind: 'compat',
label: 'Llama-compat'
});
}
if (chatOnly.length) {
ordered.push({
backendId: null,
isLocal: false,
items: leading(chatOnly),
key: 'oai-compat',
kind: 'compat',
label: 'OAI-compat'
});
}
} else {
const localItems = byBackend.get(LOCAL_BACKEND_ID);
if (localItems?.length) {
ordered.push({
backendId: LOCAL_BACKEND_ID,
isLocal: true,
items: localItems,
key: LOCAL_BACKEND_ID,
kind: 'local',
label: 'Local models'
});
}
for (const backend of backendsStore.enabled) {
if (backend.id === LOCAL_BACKEND_ID) continue;
const items = byBackend.get(backend.id);
if (items?.length) {
ordered.push({
backendId: backend.id,
isLocal: false,
items,
key: backend.id,
kind: 'provider',
label: backend.name
});
}
}
}
if (hidden.length) {
@@ -2,6 +2,7 @@
import type { ModelsTableGroup } from './utils';
import { formatLastUsed, type ModelQuantGroup } from './utils';
import {
Boxes,
ChevronDown,
ChevronRight,
Eye,
@@ -495,8 +496,10 @@
<Power class="h-3.5 w-3.5 shrink-0" />
{:else if group.kind === 'hidden'}
<EyeOff class="h-3.5 w-3.5 shrink-0" />
{:else if group.kind === 'local'}
{:else if group.kind === 'local' || group.key === 'llama-compat'}
<Logo class="shrink-0" style="--size: 0.875rem" />
{:else if group.kind === 'compat'}
<Boxes class="h-3.5 w-3.5 shrink-0" />
{/if}
{/snippet}
@@ -60,7 +60,7 @@ export interface ModelsTableGroup {
items: ModelQuantGroup[];
key: string;
/** Picks the header icon; providers use their backend logo instead. */
kind: 'favorites' | 'hidden' | 'loaded' | 'local' | 'provider';
kind: 'compat' | 'favorites' | 'hidden' | 'loaded' | 'local' | 'provider';
label: string;
}