ui : split out the params badge fallback feature

Remove the useModelParamsFallback hook and its inline duplicate in the
discover list item, along with the ModelId `params` prop it fed. The
reliability of the lazy HF param-count fallback is uncertain, so this
lands as its own change to revisit later.

Assisted-by: llama-ui:Qwen3.8-Flash-Next
This commit is contained in:
Aleksander Grygier
2026-09-04 14:44:27 +02:00
parent bfeac126bd
commit 9ec63c5db1
6 changed files with 6 additions and 138 deletions
@@ -31,8 +31,6 @@
contextLength?: number;
/** Min/max GGUF file size (main + draft) across quants; renders a range when set. */
sizeRange?: { min: number; max: number } | null;
/** Params badge fallback (formatted) when the model id carries no params token. */
params?: string;
draftSidecars?: ModelSidecar[];
/** Allow badges to wrap onto new lines instead of truncating. */
wrap?: boolean;
@@ -54,7 +52,6 @@
iconsOnNewLine = false,
modalities,
modelId,
params,
showRaw = undefined,
showRawTooltip = false,
sizeRange,
@@ -91,7 +88,7 @@
let hasBadges = $derived(
parsed.sidecar ||
((parsed.params || params) && !hideParameters) ||
(parsed.params && !hideParameters) ||
(parsed.quantization && !resolvedHideQuantization) ||
primaryAlias ||
uniqueAliases.length > 1 ||
@@ -183,9 +180,9 @@
</span>
{/if}
{#if (parsed.params || params) && !hideParameters}
{#if parsed.params && !hideParameters}
<span class={badgeClass}>
{parsed.params ?? params}{parsed.activatedParams ? `-${parsed.activatedParams}` : ''}
{parsed.params}{parsed.activatedParams ? `-${parsed.activatedParams}` : ''}
</span>
{/if}
@@ -18,7 +18,6 @@
SETTINGS_KEYS
} from '$lib/constants';
import { KeyboardKey, ServerModelStatus } from '$lib/enums';
import { useModelParamsFallback } from '$lib/hooks/use-model-params-fallback.svelte';
import { useModelsSelector } from '$lib/hooks/use-models-selector.svelte';
import { useReasoningMenu } from '$lib/hooks/use-reasoning-menu.svelte';
import { modelsStore, settingsStore } from '$lib/stores';
@@ -73,12 +72,6 @@
const selectedOption = $derived(ms.getDisplayOption());
const triggerModel = $derived(selectedOption?.model ?? null);
// Params badge fallback for trigger ids that carry no params token.
const { paramsFallback } = useModelParamsFallback({
metaParams: () => selectedOption?.meta?.n_params,
modelId: () => triggerModel
});
const showOrgNameInTrigger = $derived(
settingsStore.config[SETTINGS_KEYS.SHOW_MODEL_ORG_NAME_IN_TRIGGER] ?? false
);
@@ -235,7 +228,6 @@
hideOrgName={!showOrgNameInTrigger}
hideQuantization
modelId={selectedOption.model}
params={paramsFallback}
/>
{:else}
<span class="min-w-0 font-medium">Select model</span>
@@ -384,7 +376,6 @@
hideOrgName={!showOrgNameInTrigger}
hideQuantization
modelId={selectedOption.model}
params={paramsFallback}
/>
{/if}
@@ -14,7 +14,6 @@
import { ActionIcon, ModelId } from '$lib/components/app';
import { HF_BASE_MODEL_TAG_REGEX, ICON_CLASS_DEFAULT, PATH_SEPARATOR } from '$lib/constants';
import { ModelCapability, ServerModelStatus } from '$lib/enums';
import { useModelParamsFallback } from '$lib/hooks/use-model-params-fallback.svelte';
import { HuggingFaceService, ModelsService } from '$lib/services';
import { modelsStore } from '$lib/stores';
import type { ModelOption } from '$lib/types/models';
@@ -99,11 +98,6 @@
reasoning: modelsStore.props.checkModelSupportsThinking(option.model),
tools: option.capabilities.includes(ModelCapability.TOOL_USE)
}));
const { paramsFallback } = useModelParamsFallback({
metaParams: () => option.meta?.n_params,
modelId: () => option.model
});
</script>
<div
@@ -142,7 +136,6 @@
{hideOrgName}
{modalities}
modelId={option.model}
params={paramsFallback}
showRawTooltip
supportsThinking={capabilities.reasoning}
supportsToolUse={capabilities.tools}
@@ -9,7 +9,6 @@
} from '$lib/components/app';
import * as Sheet from '$lib/components/ui/sheet';
import { ServerModelStatus } from '$lib/enums';
import { useModelParamsFallback } from '$lib/hooks/use-model-params-fallback.svelte';
import { useModelsSelector } from '$lib/hooks/use-models-selector.svelte';
import { modelsStore } from '$lib/stores';
import { modelLoadFraction } from '$lib/utils';
@@ -45,15 +44,6 @@
useGlobalSelection: () => useGlobalSelection
});
const selectedOption = $derived(ms.getDisplayOption());
const triggerModel = $derived(selectedOption?.model ?? null);
// Params badge fallback for trigger ids that carry no params token.
const { paramsFallback } = useModelParamsFallback({
metaParams: () => selectedOption?.meta?.n_params,
modelId: () => triggerModel
});
export function open() {
ms.handleOpenChange(true);
}
@@ -116,7 +106,6 @@
hideQuantization
hideTags
modelId={selectedOption?.model || ''}
params={paramsFallback}
/>
{/if}
@@ -201,12 +190,7 @@
>
<Package class="h-3.5 w-3.5 shrink-0" />
<ModelId
class="font-medium"
hideQuantization
modelId={selectedOption?.model || ''}
params={paramsFallback}
/>
<ModelId class="font-medium" hideQuantization modelId={selectedOption?.model || ''} />
{#if ms.updating}
<Loader2 class="h-3 w-3.5 shrink-0 animate-spin" />
@@ -8,12 +8,12 @@
MODEL_ID,
type ModelSidecar
} from '$lib/constants';
import { HuggingFaceService, ModelsService } from '$lib/services';
import { HuggingFaceService } from '$lib/services';
import { modelsHubStore } from '$lib/stores';
import type { ModelsHubSizeRange } from '$lib/stores/models-hub/index.svelte';
import type { HfModelInfo } from '$lib/types/huggingface';
import type { ModelModalities } from '$lib/types/models';
import { detectThinkingSupport, detectToolUseSupport, formatParameters } from '$lib/utils';
import { detectThinkingSupport, detectToolUseSupport } from '$lib/utils';
import { SvelteSet } from 'svelte/reactivity';
interface Props {
@@ -40,35 +40,6 @@
let contextLength = $derived(model.gguf?.context_length);
// Params badge fallback: the id usually carries the count (`Qwen3.8-27B`),
// but ids like `Kimi-K3` do not. Fall back to the HF param count
// (`gguf.total`), fetched lazily only when neither the response nor the name
// has it.
let fetchedParams = $state<number | null>(null);
$effect(() => {
fetchedParams = null;
if (model.gguf?.total || ModelsService.parseModelId(model.id).params) return;
let cancelled = false;
void HuggingFaceService.getDetails(model.id).then((info) => {
if (!cancelled && info?.gguf?.total) fetchedParams = info.gguf.total;
});
return () => {
cancelled = true;
};
});
let hfParams = $derived(model.gguf?.total ?? fetchedParams);
let paramsFallback = $derived(
hfParams && !ModelsService.parseModelId(model.id).params
? formatParameters(hfParams)
: undefined
);
// Reasoning support from the chat template, matching the details view.
let supportsThinking = $derived(detectThinkingSupport(model.gguf?.chat_template ?? ''));
@@ -152,7 +123,6 @@
iconsOnNewLine
{modalities}
modelId={model.id}
params={paramsFallback}
{sizeRange}
{supportsThinking}
{supportsToolUse}
@@ -1,67 +0,0 @@
import { MODEL_ID } from '$lib/constants';
import { HuggingFaceService, ModelsService } from '$lib/services';
import { formatParameters, normalizeModelName } from '$lib/utils';
export interface UseModelParamsFallbackOptions {
/** Model id to parse; null disables the fallback. */
modelId: () => string | null | undefined;
/** Server-reported parameter count from the model meta, when available. */
metaParams?: () => unknown;
}
/**
* Params badge fallback for model ids that carry no params token (`Kimi-K3`).
* Prefers the meta `n_params`, then the HF GGUF total (`gguf.total`) fetched
* lazily like the models hub list does, only when neither the id nor the meta
* has it. Returns the formatted badge text, or undefined when unavailable.
*/
export function useModelParamsFallback(opts: UseModelParamsFallbackOptions) {
const parsedParams = $derived.by(() => {
const id = opts.modelId();
return id ? ModelsService.parseModelId(id).params : null;
});
const metaParams = $derived.by(() => {
const value = opts.metaParams?.();
return typeof value === 'number' && value > 0 ? value : null;
});
// HF repo id: the `org/model` part without the `:revision/quant` suffix;
// local paths and bare names are not HF repos.
const hfRepoId = $derived.by(() => {
const id = opts.modelId();
if (!id) return null;
const [repo] = id.split(MODEL_ID.QUANTIZATION_SEPARATOR);
const normalized = normalizeModelName(repo ?? '');
return normalized.includes(MODEL_ID.ORG_SEPARATOR) ? normalized : null;
});
let fetchedParams = $state<number | null>(null);
$effect(() => {
fetchedParams = null;
if (parsedParams || metaParams || !hfRepoId) return;
let cancelled = false;
void HuggingFaceService.getDetails(hfRepoId).then((info) => {
if (!cancelled && info?.gguf?.total) fetchedParams = info.gguf.total;
});
return () => {
cancelled = true;
};
});
const paramsFallback = $derived(
!parsedParams && (metaParams ?? fetchedParams)
? formatParameters(metaParams ?? fetchedParams)
: undefined
);
return { paramsFallback };
}