mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-09-04 02:37:27 +02:00
ui : restructure discover components to the target names
- ModelsDiscoverItem + ModelsDiscoverInfo fold into ModelsDiscoverListItem (avatar + model id + badges + context/size) - ModelsDiscoverDetails* renamed to ModelsDiscoverModelDetails* - TerminalCommands renamed to ModelsDiscoverModelDetailsCommands - ModelsDiscoverDetailsName folded into the details header - ModelsDiscoverListSearch extracted from the list search input - stories updated for the new names Assisted-by: pi
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { SearchInput } from '$lib/components/app';
|
||||
import { ModelsDiscoverDetails, ModelsDiscoverList } from '$lib/components/app/models/discover';
|
||||
import {
|
||||
ModelsDiscoverList,
|
||||
ModelsDiscoverModelDetails
|
||||
} from '$lib/components/app/models/discover';
|
||||
import { HuggingFaceService } from '$lib/services';
|
||||
import { modelsHubStore } from '$lib/stores';
|
||||
import type { HfModelDetailInfo, HfModelSibling } from '$lib/types';
|
||||
@@ -122,13 +125,13 @@
|
||||
|
||||
<main class="overflow-y-auto">
|
||||
{#if selectedId}
|
||||
<ModelsDiscoverDetails
|
||||
details={details}
|
||||
<ModelsDiscoverModelDetails
|
||||
{details}
|
||||
error={detailError}
|
||||
files={files}
|
||||
{files}
|
||||
loading={detailLoading}
|
||||
modelId={selectedId}
|
||||
readme={readme}
|
||||
{readme}
|
||||
/>
|
||||
{/if}
|
||||
</main>
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { ExternalLink, Image, Lightbulb, Wrench } from '@lucide/svelte';
|
||||
import * as Tooltip from '$lib/components/ui/tooltip';
|
||||
import { HuggingFaceService } from '$lib/services';
|
||||
|
||||
interface Props {
|
||||
/** Full HuggingFace model id (quant org + name), e.g. `ggml-org/Qwen3.8-27B-GGUF`. */
|
||||
modelId: string;
|
||||
/** Base model ids, shown as small text under the quant name. */
|
||||
baseModels: string[];
|
||||
hasVision: boolean;
|
||||
hasTools: boolean;
|
||||
hasReasoning: boolean;
|
||||
}
|
||||
|
||||
let { baseModels, hasReasoning, hasTools, hasVision, modelId }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="min-w-0">
|
||||
<div class="flex items-center gap-2">
|
||||
<h1 class="truncate text-lg font-semibold">{modelId}</h1>
|
||||
|
||||
{#if hasVision || hasTools || hasReasoning}
|
||||
<div class="flex shrink-0 items-center gap-2.5 text-muted-foreground">
|
||||
{#if hasVision}
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger>
|
||||
<Image class="h-4 w-4" />
|
||||
</Tooltip.Trigger>
|
||||
|
||||
<Tooltip.Content>
|
||||
<p>Vision</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
{/if}
|
||||
|
||||
{#if hasTools}
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger>
|
||||
<Wrench class="h-4 w-4" />
|
||||
</Tooltip.Trigger>
|
||||
|
||||
<Tooltip.Content>
|
||||
<p>Tool use</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
{/if}
|
||||
|
||||
{#if hasReasoning}
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger>
|
||||
<Lightbulb class="h-4 w-4" />
|
||||
</Tooltip.Trigger>
|
||||
|
||||
<Tooltip.Content>
|
||||
<p>Reasoning</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if baseModels.length}
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="truncate text-xs text-muted-foreground">{baseModels.join(', ')}</span>
|
||||
|
||||
<a
|
||||
aria-label="View base model on HuggingFace"
|
||||
class="shrink-0 text-muted-foreground transition-colors hover:text-foreground"
|
||||
href={HuggingFaceService.getModelUrl(baseModels[0])}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<ExternalLink class="h-3 w-3" />
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -1,43 +0,0 @@
|
||||
<script lang="ts">
|
||||
import ModelsDiscoverAvatar from './ModelsDiscoverAvatar.svelte';
|
||||
import ModelsDiscoverInfo from './ModelsDiscoverInfo.svelte';
|
||||
import { HuggingFaceService } from '$lib/services';
|
||||
import type { HfModelInfo } from '$lib/types/huggingface';
|
||||
|
||||
interface Props {
|
||||
model: HfModelInfo;
|
||||
active?: boolean;
|
||||
/** Show the original (base) model's org avatar instead of the repo's org. */
|
||||
showBaseModelAvatar?: boolean;
|
||||
onSelect?: (modelId: string) => void;
|
||||
}
|
||||
|
||||
let { active = false, model, onSelect, showBaseModelAvatar = false }: Props = $props();
|
||||
|
||||
let org = $derived(model.id.split('/')[0] ?? model.id);
|
||||
|
||||
// Org whose avatar is shown: the base model's org when showBaseModelAvatar
|
||||
// (e.g. the Qwen logo for ggml-org/Qwen3.8-27B-GGUF), else the repo's org.
|
||||
let avatarOrg = $derived.by(() => {
|
||||
if (!showBaseModelAvatar) return org;
|
||||
|
||||
const base = HuggingFaceService.getBaseModels(model)[0];
|
||||
|
||||
return base?.split('/')[0] || org;
|
||||
});
|
||||
</script>
|
||||
|
||||
<li>
|
||||
<button
|
||||
aria-current={active ? 'page' : undefined}
|
||||
class="flex w-full cursor-pointer items-start gap-2.5 rounded-lg p-2.5 text-left transition-colors {active
|
||||
? 'bg-primary/10 hover:bg-primary/15'
|
||||
: 'hover:bg-muted/60'}"
|
||||
onclick={() => onSelect?.(model.id)}
|
||||
type="button"
|
||||
>
|
||||
<ModelsDiscoverAvatar org={avatarOrg} quantOrg={showBaseModelAvatar ? org : undefined} />
|
||||
|
||||
<ModelsDiscoverInfo {model} />
|
||||
</button>
|
||||
</li>
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import ModelsDiscoverItem from './ModelsDiscoverItem.svelte';
|
||||
import ModelsDiscoverListItem from './ModelsDiscoverListItem.svelte';
|
||||
import type { HfModelInfo } from '$lib/types/huggingface';
|
||||
|
||||
interface Props {
|
||||
@@ -15,6 +15,11 @@
|
||||
|
||||
<ul class="space-y-0.5 p-2">
|
||||
{#each models as model (model.id)}
|
||||
<ModelsDiscoverItem active={model.id === activeId} {model} {onSelect} {showBaseModelAvatar} />
|
||||
<ModelsDiscoverListItem
|
||||
active={model.id === activeId}
|
||||
{model}
|
||||
{onSelect}
|
||||
{showBaseModelAvatar}
|
||||
/>
|
||||
{/each}
|
||||
</ul>
|
||||
|
||||
+47
-17
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import ModelId from '../ModelId.svelte';
|
||||
import ModelsDiscoverAvatar from './ModelsDiscoverAvatar.svelte';
|
||||
import { isAuxSidecar, type ModelSidecar } from '$lib/constants';
|
||||
import { HuggingFaceService, ModelsService } from '$lib/services';
|
||||
import { modelsHubStore } from '$lib/stores';
|
||||
@@ -10,9 +11,25 @@
|
||||
|
||||
interface Props {
|
||||
model: HfModelInfo;
|
||||
active?: boolean;
|
||||
/** Show the original (base) model's org avatar instead of the repo's org. */
|
||||
showBaseModelAvatar?: boolean;
|
||||
onSelect?: (modelId: string) => void;
|
||||
}
|
||||
|
||||
let { model }: Props = $props();
|
||||
let { active = false, model, onSelect, showBaseModelAvatar = false }: Props = $props();
|
||||
|
||||
let org = $derived(model.id.split('/')[0] ?? model.id);
|
||||
|
||||
// Org whose avatar is shown: the base model's org when showBaseModelAvatar
|
||||
// (e.g. the Qwen logo for ggml-org/Qwen3.8-27B-GGUF), else the repo's org.
|
||||
let avatarOrg = $derived.by(() => {
|
||||
if (!showBaseModelAvatar) return org;
|
||||
|
||||
const base = HuggingFaceService.getBaseModels(model)[0];
|
||||
|
||||
return base?.split('/')[0] || org;
|
||||
});
|
||||
|
||||
let contextLength = $derived(model.gguf?.context_length);
|
||||
|
||||
@@ -130,19 +147,32 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<span class="min-w-0 flex-1">
|
||||
<ModelId
|
||||
class="min-w-0"
|
||||
{contextLength}
|
||||
{draftSidecars}
|
||||
hideOrgName
|
||||
iconsOnNewLine
|
||||
{modalities}
|
||||
modelId={model.id}
|
||||
params={paramsFallback}
|
||||
{sizeRange}
|
||||
{supportsThinking}
|
||||
{supportsToolUse}
|
||||
wrap
|
||||
/>
|
||||
</span>
|
||||
<li>
|
||||
<button
|
||||
aria-current={active ? 'page' : undefined}
|
||||
class="flex w-full cursor-pointer items-start gap-2.5 rounded-lg p-2.5 text-left transition-colors {active
|
||||
? 'bg-primary/10 hover:bg-primary/15'
|
||||
: 'hover:bg-muted/60'}"
|
||||
onclick={() => onSelect?.(model.id)}
|
||||
type="button"
|
||||
>
|
||||
<ModelsDiscoverAvatar org={avatarOrg} quantOrg={showBaseModelAvatar ? org : undefined} />
|
||||
|
||||
<span class="min-w-0 flex-1">
|
||||
<ModelId
|
||||
class="min-w-0"
|
||||
{contextLength}
|
||||
{draftSidecars}
|
||||
hideOrgName
|
||||
iconsOnNewLine
|
||||
{modalities}
|
||||
modelId={model.id}
|
||||
params={paramsFallback}
|
||||
{sizeRange}
|
||||
{supportsThinking}
|
||||
{supportsToolUse}
|
||||
wrap
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</li>
|
||||
+5
-5
@@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import ModelsDiscoverDetailsDownloadOptions from './ModelsDiscoverDetailsDownloadOptions.svelte';
|
||||
import ModelsDiscoverDetailsHeader from './ModelsDiscoverDetailsHeader.svelte';
|
||||
import ModelsDiscoverDetailsReadme from './ModelsDiscoverDetailsReadme.svelte';
|
||||
import TerminalCommands from './TerminalCommands.svelte';
|
||||
import ModelsDiscoverModelDetailsCommands from './ModelsDiscoverModelDetailsCommands.svelte';
|
||||
import ModelsDiscoverDetailsDownloadOptions from './ModelsDiscoverModelDetailsDownloadOptions.svelte';
|
||||
import ModelsDiscoverDetailsHeader from './ModelsDiscoverModelDetailsHeader.svelte';
|
||||
import ModelsDiscoverDetailsReadme from './ModelsDiscoverModelDetailsReadme.svelte';
|
||||
import { isAuxSidecar, type ModelSidecar } from '$lib/constants';
|
||||
import { HuggingFaceService } from '$lib/services';
|
||||
import type { HfModelDetailInfo, HfModelSibling } from '$lib/types/huggingface';
|
||||
@@ -108,7 +108,7 @@
|
||||
|
||||
<ModelsDiscoverDetailsDownloadOptions {bitDepthRows} {modelId} />
|
||||
|
||||
<TerminalCommands {modelId} sidecars={draftSidecars} />
|
||||
<ModelsDiscoverModelDetailsCommands {modelId} sidecars={draftSidecars} />
|
||||
|
||||
<ModelsDiscoverDetailsReadme {readme} />
|
||||
</div>
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { Check, Copy, Server, SquareTerminal } from '@lucide/svelte';
|
||||
import { isAuxSidecar, type ModelSidecar } from '$lib/constants';
|
||||
import { ModelAuxSidecar, ModelDraftSidecar } from '$lib/enums';
|
||||
import { ModelAuxSidecar, ModelDraftSidecar } from '$lib/enums';
|
||||
import { copyToClipboard } from '$lib/utils';
|
||||
|
||||
interface Props {
|
||||
+12
-4
@@ -6,7 +6,7 @@
|
||||
import { isAuxSidecar, type ModelSidecar } from '$lib/constants';
|
||||
import { HuggingFaceService, ModelsService } from '$lib/services';
|
||||
import { modelsStore } from '$lib/stores';
|
||||
import type { ModelDownloadProgress } from '$lib/types';
|
||||
import type { ModelDownloadProgress } from '$lib/types';
|
||||
import type { HfModelSibling } from '$lib/types/huggingface';
|
||||
import { estimateModelMemoryBytes } from '$lib/utils';
|
||||
|
||||
@@ -33,7 +33,11 @@ import type { ModelDownloadProgress } from '$lib/types';
|
||||
/** GGUF files grouped by bit depth. */
|
||||
bitDepthRows: BitDepthRow[];
|
||||
/** Download state lookup; defaults to the models store status feed. */
|
||||
getDownloadState?: (repoWithTag: string, filePath: string, isSidecar: boolean) => DownloadEntryState;
|
||||
getDownloadState?: (
|
||||
repoWithTag: string,
|
||||
filePath: string,
|
||||
isSidecar: boolean
|
||||
) => DownloadEntryState;
|
||||
}
|
||||
|
||||
let { bitDepthRows, getDownloadState, modelId }: Props = $props();
|
||||
@@ -93,13 +97,17 @@ import type { ModelDownloadProgress } from '$lib/types';
|
||||
{@const meta = HuggingFaceService.extractQuantMeta(file.path)}
|
||||
{@const basename = file.path.split('/').pop() ?? file.path}
|
||||
{@const label = meta?.quant ?? basename.replace(/\.gguf$/i, '')}
|
||||
{@const hfRepoWithTag = ModelsService.buildDownloadTag(modelId, meta?.quant ?? null, meta?.sidecar ?? null)}
|
||||
{@const hfRepoWithTag = ModelsService.buildDownloadTag(
|
||||
modelId,
|
||||
meta?.quant ?? null,
|
||||
meta?.sidecar ?? null
|
||||
)}
|
||||
{@const state = stateFor(hfRepoWithTag, file.path, Boolean(meta?.sidecar))}
|
||||
{@const isDownloading = state.isDownloading}
|
||||
{@const progress = state.progress}
|
||||
{@const isDownloaded = state.isDownloaded}
|
||||
{@const isFailed = state.isFailed}
|
||||
{@const memoryGb = Math.ceil(estimateModelMemoryBytes(file.size ?? 0) / (1024 ** 3))}
|
||||
{@const memoryGb = Math.ceil(estimateModelMemoryBytes(file.size ?? 0) / 1024 ** 3)}
|
||||
{@const tooltipText = isDownloading
|
||||
? `Downloading ${file.path}`
|
||||
: isDownloaded
|
||||
+71
-9
@@ -1,8 +1,16 @@
|
||||
<script lang="ts">
|
||||
import ModelsDiscoverAvatar from './ModelsDiscoverAvatar.svelte';
|
||||
import ModelsDiscoverChatTemplateDialog from './ModelsDiscoverChatTemplateDialog.svelte';
|
||||
import ModelsDiscoverDetailsName from './ModelsDiscoverDetailsName.svelte';
|
||||
import { Download, ExternalLink, Heart, MessageSquareCode } from '@lucide/svelte';
|
||||
import {
|
||||
Download,
|
||||
ExternalLink,
|
||||
Heart,
|
||||
Image,
|
||||
Lightbulb,
|
||||
MessageSquareCode,
|
||||
Wrench
|
||||
} from '@lucide/svelte';
|
||||
import * as Tooltip from '$lib/components/ui/tooltip';
|
||||
import { ICON_CLASS_SM } from '$lib/constants';
|
||||
import { HuggingFaceService } from '$lib/services';
|
||||
import { modelsHubStore } from '$lib/stores';
|
||||
@@ -43,13 +51,67 @@
|
||||
<div class="flex min-w-0 items-center gap-2">
|
||||
<ModelsDiscoverAvatar org={avatarOrg} {quantOrg} />
|
||||
|
||||
<ModelsDiscoverDetailsName
|
||||
{baseModels}
|
||||
{hasReasoning}
|
||||
{hasTools}
|
||||
{hasVision}
|
||||
modelId={details.id ?? modelId}
|
||||
/>
|
||||
<div class="min-w-0">
|
||||
<div class="flex items-center gap-2">
|
||||
<h1 class="truncate text-lg font-semibold">{details.id ?? modelId}</h1>
|
||||
|
||||
{#if hasVision || hasTools || hasReasoning}
|
||||
<div class="flex shrink-0 items-center gap-2.5 text-muted-foreground">
|
||||
{#if hasVision}
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger>
|
||||
<Image class="h-4 w-4" />
|
||||
</Tooltip.Trigger>
|
||||
|
||||
<Tooltip.Content>
|
||||
<p>Vision</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
{/if}
|
||||
|
||||
{#if hasTools}
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger>
|
||||
<Wrench class="h-4 w-4" />
|
||||
</Tooltip.Trigger>
|
||||
|
||||
<Tooltip.Content>
|
||||
<p>Tool use</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
{/if}
|
||||
|
||||
{#if hasReasoning}
|
||||
<Tooltip.Root>
|
||||
<Tooltip.Trigger>
|
||||
<Lightbulb class="h-4 w-4" />
|
||||
</Tooltip.Trigger>
|
||||
|
||||
<Tooltip.Content>
|
||||
<p>Reasoning</p>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if baseModels.length}
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="truncate text-xs text-muted-foreground">{baseModels.join(', ')}</span>
|
||||
|
||||
<a
|
||||
aria-label="View base model on HuggingFace"
|
||||
class="shrink-0 text-muted-foreground transition-colors hover:text-foreground"
|
||||
href={HuggingFaceService.getModelUrl(baseModels[0])}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<ExternalLink class="h-3 w-3" />
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a
|
||||
@@ -29,7 +29,7 @@ export { default as ModelsDiscoverList } from './ModelsDiscoverList.svelte';
|
||||
*
|
||||
* One model entry in the sidebar list. Links to `/models-hub/[org]/[model]`.
|
||||
*/
|
||||
export { default as ModelsDiscoverItem } from './ModelsDiscoverItem.svelte';
|
||||
export { default as ModelsDiscoverListItem } from './ModelsDiscoverListItem.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverAvatar** - Org avatar for a model row
|
||||
@@ -39,21 +39,13 @@ export { default as ModelsDiscoverItem } from './ModelsDiscoverItem.svelte';
|
||||
*/
|
||||
export { default as ModelsDiscoverAvatar } from './ModelsDiscoverAvatar.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverInfo** - Model name + metadata for a row
|
||||
*
|
||||
* Renders the model name via ModelId and the remaining metadata (org, last
|
||||
* modified, params, downloads, likes, vision) below it.
|
||||
*/
|
||||
export { default as ModelsDiscoverInfo } from './ModelsDiscoverInfo.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetails** - Model detail view
|
||||
*
|
||||
* Detail pane for the selected model. Loads its own data (details + GGUF file
|
||||
* list) from HuggingFaceService based on the `modelId` route param.
|
||||
*/
|
||||
export { default as ModelsDiscoverDetails } from './ModelsDiscoverDetails.svelte';
|
||||
export { default as ModelsDiscoverModelDetails } from './ModelsDiscoverModelDetails.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsHeader** - Detail view header
|
||||
@@ -61,16 +53,7 @@ export { default as ModelsDiscoverDetails } from './ModelsDiscoverDetails.svelte
|
||||
* Shows the model avatar (base org + quant org corner badge), name, base model
|
||||
* info, stats, metadata chips and capability badges.
|
||||
*/
|
||||
export { default as ModelsDiscoverDetailsHeader } from './ModelsDiscoverDetailsHeader.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsName** - Model name block
|
||||
*
|
||||
* Shows the quant model name with capability icons (vision, tool use,
|
||||
* reasoning) beside it, and the base model name with a smaller external-link
|
||||
* icon on the line below.
|
||||
*/
|
||||
export { default as ModelsDiscoverDetailsName } from './ModelsDiscoverDetailsName.svelte';
|
||||
export { default as ModelsDiscoverModelDetailsHeader } from './ModelsDiscoverModelDetailsHeader.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsDownloadOptions** - GGUF download options
|
||||
@@ -78,7 +61,7 @@ export { default as ModelsDiscoverDetailsName } from './ModelsDiscoverDetailsNam
|
||||
* Groups GGUF files by bit depth and renders per-file download buttons with
|
||||
* progress, owned by the download confirmation dialog.
|
||||
*/
|
||||
export { default as ModelsDiscoverDetailsDownloadOptions } from './ModelsDiscoverDetailsDownloadOptions.svelte';
|
||||
export { default as ModelsDiscoverModelDetailsDownloadOptions } from './ModelsDiscoverModelDetailsDownloadOptions.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverChatTemplateDialog** - Chat template viewer
|
||||
@@ -92,14 +75,14 @@ export { default as ModelsDiscoverChatTemplateDialog } from './ModelsDiscoverCha
|
||||
*
|
||||
* Renders the model card README as markdown.
|
||||
*/
|
||||
export { default as ModelsDiscoverDetailsReadme } from './ModelsDiscoverDetailsReadme.svelte';
|
||||
export { default as ModelsDiscoverModelDetailsReadme } from './ModelsDiscoverModelDetailsReadme.svelte';
|
||||
|
||||
/**
|
||||
* **TerminalCommands** - Terminal command block
|
||||
*
|
||||
* Shows the `llama serve` / `llama cli` commands for a model with copy buttons.
|
||||
*/
|
||||
export { default as TerminalCommands } from './TerminalCommands.svelte';
|
||||
export { default as ModelsDiscoverModelDetailsCommands } from './ModelsDiscoverModelDetailsCommands.svelte';
|
||||
|
||||
/**
|
||||
* **DialogModelDownload** - Download confirmation / progress dialog
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* a model, so `firstModel` drives the initial selection. By default the list
|
||||
* shows a curated set of official ggml-org GGUF models in a fixed display order;
|
||||
* search replaces the list with matching models across all of HuggingFace.
|
||||
* Detail data is loaded by ModelsDiscoverDetails, not here.
|
||||
* Detail data is loaded by ModelsDiscoverModelDetails, not here.
|
||||
*/
|
||||
|
||||
import { HuggingFaceService } from '$lib/services';
|
||||
|
||||
@@ -23,11 +23,8 @@
|
||||
// manager keeps this in a private SvelteSet keyed by `<repo>:<tag>`.
|
||||
const FAILED_TAG = 'ggml-org/gemma-4-12b-it-GGUF:Q4_K_M';
|
||||
|
||||
(
|
||||
modelsStore.status as unknown as { failedDownloads: Set<string> }
|
||||
).failedDownloads = new SvelteSet([FAILED_TAG]);
|
||||
|
||||
|
||||
(modelsStore.status as unknown as { failedDownloads: Set<string> }).failedDownloads =
|
||||
new SvelteSet([FAILED_TAG]);
|
||||
</script>
|
||||
|
||||
<Story name="Progress bar">
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
import { mockGemma, mockListModels, mockQwen } from './fixtures/models-discover';
|
||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||
import ModelsDiscoverAvatar from '$lib/components/app/models/discover/ModelsDiscoverAvatar.svelte';
|
||||
import ModelsDiscoverInfo from '$lib/components/app/models/discover/ModelsDiscoverInfo.svelte';
|
||||
import ModelsDiscoverItem from '$lib/components/app/models/discover/ModelsDiscoverItem.svelte';
|
||||
import ModelsDiscoverList from '$lib/components/app/models/discover/ModelsDiscoverList.svelte';
|
||||
import ModelsDiscoverListItem from '$lib/components/app/models/discover/ModelsDiscoverListItem.svelte';
|
||||
|
||||
const { Story } = defineMeta({
|
||||
tags: ['autodocs'],
|
||||
@@ -30,17 +29,17 @@
|
||||
|
||||
<Story name="Info">
|
||||
<div class="flex w-80 flex-col gap-2 p-4">
|
||||
<ModelsDiscoverInfo model={mockGemma} />
|
||||
<ModelsDiscoverListItem model={mockGemma} />
|
||||
|
||||
<ModelsDiscoverInfo model={mockQwen} />
|
||||
<ModelsDiscoverListItem model={mockQwen} />
|
||||
</div>
|
||||
</Story>
|
||||
|
||||
<Story name="Item">
|
||||
<ul class="w-96 p-2">
|
||||
<ModelsDiscoverItem active model={mockGemma} />
|
||||
<ModelsDiscoverListItem active model={mockGemma} />
|
||||
|
||||
<ModelsDiscoverItem model={mockQwen} />
|
||||
<ModelsDiscoverListItem model={mockQwen} />
|
||||
</ul>
|
||||
</Story>
|
||||
|
||||
|
||||
+17
-35
@@ -2,12 +2,11 @@
|
||||
import { mockDetails, mockSiblings } from './fixtures/models-discover';
|
||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||
import ModelsDiscoverChatTemplateDialog from '$lib/components/app/models/discover/ModelsDiscoverChatTemplateDialog.svelte';
|
||||
import ModelsDiscoverDetails from '$lib/components/app/models/discover/ModelsDiscoverDetails.svelte';
|
||||
import ModelsDiscoverDetailsDownloadOptions from '$lib/components/app/models/discover/ModelsDiscoverDetailsDownloadOptions.svelte';
|
||||
import ModelsDiscoverDetailsHeader from '$lib/components/app/models/discover/ModelsDiscoverDetailsHeader.svelte';
|
||||
import ModelsDiscoverDetailsName from '$lib/components/app/models/discover/ModelsDiscoverDetailsName.svelte';
|
||||
import ModelsDiscoverDetailsReadme from '$lib/components/app/models/discover/ModelsDiscoverDetailsReadme.svelte';
|
||||
import TerminalCommands from '$lib/components/app/models/discover/TerminalCommands.svelte';
|
||||
import ModelsDiscoverModelDetails from '$lib/components/app/models/discover/ModelsDiscoverModelDetails.svelte';
|
||||
import ModelsDiscoverModelDetailsCommands from '$lib/components/app/models/discover/ModelsDiscoverModelDetailsCommands.svelte';
|
||||
import ModelsDiscoverModelDetailsDownloadOptions from '$lib/components/app/models/discover/ModelsDiscoverModelDetailsDownloadOptions.svelte';
|
||||
import ModelsDiscoverModelDetailsHeader from '$lib/components/app/models/discover/ModelsDiscoverModelDetailsHeader.svelte';
|
||||
import ModelsDiscoverModelDetailsReadme from '$lib/components/app/models/discover/ModelsDiscoverModelDetailsReadme.svelte';
|
||||
import { ModelDraftSidecar } from '$lib/enums';
|
||||
import type { HfModelSibling } from '$lib/types';
|
||||
|
||||
@@ -34,7 +33,7 @@
|
||||
|
||||
<Story name="Header">
|
||||
<div class="w-160 p-4">
|
||||
<ModelsDiscoverDetailsHeader
|
||||
<ModelsDiscoverModelDetailsHeader
|
||||
baseModels={mockDetails.cardData?.base_model ? [String(mockDetails.cardData.base_model)] : []}
|
||||
details={mockDetails}
|
||||
hasReasoning
|
||||
@@ -48,29 +47,9 @@
|
||||
</div>
|
||||
</Story>
|
||||
|
||||
<Story name="Name">
|
||||
<div class="space-y-4 p-4">
|
||||
<ModelsDiscoverDetailsName
|
||||
baseModels={['google/gemma-4-12b-it']}
|
||||
hasReasoning
|
||||
hasTools
|
||||
hasVision
|
||||
modelId="ggml-org/gemma-4-12b-it"
|
||||
/>
|
||||
|
||||
<ModelsDiscoverDetailsName
|
||||
baseModels={[]}
|
||||
hasReasoning={false}
|
||||
hasTools={false}
|
||||
hasVision={false}
|
||||
modelId="ggml-org/Qwen3.8-27B"
|
||||
/>
|
||||
</div>
|
||||
</Story>
|
||||
|
||||
<Story name="Download options">
|
||||
<div class="w-200 p-4">
|
||||
<ModelsDiscoverDetailsDownloadOptions
|
||||
<ModelsDiscoverModelDetailsDownloadOptions
|
||||
bitDepthRows={[
|
||||
{ bitDepth: 4, files: files.filter((f) => f.path.includes('Q4_K_M')) },
|
||||
{ bitDepth: 8, files: files.filter((f) => f.path.includes('Q8_0')) },
|
||||
@@ -83,7 +62,7 @@
|
||||
|
||||
<Story name="Download options (unknown device)">
|
||||
<div class="w-200 p-4">
|
||||
<ModelsDiscoverDetailsDownloadOptions
|
||||
<ModelsDiscoverModelDetailsDownloadOptions
|
||||
bitDepthRows={[
|
||||
{ bitDepth: 4, files: files.filter((f) => f.path.includes('Q4_K_M')) },
|
||||
{ bitDepth: 8, files: files.filter((f) => f.path.includes('Q8_0')) }
|
||||
@@ -95,19 +74,22 @@
|
||||
|
||||
<Story name="Terminal commands (no sidecars)">
|
||||
<div class="w-200 p-4">
|
||||
<TerminalCommands modelId="ggml-org/Qwen3.8-27B-GGUF" />
|
||||
<ModelsDiscoverModelDetailsCommands modelId="ggml-org/Qwen3.8-27B-GGUF" />
|
||||
</div>
|
||||
</Story>
|
||||
|
||||
<Story name="Terminal commands (MTP sidecar)">
|
||||
<div class="w-200 p-4">
|
||||
<TerminalCommands modelId="ggml-org/gemma-4-12b-it-GGUF" sidecars={[ModelDraftSidecar.MTP]} />
|
||||
<ModelsDiscoverModelDetailsCommands
|
||||
modelId="ggml-org/gemma-4-12b-it-GGUF"
|
||||
sidecars={[ModelDraftSidecar.MTP]}
|
||||
/>
|
||||
</div>
|
||||
</Story>
|
||||
|
||||
<Story name="Readme">
|
||||
<div class="w-160 p-4">
|
||||
<ModelsDiscoverDetailsReadme {readme} />
|
||||
<ModelsDiscoverModelDetailsReadme {readme} />
|
||||
</div>
|
||||
</Story>
|
||||
|
||||
@@ -119,7 +101,7 @@
|
||||
|
||||
<Story name="Details (loading)">
|
||||
<div class="h-96 w-200 border">
|
||||
<ModelsDiscoverDetails
|
||||
<ModelsDiscoverModelDetails
|
||||
details={null}
|
||||
files={[]}
|
||||
loading
|
||||
@@ -131,7 +113,7 @@
|
||||
|
||||
<Story name="Details (error)">
|
||||
<div class="h-96 w-200 border">
|
||||
<ModelsDiscoverDetails
|
||||
<ModelsDiscoverModelDetails
|
||||
details={null}
|
||||
error="Model not found"
|
||||
files={[]}
|
||||
@@ -143,7 +125,7 @@
|
||||
|
||||
<Story name="Details (loaded)">
|
||||
<div class="h-96 w-200 overflow-y-auto border">
|
||||
<ModelsDiscoverDetails
|
||||
<ModelsDiscoverModelDetails
|
||||
details={mockDetails}
|
||||
{files}
|
||||
modelId={mockDetails.id ?? 'ggml-org/gemma-4-12b-it-GGUF'}
|
||||
Reference in New Issue
Block a user