From 39f5b368fd01c632d166103bd23f47a25aff8f27 Mon Sep 17 00:00:00 2001 From: Aleksander Grygier Date: Tue, 29 Sep 2026 13:53:05 +0200 Subject: [PATCH] ui : drop an orphaned doc comment left by a moved method Assisted-by: pi:zai-org/GLM-5.3-Flash --- tools/server/server-http.cpp | 14 +- .../ChatFormActionAddDropdown.svelte | 3 +- .../ChatFormActionModels.svelte | 35 +-- .../ChatFormActionReasoning.svelte | 3 +- .../ChatFormPickerCommand.svelte | 12 +- .../ChatScreen/ChatScreenServerError.svelte | 11 +- tools/ui/src/lib/components/app/chat/index.ts | 1 - .../app/misc/CollapsibleRegion.svelte | 8 +- .../app/misc/CollapsibleSection.svelte | 7 +- .../components/app/misc/GroupedList.svelte | 21 +- tools/ui/src/lib/components/app/misc/index.ts | 15 +- .../components/app/models/ModelAvatar.svelte | 13 +- .../app/models/ModelCapabilities.svelte | 13 +- .../app/models/ModelCapabilityIcons.svelte | 89 +++---- .../components/app/models/ModelContext.svelte | 11 +- ...svelte => ModelDownloadProgressBar.svelte} | 0 .../app/models/ModelDraftSidecars.svelte | 40 +++- .../lib/components/app/models/ModelId.svelte | 7 +- .../app/models/ModelLoadControl.svelte | 15 +- ...verAvatar.svelte => ModelOrgAvatar.svelte} | 7 +- .../models/ModelsManager/ModelsManager.svelte | 166 +++++++++++++- .../ModelsManager/ModelsManagerFilters.svelte | 47 ++-- .../ModelsManagerModelConfiguration.svelte | 73 ++++++ ...delsManagerModelConfigurationHeader.svelte | 119 ++++++++++ ...anagerModelConfigurationInformation.svelte | 195 ++++++++++++++++ .../ModelsManagerModelRow.svelte | 6 +- .../ModelsManagerModelsTable.svelte | 40 ++-- .../ModelsManagerQuantRow.svelte | 6 +- .../ModelsManager/ModelsManagerRepoRow.svelte | 7 +- .../ModelsManagerTableToolbar.svelte | 2 +- .../app/models/ModelsManager/utils.ts | 53 +---- .../app/models/ModelsSection.svelte | 7 +- .../ModelsSelectorDownloadItem.svelte | 44 ++-- .../ModelsSelectorDropdown.svelte | 71 ++---- .../ModelsSelector/ModelsSelectorList.svelte | 56 +---- .../ModelsSelectorOption.svelte | 24 +- .../ModelsSelector/ModelsSelectorSheet.svelte | 62 ++--- .../app/models/ModelsSelector/index.ts | 103 +-------- .../app/models/ModelsSelectorOption.svelte | 217 ------------------ .../discover/DownloadProgressBar.svelte | 32 --- .../ui/src/lib/components/app/models/index.ts | 36 +-- .../navigation/DropdownMenuSearchable.svelte | 9 +- .../lib/components/app/navigation/utils.ts | 70 +----- .../lib/constants/css-classes.constants.ts | 7 + tools/ui/src/lib/constants/icons.constants.ts | 47 +++- tools/ui/src/lib/constants/index.ts | 1 + .../lib/constants/model-loading.constants.ts | 22 ++ .../lib/constants/models-manager.constants.ts | 36 +++ .../lib/constants/settings-keys.constants.ts | 2 + .../src/lib/constants/settings.constants.ts | 7 + tools/ui/src/lib/constants/ui.constants.ts | 8 +- .../lib/hooks/use-models-selector.svelte.ts | 178 ++------------ .../lib/hooks/use-reasoning-menu.svelte.ts | 4 +- .../src/lib/services/huggingface.service.ts | 110 ++++----- .../ui/src/lib/stores/models/index.svelte.ts | 27 +-- .../ui/src/lib/stores/models/status.svelte.ts | 7 +- .../src/lib/stores/settings/index.svelte.ts | 6 +- tools/ui/src/lib/types/models.d.ts | 11 +- tools/ui/src/lib/utils/formatters.ts | 16 ++ tools/ui/src/lib/utils/model-families.ts | 14 +- tools/ui/src/lib/utils/near-viewport.ts | 5 +- .../stories/ModelsSelector.stories.svelte | 9 +- tools/ui/vite.config.ts | 4 - 63 files changed, 1072 insertions(+), 1219 deletions(-) rename tools/ui/src/lib/components/app/models/{discover/ModelsDiscoverDownloadProgressBar.svelte => ModelDownloadProgressBar.svelte} (100%) rename tools/ui/src/lib/components/app/models/{discover/ModelsDiscoverAvatar.svelte => ModelOrgAvatar.svelte} (90%) create mode 100644 tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelConfiguration/ModelsManagerModelConfiguration.svelte create mode 100644 tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelConfiguration/ModelsManagerModelConfigurationHeader.svelte create mode 100644 tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelConfiguration/ModelsManagerModelConfigurationInformation.svelte delete mode 100644 tools/ui/src/lib/components/app/models/ModelsSelectorOption.svelte delete mode 100644 tools/ui/src/lib/components/app/models/discover/DownloadProgressBar.svelte create mode 100644 tools/ui/src/lib/constants/models-manager.constants.ts diff --git a/tools/server/server-http.cpp b/tools/server/server-http.cpp index 33cbb156c5..d6d2bfee40 100644 --- a/tools/server/server-http.cpp +++ b/tools/server/server-http.cpp @@ -404,8 +404,8 @@ bool server_http_context::init_listener(const common_params & params) { static constexpr auto cache_revalidate = "no-cache"; // Serves an asset with ETag/304 handling, under the given caching policy. - auto serve_asset_cached = [](const std::string & name, bool isolation, const char * cache_control) { - return [name, isolation, cache_control](const httplib::Request & req, httplib::Response & res) { + auto serve_asset_cached = [](const std::string & name, const char * cache_control) { + return [name, cache_control](const httplib::Request & req, httplib::Response & res) { if (!handle_gzip_header(req, res)) { return true; // returns error message } @@ -417,10 +417,6 @@ bool server_http_context::init_listener(const common_params & params) { res.status = 304; return false; } - if (isolation) { - res.set_header("Cross-Origin-Embedder-Policy", "require-corp"); - res.set_header("Cross-Origin-Opener-Policy", "same-origin"); - } res.set_header("Cache-Control", cache_control); res.set_content(reinterpret_cast(a->data), a->size, a->type.c_str()); return false; @@ -444,8 +440,8 @@ bool server_http_context::init_listener(const common_params & params) { }; // main index file -- revalidated, so a new build is picked up on the next load - srv->Get(params.api_prefix + "/", serve_asset_cached("index.html", true, cache_revalidate)); - srv->Get(params.api_prefix + "/index.html", serve_asset_cached("index.html", true, cache_revalidate)); + srv->Get(params.api_prefix + "/", serve_asset_cached("index.html", cache_revalidate)); + srv->Get(params.api_prefix + "/index.html", serve_asset_cached("index.html", cache_revalidate)); // All remaining assets registered directly from the embedded asset table. // PWA revalidation files (sw.js, manifest, version.json) use no-cache; @@ -463,7 +459,7 @@ bool server_http_context::init_listener(const common_params & params) { SRV_DBG("serve nocache for %s\n", a.name.c_str()); srv->Get(params.api_prefix + "/" + a.name, serve_asset_nocache(a.name)); } else { - srv->Get(params.api_prefix + "/" + a.name, serve_asset_cached(a.name, false, cache_immutable)); + srv->Get(params.api_prefix + "/" + a.name, serve_asset_cached(a.name, cache_immutable)); } } diff --git a/tools/ui/src/lib/components/app/chat/ChatForm/ChatFormActions/ChatFormActionAdd/ChatFormActionAddDropdown.svelte b/tools/ui/src/lib/components/app/chat/ChatForm/ChatFormActions/ChatFormActionAdd/ChatFormActionAddDropdown.svelte index 7d0b3ac1e8..ea805eaafd 100644 --- a/tools/ui/src/lib/components/app/chat/ChatForm/ChatFormActions/ChatFormActionAdd/ChatFormActionAddDropdown.svelte +++ b/tools/ui/src/lib/components/app/chat/ChatForm/ChatFormActions/ChatFormActionAdd/ChatFormActionAddDropdown.svelte @@ -65,8 +65,7 @@ import { ModelsSelectorDropdown, ModelsSelectorSheet } from '$lib/components/app'; - import { LOCAL_BACKEND_ID } from '$lib/constants'; - import { - backendsModelsStore, - backendsStore, - conversationsStore, - deviceStore, - modelsStore, - serverStore - } from '$lib/stores'; + import { conversationsStore, deviceStore, modelsStore, serverStore } from '$lib/stores'; import { getConversationModel } from '$lib/utils'; interface Props { @@ -36,14 +28,7 @@ }: Props = $props(); let isRouter = $derived(serverStore.isRouterMode); - // the provider this selector is pointed at, which is the one its colours report - let selectorError = $derived.by(() => { - const backendId = backendsStore.active.id; - - return backendId === LOCAL_BACKEND_ID - ? Boolean(serverStore.error) - : backendsModelsStore.get(backendId).error !== null; - }); + let isOffline = $derived(!!serverStore.error); let conversationModel = $derived( getConversationModel(conversationsStore.activeMessages as DatabaseMessage[]) @@ -67,16 +52,10 @@ $effect(() => { if (conversationModel && conversationModel !== lastSyncedConversationModel) { - const option = modelsStore.models.find((m) => m.model === conversationModel); - - // only sync models served by the active backend; a model from another - // backend must not yank the active tab (and trigger a full backend - // switch) just because the conversation used it. sends resolve their - // backend explicitly via ensureModelBackend - if (option && option.backendId === backendsStore.active.id) { + if (modelsStore.models.some((m) => m.model === conversationModel)) { modelsStore.selectedModelName = conversationModel; modelsStore.selectModelByName(conversationModel); - } else if (!option) { + } else { modelsStore.selectedModelName = null; modelsStore.clearSelection(); } @@ -176,8 +155,7 @@ @@ -185,8 +163,7 @@ diff --git a/tools/ui/src/lib/components/app/chat/ChatForm/ChatFormActions/ChatFormActionReasoning.svelte b/tools/ui/src/lib/components/app/chat/ChatForm/ChatFormActions/ChatFormActionReasoning.svelte index dc40ecbc6a..ebcf3f9307 100644 --- a/tools/ui/src/lib/components/app/chat/ChatForm/ChatFormActions/ChatFormActionReasoning.svelte +++ b/tools/ui/src/lib/components/app/chat/ChatForm/ChatFormActions/ChatFormActionReasoning.svelte @@ -13,8 +13,7 @@ let isDefault = $derived(reasoning.currentEffort === ReasoningEffort.DEFAULT); - + {#snippet child({ props })} diff --git a/tools/ui/src/lib/components/app/chat/ChatForm/ChatFormPickers/ChatFormPickerCommand.svelte b/tools/ui/src/lib/components/app/chat/ChatForm/ChatFormPickers/ChatFormPickerCommand.svelte index c68a0171ae..e3ff9d780a 100644 --- a/tools/ui/src/lib/components/app/chat/ChatForm/ChatFormPickers/ChatFormPickerCommand.svelte +++ b/tools/ui/src/lib/components/app/chat/ChatForm/ChatFormPickers/ChatFormPickerCommand.svelte @@ -1,12 +1,10 @@ {#if hasError || isLoadingModel} diff --git a/tools/ui/src/lib/components/app/chat/index.ts b/tools/ui/src/lib/components/app/chat/index.ts index 243856bd55..2f7d417b4e 100644 --- a/tools/ui/src/lib/components/app/chat/index.ts +++ b/tools/ui/src/lib/components/app/chat/index.ts @@ -221,7 +221,6 @@ export { default as ChatFormActionReasoning } from './ChatForm/ChatFormActions/C */ export { default as ChatFormActionAddToolsSubmenu } from './ChatForm/ChatFormActions/ChatFormActionAdd/ChatFormActionAddToolsSubmenu.svelte'; - /** * Compact context-usage gauge with per-turn and cumulative breakdown in the tooltip. */ diff --git a/tools/ui/src/lib/components/app/misc/CollapsibleRegion.svelte b/tools/ui/src/lib/components/app/misc/CollapsibleRegion.svelte index 4a7a2ffbcc..edbb5f7743 100644 --- a/tools/ui/src/lib/components/app/misc/CollapsibleRegion.svelte +++ b/tools/ui/src/lib/components/app/misc/CollapsibleRegion.svelte @@ -36,12 +36,8 @@ diff --git a/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerFilters.svelte b/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerFilters.svelte index 9120ce582d..be3cbe6f4a 100644 --- a/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerFilters.svelte +++ b/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerFilters.svelte @@ -1,10 +1,18 @@ + +
+ + +
+ +
+
diff --git a/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelConfiguration/ModelsManagerModelConfigurationHeader.svelte b/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelConfiguration/ModelsManagerModelConfigurationHeader.svelte new file mode 100644 index 0000000000..50ddee1969 --- /dev/null +++ b/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelConfiguration/ModelsManagerModelConfigurationHeader.svelte @@ -0,0 +1,119 @@ + + +
+
+
+ + + +
+ + +

+ + + + {statusLabel} + +

+
+
+ + +
+ +
+ + + +
+
diff --git a/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelConfiguration/ModelsManagerModelConfigurationInformation.svelte b/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelConfiguration/ModelsManagerModelConfigurationInformation.svelte new file mode 100644 index 0000000000..ac341f8059 --- /dev/null +++ b/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelConfiguration/ModelsManagerModelConfigurationInformation.svelte @@ -0,0 +1,195 @@ + + +
+
+ Model + + + + {option.model} + + + + +
+ + {#each visibleRows as row (row.label)} +
+ {row.label} + + + {#if row.value === null} + - + {:else} + + {#if row.isBadge} + {row.value} + {:else} + {row.value} + {/if} + + + {#if row.isCopyable} + + {/if} + {/if} + +
+ {/each} + + {#if visibleRows.length === 0} +

This model reports no metadata.

+ {/if} + + {#if modalities.length > 0} +
+ Modalities + + +
+ {/if} +
+ +{#if !serverProps} +

+ /props values - file path, slots, build info - appear once the model is loaded. Reading this + page never loads a model. +

+{/if} + +
+ + {#snippet trigger()} + Chat Template + {/snippet} + +
{serverProps?.chat_template ??
+				gguf?.chat_template ??
+				'Not reported by the server.'}
+
+
diff --git a/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelRow.svelte b/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelRow.svelte index c694b58173..e23362e2d3 100644 --- a/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelRow.svelte +++ b/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelRow.svelte @@ -9,12 +9,12 @@ import { MoreHorizontal } from '@lucide/svelte'; import { DropdownMenuActions } from '$lib/components/app'; import { MODEL_ROW_GRID_CLASS } from '$lib/constants'; + import { KeyboardKey } from '$lib/enums'; import { modelsStore, settingsStore } from '$lib/stores'; import type { ModelOption } from '$lib/types/models'; interface Props { isFavorite: (option: ModelOption) => boolean; - /** Model this row stands for. */ option: ModelOption; onDelete: (option: ModelOption) => void; onSelect: (option: ModelOption) => void; @@ -29,9 +29,9 @@ let isHidden = $derived(modelsStore.isHidden(option.id)); function handleKeydown(event: KeyboardEvent): void { - if (event.key === ' ') event.preventDefault(); + if (event.key === KeyboardKey.SPACE) event.preventDefault(); - if (event.key === 'Enter' || event.key === ' ') onSelect(option); + if (event.key === KeyboardKey.ENTER || event.key === KeyboardKey.SPACE) onSelect(option); } diff --git a/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelsTable.svelte b/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelsTable.svelte index d1f80d29b6..b86e13d681 100644 --- a/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelsTable.svelte +++ b/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerModelsTable.svelte @@ -5,12 +5,9 @@ import ModelsManagerTableToolbar from './ModelsManagerTableToolbar.svelte'; import { isModelRunning, - type ModalityKey, modelContextLength, type ModelQuantGroup, - type ModelsTableGroup, - ModelsTableGroupKind, - ModelsTableSortKey + type ModelsTableGroup } from './utils'; import { ArrowDown, @@ -23,16 +20,25 @@ Power } from '@lucide/svelte'; import { + CollapsibleRegion, GroupedList, type GroupedListGroup, + GroupedListUnit, Logo, ModelAvatar, ModelsSection } from '$lib/components/app'; import { DialogConfirmDownload } from '$lib/components/app/dialogs'; import ModelsSelectorDownloadItem from '$lib/components/app/models/ModelsSelector/ModelsSelectorDownloadItem.svelte'; - import { FAMILY_ROW_WINDOW, MODEL_ROW_GRID_CLASS, MODEL_ROW_WINDOW } from '$lib/constants'; - import { ModelCapability, ModelDownloadConfirmAction } from '$lib/enums'; + import { + FAMILY_ROW_WINDOW, + type ModalityKey, + MODEL_ROW_GRID_CLASS, + MODEL_ROW_WINDOW, + ModelsTableGroupKind, + ModelsTableSortKey + } from '$lib/constants'; + import { KeyboardKey, ModelCapability, ModelDownloadConfirmAction } from '$lib/enums'; import { modelsStore, settingsStore } from '$lib/stores'; import type { ModelOption } from '$lib/types/models'; import { groupModelFamilies, type ModelFamilyGroup } from '$lib/utils/model-families'; @@ -72,6 +78,12 @@ /** In-flight and paused downloads, tracked by the status feed. */ let downloadEntries = $derived(modelsStore.status.getDownloadEntries()); + + /** Noun the show-more row counts in, per unit of the grouped list. */ + const SHOW_MORE_NOUNS: Record = { + [GroupedListUnit.ENTRIES]: 'models', + [GroupedListUnit.GROUPS]: 'families' + }; let pendingCancel = $state(''); let cancelOpen = $state(false); let pendingDelete = $state(''); @@ -98,7 +110,6 @@ }) ); - /** Families of one section. */ function familyGroups( group: (typeof sections)[number] ): GroupedListGroup, ModelQuantGroup>[] { @@ -109,8 +120,7 @@ })); } - // Cancel is confirmed once for the whole list, so a single dialog instance - // serves however many downloads are in flight. + // cancel is confirmed once for the whole list, so one dialog serves every row function requestCancel(repoWithTag: string): void { pendingCancel = repoWithTag; cancelOpen = true; @@ -184,9 +194,9 @@ } function handleFamilyKeydown(event: KeyboardEvent, toggle: () => void): void { - if (event.key === ' ') event.preventDefault(); + if (event.key === KeyboardKey.SPACE) event.preventDefault(); - if (event.key === 'Enter' || event.key === ' ') toggle(); + if (event.key === KeyboardKey.ENTER || event.key === KeyboardKey.SPACE) toggle(); } @@ -218,7 +228,7 @@ onToggle={() => toggleQuants(entry.key)} /> - {#if !collapsedQuants.has(entry.key)} + {#each entry.quants as quant (quant.id)} {/each} - {/if} + {:else} void; - unit: 'entries' | 'families'; + unit: GroupedListUnit; })}
{/snippet} diff --git a/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerQuantRow.svelte b/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerQuantRow.svelte index da8ac4821b..b7614b1f84 100644 --- a/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerQuantRow.svelte +++ b/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerQuantRow.svelte @@ -8,12 +8,12 @@ import { DropdownMenuActions } from '$lib/components/app'; import { Badge } from '$lib/components/ui/badge'; import { MODEL_ROW_GRID_CLASS } from '$lib/constants'; + import { KeyboardKey } from '$lib/enums'; import { modelsStore } from '$lib/stores'; import type { ModelOption } from '$lib/types/models'; interface Props { isFavorite: (option: ModelOption) => boolean; - /** Quant this row stands for. */ option: ModelOption; onDelete: (option: ModelOption) => void; onSelect: (option: ModelOption) => void; @@ -29,9 +29,9 @@ let quant = $derived(option.parsedId?.quantization ?? option.model); function handleKeydown(event: KeyboardEvent): void { - if (event.key === ' ') event.preventDefault(); + if (event.key === KeyboardKey.SPACE) event.preventDefault(); - if (event.key === 'Enter' || event.key === ' ') onSelect(option); + if (event.key === KeyboardKey.ENTER || event.key === KeyboardKey.SPACE) onSelect(option); } diff --git a/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerRepoRow.svelte b/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerRepoRow.svelte index 2693c12caa..7a946b53d4 100644 --- a/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerRepoRow.svelte +++ b/tools/ui/src/lib/components/app/models/ModelsManager/ModelsManagerRepoRow.svelte @@ -7,10 +7,10 @@ import { configuredContext, isModelRunning } from './utils'; import { ChevronDown, ChevronUp } from '@lucide/svelte'; import { MODEL_ROW_GRID_CLASS } from '$lib/constants'; + import { KeyboardKey } from '$lib/enums'; import { settingsStore } from '$lib/stores'; interface Props { - /** Repo entry the row folds. */ entry: ModelQuantGroup; expanded: boolean; onToggle: () => void; @@ -31,9 +31,9 @@ let mediaSource = $derived(entry.quants.find((quant) => quant.modalities) ?? entry.base); function handleKeydown(event: KeyboardEvent): void { - if (event.key === ' ') event.preventDefault(); + if (event.key === KeyboardKey.SPACE) event.preventDefault(); - if (event.key === 'Enter' || event.key === ' ') onToggle(); + if (event.key === KeyboardKey.ENTER || event.key === KeyboardKey.SPACE) onToggle(); } @@ -60,7 +60,6 @@ import ModelsManagerFilters from './ModelsManagerFilters.svelte'; - import { type ModalityKey } from './utils'; import { X } from '@lucide/svelte'; import { SearchInput } from '$lib/components/app/forms'; import { Button } from '$lib/components/ui/button'; + import { type ModalityKey } from '$lib/constants'; import { ModelCapability } from '$lib/enums'; import { uiStore } from '$lib/stores'; import type { Snippet } from 'svelte'; diff --git a/tools/ui/src/lib/components/app/models/ModelsManager/utils.ts b/tools/ui/src/lib/components/app/models/ModelsManager/utils.ts index d55c83f73a..fd84ef4470 100644 --- a/tools/ui/src/lib/components/app/models/ModelsManager/utils.ts +++ b/tools/ui/src/lib/components/app/models/ModelsManager/utils.ts @@ -1,12 +1,10 @@ +import { ModelGroupKind, ModelsTableGroupKind } from '$lib/constants'; import { ModelCapability, ServerModelStatus } from '$lib/enums'; import { HuggingFaceService, ModelsService } from '$lib/services'; import { modelsStore } from '$lib/stores'; -import type { ModelModalities, ModelOption } from '$lib/types/models'; +import type { ModelOption } from '$lib/types/models'; import { detectThinkingSupport, detectToolUseSupport } from '$lib/utils'; -/** What a group folds, which decides its label. */ -export type ModelGroupKind = 'quants' | 'variants'; - /** One repo of the table, with the rows it ships as. */ export interface ModelQuantGroup { base: ModelOption; @@ -15,36 +13,6 @@ export interface ModelQuantGroup { quants: ModelOption[]; } -/** - * Kind of one collapsible block of the manager's table. A plain constant map, so - * provider blocks can extend the union with their own string kinds. - */ -export const ModelsTableGroupKind = { - FAVORITES: 'favorites', - HIDDEN: 'hidden', - LOADED: 'loaded', - LOCAL: 'local' -} as const; - -export type ModelsTableGroupKind = (typeof ModelsTableGroupKind)[keyof typeof ModelsTableGroupKind]; - -/** Column the manager's table can be ordered by. */ -export const ModelsTableSortKey = { - CONTEXT: 'context', - NAME: 'name', - STATUS: 'status' -} as const; - -export type ModelsTableSortKey = (typeof ModelsTableSortKey)[keyof typeof ModelsTableSortKey]; - -/** Header label of each manager section. */ -export const MODELS_TABLE_GROUP_LABELS: Record = { - [ModelsTableGroupKind.FAVORITES]: 'Favorites', - [ModelsTableGroupKind.HIDDEN]: 'Hidden models', - [ModelsTableGroupKind.LOADED]: 'Loaded models', - [ModelsTableGroupKind.LOCAL]: 'Local models' -}; - /** One collapsible block of the manager's table. */ export interface ModelsTableGroup { /** One entry per repo, its quants hanging off it. */ @@ -54,12 +22,6 @@ export interface ModelsTableGroup { label: string; } -/** Modalities a model can accept, as the manager filter offers them. */ -export type ModalityKey = keyof ModelModalities; - -/** Modalities the manager filter offers, in display order. */ -export const MODALITY_KEYS: ModalityKey[] = ['vision', 'video', 'audio']; - /** True when the model is loaded (or sleeping) and not mid-operation. */ export function isModelRunning(option: ModelOption): boolean { const status = modelsStore.getModelStatus(option.model); @@ -85,10 +47,7 @@ export function modelSupports(option: ModelOption, capability: ModelCapability): : detectThinkingSupport(template); } -/** - * Context a model reports: the provider listing first, then whatever the Hub has - * cached for it. 0 means nothing is known yet. - */ +/** Context a model reports: the provider listing first, then the cached Hub record. */ export function modelContextLength(option: ModelOption): number { return ( option.contextLength ?? @@ -118,7 +77,7 @@ export function groupModelQuants(models: ModelOption[]): ModelQuantGroup[] { continue; } - groups.set(key, { base: option, key, kind: 'quants', quants: [option] }); + groups.set(key, { base: option, key, kind: ModelGroupKind.QUANTS, quants: [option] }); } return Array.from(groups.values()).flatMap((group) => { @@ -131,7 +90,7 @@ export function groupModelQuants(models: ModelOption[]): ModelQuantGroup[] { ...group, base: option, key: `${group.key}::${option.id}`, - kind: 'variants' as const, + kind: ModelGroupKind.VARIANTS, quants: [option] })); } @@ -146,5 +105,5 @@ function groupKind(quants: ModelOption[]): ModelGroupKind { (option) => (option.parsedId ?? ModelsService.parseModelId(option.model)).quantization ); - return isQuant ? 'quants' : 'variants'; + return isQuant ? ModelGroupKind.QUANTS : ModelGroupKind.VARIANTS; } diff --git a/tools/ui/src/lib/components/app/models/ModelsSection.svelte b/tools/ui/src/lib/components/app/models/ModelsSection.svelte index 2427adf1d9..749dc5b070 100644 --- a/tools/ui/src/lib/components/app/models/ModelsSection.svelte +++ b/tools/ui/src/lib/components/app/models/ModelsSection.svelte @@ -5,7 +5,6 @@ import type { Snippet } from 'svelte'; interface Props { - /** Section rows. */ children: Snippet; /** Extra classes for the chevron, to line it up with a row's own control. */ chevronClass?: string; @@ -26,7 +25,6 @@ sectionHeaderClass?: string; /** Sticky class of the header, so a surface can shade it differently. */ stickyClass?: string; - /** Sticks the header to the top of the scrollport. */ sticky?: boolean; } @@ -50,7 +48,7 @@ let triggerClass = $derived( `${sectionHeaderClass} flex w-full cursor-pointer items-center gap-1.5 text-left${sticky ? ` ${stickyClass}` : ''}` ); - // the dropdown publishes its search block height, surfaces without one fall back to 0 + // surfaces without a search block fall back to a 0 sticky height let triggerStyle = $derived(sticky ? 'top: var(--dropdown-sticky-height, 0px)' : ''); @@ -68,8 +66,7 @@ aria-label="Back to all providers" class="-ml-1 inline-flex shrink-0 cursor-pointer items-center rounded-sm p-0.5 text-muted-foreground transition hover:bg-muted/60 hover:text-foreground" onclick={(event) => { - // the surrounding trigger toggles the section, the back control - // must not collapse the list it is leaving + // the back control must not collapse the list it is leaving event.stopPropagation(); onBack?.(); }} diff --git a/tools/ui/src/lib/components/app/models/ModelsSelector/ModelsSelectorDownloadItem.svelte b/tools/ui/src/lib/components/app/models/ModelsSelector/ModelsSelectorDownloadItem.svelte index 6ee03f2d79..e4bdff6994 100644 --- a/tools/ui/src/lib/components/app/models/ModelsSelector/ModelsSelectorDownloadItem.svelte +++ b/tools/ui/src/lib/components/app/models/ModelsSelector/ModelsSelectorDownloadItem.svelte @@ -1,8 +1,8 @@
- +
{#if isLoading} diff --git a/tools/ui/src/lib/components/app/models/ModelsSelector/ModelsSelectorSheet.svelte b/tools/ui/src/lib/components/app/models/ModelsSelector/ModelsSelectorSheet.svelte index 74a8c42f50..0619c12b92 100644 --- a/tools/ui/src/lib/components/app/models/ModelsSelector/ModelsSelectorSheet.svelte +++ b/tools/ui/src/lib/components/app/models/ModelsSelector/ModelsSelectorSheet.svelte @@ -7,7 +7,6 @@ ModelsSelectorTriggerIcon, SearchInput } from '$lib/components/app'; - import { DialogBackendForm } from '$lib/components/app/backends'; import * as Sheet from '$lib/components/ui/sheet'; import { MODEL_ICON, SETTINGS_KEYS } from '$lib/constants'; import { ServerModelStatus } from '$lib/enums'; @@ -19,14 +18,8 @@ class?: string; currentModel?: string | null; /** Callback when model changes. Return false to keep menu open (e.g., for validation failures) */ - onModelChange?: ( - modelId: string, - modelName: string, - backendId?: string - ) => Promise | boolean | void; + onModelChange?: (modelId: string, modelName: string) => Promise | boolean | void; disabled?: boolean; - /** The provider behind this selector is unreachable. */ - error?: boolean; forceForegroundText?: boolean; /** When true, user's global selection takes priority over currentModel (for form selector) */ useGlobalSelection?: boolean; @@ -36,14 +29,12 @@ class: className = '', currentModel = null, disabled = false, - error = false, forceForegroundText = false, onModelChange, useGlobalSelection = false }: Props = $props(); let sheetOpen = $state(false); - let showAddBackend = $state(false); const ms = useModelsSelector({ currentModel: () => currentModel, @@ -54,7 +45,6 @@ useGlobalSelection: () => useGlobalSelection }); - // one setting for every model id in the selector: the trigger and the rows const showOrgName = $derived(settingsStore.config[SETTINGS_KEYS.SHOW_MODEL_ORG_NAME] ?? true); export function open() { @@ -73,13 +63,6 @@ // let the sheet finish closing before the dialog takes focus setTimeout(() => uiStore.openModelsManager(), 0); } - - function handleAddBackend() { - sheetOpen = false; - - // let the sheet finish closing before the dialog takes focus - setTimeout(() => (showAddBackend = true), 0); - }
@@ -89,13 +72,7 @@ Loading models…
{:else if ms.options.length === 0 && ms.isMultiModel} - + No models yet. {:else} {@const selectedOption = ms.getDisplayOption()} {@const triggerModel = selectedOption?.model} @@ -114,15 +91,13 @@