mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-09-19 01:04:55 +02:00
ui : group discover and selector components into folders
Move the ModelsDiscover components into ModelsDiscoverList/ and ModelsDiscoverDetails/ subfolders (with ModelsDiscoverDetailsDownloadOptions/ nested inside), and the model selector components into a ModelsSelector/ subfolder. Rename ModelsDiscoverModelDetails* to ModelsDiscoverDetails* for consistency, add per-folder index.ts barrels, and keep shared leaves (ModelId, ModelBadge, ModelLoadHighlight, ModelsDiscoverAvatar, DownloadProgressBar) at their folder roots.
This commit is contained in:
+2
-2
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import DownloadProgressBar from './discover/DownloadProgressBar.svelte';
|
||||
import ModelsDiscoverAvatar from './discover/ModelsDiscoverAvatar.svelte';
|
||||
import DownloadProgressBar from '../discover/DownloadProgressBar.svelte';
|
||||
import ModelsDiscoverAvatar from '../discover/ModelsDiscoverAvatar.svelte';
|
||||
import { Loader2, Pause, Play, X } from '@lucide/svelte';
|
||||
import { ModelId } from '$lib/components/app';
|
||||
import DialogConfirmation from '$lib/components/app/dialogs/DialogConfirmation.svelte';
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import ModelLoadHighlight from './ModelLoadHighlight.svelte';
|
||||
import ModelLoadHighlight from '../ModelLoadHighlight.svelte';
|
||||
import { ChevronDown, Lightbulb, Loader2 } from '@lucide/svelte';
|
||||
import {
|
||||
DialogModelInformation,
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import ModelsDiscoverAvatar from './discover/ModelsDiscoverAvatar.svelte';
|
||||
import ModelLoadHighlight from './ModelLoadHighlight.svelte';
|
||||
import ModelsDiscoverAvatar from '../discover/ModelsDiscoverAvatar.svelte';
|
||||
import ModelLoadHighlight from '../ModelLoadHighlight.svelte';
|
||||
import {
|
||||
CircleAlert,
|
||||
Heart,
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import ModelLoadHighlight from './ModelLoadHighlight.svelte';
|
||||
import ModelLoadHighlight from '../ModelLoadHighlight.svelte';
|
||||
import { ChevronDown, Loader2, Package } from '@lucide/svelte';
|
||||
import {
|
||||
DialogModelInformation,
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
*
|
||||
* MODELS SELECTOR
|
||||
*
|
||||
* Model selection UI for the chat form: a desktop dropdown and a mobile sheet,
|
||||
* each backed by a shared grouped options list, option rows, in-flight download
|
||||
* rows and an inline reasoning-effort picker. Supports two server modes:
|
||||
* - **Single model mode**: Server runs with one model, selector shows model info
|
||||
* - **Router mode**: Server runs with multiple models, selector enables switching
|
||||
*
|
||||
* Integrates with modelsStore for model data and serverStore for mode detection.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* **ModelsSelectorDropdown** - Model selection dropdown (desktop)
|
||||
*
|
||||
* Dropdown for selecting AI models with status indicators,
|
||||
* search, and model information display. Adapts UI based on server mode.
|
||||
*
|
||||
* **Architecture:**
|
||||
* - Uses DropdownMenuSearchable for model list
|
||||
* - Integrates with modelsStore for model options and selection
|
||||
* - Detects router vs single mode from serverStore
|
||||
* - Opens DialogModelInformation for model details
|
||||
*
|
||||
* **Features:**
|
||||
* - Searchable model list with keyboard navigation
|
||||
* - Model status indicators (loading/ready/error/updating)
|
||||
* - Model capabilities badges (vision, tools, etc.)
|
||||
* - Current/active model highlighting
|
||||
* - Model information dialog on info button click
|
||||
* - Router mode: shows all available models with status
|
||||
* - Single mode: shows current model name only
|
||||
* - Loading/updating skeleton states
|
||||
* - Global selection support for form integration
|
||||
*
|
||||
* @example
|
||||
* ```svelte
|
||||
* <ModelsSelectorDropdown
|
||||
* currentModel={conversation.modelId}
|
||||
* onModelChange={(id, name) => updateModel(id)}
|
||||
* useGlobalSelection
|
||||
* />
|
||||
* ```
|
||||
*/
|
||||
export { default as ModelsSelectorDropdown } from './ModelsSelectorDropdown.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsSelectorList** - Grouped model options list
|
||||
*
|
||||
* Renders grouped model options (loaded, favorites, available) with section
|
||||
* headers and org subgroups. Shared between ModelsSelectorDropdown and ModelsSelectorSheet
|
||||
* to avoid template duplication.
|
||||
*
|
||||
* Accepts an optional `renderOption` snippet to customize how each option is
|
||||
* rendered (e.g., to add keyboard navigation or highlighting).
|
||||
*/
|
||||
export { default as ModelsSelectorList } from './ModelsSelectorList.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsSelectorDownloadItem** - Single in-flight download row
|
||||
*
|
||||
* One "Download in progress" row for the models selector: live progress bar,
|
||||
* pause / resume on click and a hover-revealed cancel, mirroring the discover
|
||||
* quant chips.
|
||||
*/
|
||||
export { default as ModelsSelectorDownloadItem } from './ModelsSelectorDownloadItem.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsSelectorOption** - Single model option row
|
||||
*
|
||||
* Renders a single model option with selection state, favorite toggle,
|
||||
* load/unload actions, status indicators, and an info button.
|
||||
* Used inside ModelsSelectorList or directly in custom render snippets.
|
||||
*/
|
||||
export { default as ModelsSelectorOption } from './ModelsSelectorOption.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsSelectorReasoningPanel** - Inline reasoning effort picker
|
||||
*
|
||||
* Collapsible row that expands in place to reveal the reasoning effort levels.
|
||||
* Used in the sticky footer of ModelsSelectorDropdown, where a flyout submenu
|
||||
* would float over the model list it belongs to.
|
||||
*/
|
||||
export { default as ModelsSelectorReasoningPanel } from './ModelsSelectorReasoningPanel.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsSelectorSheet** - Mobile model selection sheet
|
||||
*
|
||||
* Bottom sheet variant of ModelsSelectorDropdown optimized for touch interaction
|
||||
* on mobile devices. Same functionality as ModelsSelectorDropdown but uses Sheet UI
|
||||
* instead of DropdownMenu.
|
||||
*/
|
||||
export { default as ModelsSelectorSheet } from './ModelsSelectorSheet.svelte';
|
||||
@@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
ModelsDiscoverDetails,
|
||||
ModelsDiscoverList,
|
||||
ModelsDiscoverListSearch,
|
||||
ModelsDiscoverModelDetails
|
||||
ModelsDiscoverListSearch
|
||||
} from '$lib/components/app/models/discover';
|
||||
import { HuggingFaceService } from '$lib/services';
|
||||
import { modelsHubStore } from '$lib/stores';
|
||||
@@ -119,7 +119,7 @@
|
||||
|
||||
<main class="overflow-y-auto">
|
||||
{#if selectedId}
|
||||
<ModelsDiscoverModelDetails
|
||||
<ModelsDiscoverDetails
|
||||
{details}
|
||||
error={detailError}
|
||||
{files}
|
||||
|
||||
+11
-9
@@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import ModelsDiscoverModelDetailsDownloadOptions from './ModelsDiscoverModelDetailsDownloadOptions.svelte';
|
||||
import ModelsDiscoverModelDetailsHeader from './ModelsDiscoverModelDetailsHeader.svelte';
|
||||
import ModelsDiscoverModelDetailsReadme from './ModelsDiscoverModelDetailsReadme.svelte';
|
||||
import ModelsDiscoverModelDetailsSkeleton from './ModelsDiscoverModelDetailsSkeleton.svelte';
|
||||
import { ModelsDiscoverDetailsDownloadOptions } from './ModelsDiscoverDetailsDownloadOptions';
|
||||
import ModelsDiscoverDetailsHeader from './ModelsDiscoverDetailsHeader.svelte';
|
||||
import ModelsDiscoverDetailsReadme from './ModelsDiscoverDetailsReadme.svelte';
|
||||
import ModelsDiscoverDetailsSkeleton from './ModelsDiscoverDetailsSkeleton.svelte';
|
||||
import { ModelAuxSidecar } from '$lib/enums';
|
||||
import { HuggingFaceService } from '$lib/services';
|
||||
import type { HfModelDetailInfo, HfModelSibling } from '$lib/types/huggingface';
|
||||
@@ -37,7 +37,9 @@
|
||||
// Capabilities derived from HF metadata. Vision comes from an mmproj sidecar
|
||||
// or a multimodal pipeline tag; tool use / reasoning from the chat template.
|
||||
let hasMmproj = $derived(
|
||||
files.some((f) => HuggingFaceService.extractQuantMeta(f.path)?.sidecar === ModelAuxSidecar.MMPROJ)
|
||||
files.some(
|
||||
(f) => HuggingFaceService.extractQuantMeta(f.path)?.sidecar === ModelAuxSidecar.MMPROJ
|
||||
)
|
||||
);
|
||||
let hasVision = $derived(hasMmproj || details?.pipeline_tag === 'image-text-to-text');
|
||||
let hasTools = $derived(detectToolUseSupport(gguf?.chat_template ?? ''));
|
||||
@@ -72,14 +74,14 @@
|
||||
</script>
|
||||
|
||||
{#if loading}
|
||||
<ModelsDiscoverModelDetailsSkeleton />
|
||||
<ModelsDiscoverDetailsSkeleton />
|
||||
{:else if error}
|
||||
<div class="flex h-full items-center justify-center py-20">
|
||||
<p class="text-sm text-destructive">{error}</p>
|
||||
</div>
|
||||
{:else if details}
|
||||
<div class="space-y-6 p-6">
|
||||
<ModelsDiscoverModelDetailsHeader
|
||||
<ModelsDiscoverDetailsHeader
|
||||
{baseModels}
|
||||
{details}
|
||||
{gguf}
|
||||
@@ -90,8 +92,8 @@
|
||||
{modelId}
|
||||
/>
|
||||
|
||||
<ModelsDiscoverModelDetailsDownloadOptions {bitDepthRows} {modelId} />
|
||||
<ModelsDiscoverDetailsDownloadOptions {bitDepthRows} {modelId} />
|
||||
|
||||
<ModelsDiscoverModelDetailsReadme {readme} />
|
||||
<ModelsDiscoverDetailsReadme {readme} />
|
||||
</div>
|
||||
{/if}
|
||||
+4
-8
@@ -7,8 +7,8 @@
|
||||
type QuantOption,
|
||||
type SelectableFile
|
||||
} from './download-options.utils';
|
||||
import ModelsDiscoverModelDetailsDownloadOptionsDownloadCommand from './ModelsDiscoverModelDetailsDownloadOptionsDownloadCommand.svelte';
|
||||
import ModelsDiscoverModelDetailsDownloadOptionsRow from './ModelsDiscoverModelDetailsDownloadOptionsRow.svelte';
|
||||
import ModelsDiscoverDetailsDownloadOptionsDownloadCommand from './ModelsDiscoverDetailsDownloadOptionsDownloadCommand.svelte';
|
||||
import ModelsDiscoverDetailsDownloadOptionsRow from './ModelsDiscoverDetailsDownloadOptionsRow.svelte';
|
||||
import { HuggingFaceService, ModelsService } from '$lib/services';
|
||||
import { modelsStore } from '$lib/stores';
|
||||
|
||||
@@ -120,17 +120,13 @@
|
||||
lifecycle state; nothing here selects anything. -->
|
||||
<div class="flex w-full flex-col divide-y divide-border/50 px-4 pb-1 dark:divide-border/35">
|
||||
{#each rows as row (row.bitDepth)}
|
||||
<ModelsDiscoverModelDetailsDownloadOptionsRow bitDepth={row.bitDepth} files={row.files} />
|
||||
<ModelsDiscoverDetailsDownloadOptionsRow bitDepth={row.bitDepth} files={row.files} />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<!-- Terminal command preview, standalone: its picks are not bound to the chips. -->
|
||||
<div class="border-t border-border/50 px-4 pt-3.5 pb-4 dark:border-border/35">
|
||||
<ModelsDiscoverModelDetailsDownloadOptionsDownloadCommand
|
||||
{draftOptions}
|
||||
{mainOptions}
|
||||
{modelId}
|
||||
/>
|
||||
<ModelsDiscoverDetailsDownloadOptionsDownloadCommand {draftOptions} {mainOptions} {modelId} />
|
||||
</div>
|
||||
</section>
|
||||
{/if}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import DownloadProgressBar from '../../DownloadProgressBar.svelte';
|
||||
import { type DownloadEntryState, labelFor } from './download-options.utils';
|
||||
import DownloadProgressBar from './DownloadProgressBar.svelte';
|
||||
import { Check, Download, Loader2, Pause, Play, RotateCw, X } from '@lucide/svelte';
|
||||
import DialogConfirmation from '$lib/components/app/dialogs/DialogConfirmation.svelte';
|
||||
import * as Tooltip from '$lib/components/ui/tooltip';
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { DownloadEntryState, SelectableFile } from './download-options.utils';
|
||||
import ModelsDiscoverModelDetailsDownloadOptionsQuantDownloadButton from './ModelsDiscoverModelDetailsDownloadOptionsQuantDownloadButton.svelte';
|
||||
import ModelsDiscoverDetailsDownloadOptionsQuantDownloadButton from './ModelsDiscoverDetailsDownloadOptionsQuantDownloadButton.svelte';
|
||||
import { minMemoryTierGb } from '$lib/utils';
|
||||
|
||||
interface Props {
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
<div class="flex flex-wrap justify-end gap-1.5">
|
||||
{#each files as file (file.path)}
|
||||
<ModelsDiscoverModelDetailsDownloadOptionsQuantDownloadButton entry={file.state} {file} />
|
||||
<ModelsDiscoverDetailsDownloadOptionsQuantDownloadButton entry={file.state} {file} />
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
+1
-1
@@ -71,8 +71,8 @@ export function quantBitDepth(quant: string | null): number {
|
||||
|
||||
// LLAMA-APP-REUSE: --spec-type value for each draft sidecar; aux sidecars stay empty
|
||||
export const SPEC_TYPE: Record<ModelSidecar, string> = {
|
||||
[ModelAuxSidecar.MMPROJ]: '',
|
||||
[ModelAuxSidecar.IMATRIX]: '',
|
||||
[ModelAuxSidecar.MMPROJ]: '',
|
||||
[ModelDraftSidecar.DFLASH]: 'draft-dflash',
|
||||
[ModelDraftSidecar.DSPARK]: 'draft-dspark',
|
||||
[ModelDraftSidecar.EAGLE3]: 'eagle3',
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
*
|
||||
* MODELS DISCOVER — DETAILS — DOWNLOAD OPTIONS
|
||||
*
|
||||
* The download area of the detail pane: GGUF files grouped by bit depth, each an
|
||||
* independent download action chip, plus the standalone terminal command preview.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsDownloadOptions** - GGUF download options
|
||||
*
|
||||
* Groups GGUF files by bit depth and renders one independent download
|
||||
* action chip per file, plus the standalone terminal command preview.
|
||||
*/
|
||||
export { default as ModelsDiscoverDetailsDownloadOptions } from './ModelsDiscoverDetailsDownloadOptions.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsDownloadOptionsRow** - One bit-depth group of quants
|
||||
*
|
||||
* A single bit-depth row inside ModelsDiscoverDetailsDownloadOptions: the
|
||||
* depth label with its memory hint and the quant chips of that depth.
|
||||
*/
|
||||
export { default as ModelsDiscoverDetailsDownloadOptionsRow } from './ModelsDiscoverDetailsDownloadOptionsRow.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsDownloadOptionsQuantDownloadButton** - One quant chip
|
||||
*
|
||||
* A single GGUF file as an independent action chip: download / retry when
|
||||
* idle, pause / resume / cancel while in flight, delete when downloaded.
|
||||
*/
|
||||
export { default as ModelsDiscoverDetailsDownloadOptionsQuantDownloadButton } from './ModelsDiscoverDetailsDownloadOptionsQuantDownloadButton.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsDownloadOptionsDownloadCommand** - Terminal command
|
||||
*
|
||||
* The `llama serve -hf ...` command box with inline quant selects and a copy
|
||||
* button; owns its picks, nothing two-way binds them to the quant chips.
|
||||
*/
|
||||
export { default as ModelsDiscoverDetailsDownloadOptionsDownloadCommand } from './ModelsDiscoverDetailsDownloadOptionsDownloadCommand.svelte';
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import ModelsDiscoverAvatar from './ModelsDiscoverAvatar.svelte';
|
||||
import ModelsDiscoverModelDetailsMetadata from './ModelsDiscoverModelDetailsMetadata.svelte';
|
||||
import ModelsDiscoverAvatar from '../ModelsDiscoverAvatar.svelte';
|
||||
import ModelsDiscoverDetailsMetadata from './ModelsDiscoverDetailsMetadata.svelte';
|
||||
import { Download, ExternalLink, Heart, Image, Lightbulb, Wrench } from '@lucide/svelte';
|
||||
import * as Tooltip from '$lib/components/ui/tooltip';
|
||||
import { ICON_CLASS_SM } from '$lib/constants';
|
||||
@@ -137,5 +137,5 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<ModelsDiscoverModelDetailsMetadata {details} {gguf} {licenseTag} {modelId} />
|
||||
<ModelsDiscoverDetailsMetadata {details} {gguf} {licenseTag} {modelId} />
|
||||
</header>
|
||||
+5
-5
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import ModelsDiscoverChatTemplateDialog from './ModelsDiscoverChatTemplateDialog.svelte';
|
||||
import ModelsDiscoverModelDetailsMetadataItem from './ModelsDiscoverModelDetailsMetadataItem.svelte';
|
||||
import ModelsDiscoverDetailsMetadataItem from './ModelsDiscoverDetailsMetadataItem.svelte';
|
||||
import { MessageSquareCode } from '@lucide/svelte';
|
||||
import { modelsHubStore } from '$lib/stores';
|
||||
import type { HfModelDetailInfo, HfModelGguf } from '$lib/types/huggingface';
|
||||
@@ -31,21 +31,21 @@
|
||||
<!-- Metadata chips: label | value pairs, matching the HF model page style -->
|
||||
<div class="flex flex-wrap items-center gap-1.5">
|
||||
{#if gguf?.total}
|
||||
<ModelsDiscoverModelDetailsMetadataItem
|
||||
<ModelsDiscoverDetailsMetadataItem
|
||||
label="Model size"
|
||||
value="{formatParameters(gguf.total)} params"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if gguf?.context_length}
|
||||
<ModelsDiscoverModelDetailsMetadataItem
|
||||
<ModelsDiscoverDetailsMetadataItem
|
||||
label="Context"
|
||||
value={gguf.context_length.toLocaleString()}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if gguf?.architecture}
|
||||
<ModelsDiscoverModelDetailsMetadataItem label="Architecture" value={gguf.architecture} />
|
||||
<ModelsDiscoverDetailsMetadataItem label="Architecture" value={gguf.architecture} />
|
||||
{/if}
|
||||
|
||||
{#if gguf?.chat_template}
|
||||
@@ -60,7 +60,7 @@
|
||||
{/if}
|
||||
|
||||
{#if licenseTag}
|
||||
<ModelsDiscoverModelDetailsMetadataItem label="License" value={licenseTag} />
|
||||
<ModelsDiscoverDetailsMetadataItem label="License" value={licenseTag} />
|
||||
{/if}
|
||||
|
||||
{#if details.gated === true}
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
import { Skeleton } from '$lib/components/ui/skeleton';
|
||||
</script>
|
||||
|
||||
<!-- Static skeleton of ModelsDiscoverModelDetails: header, metadata chips, download options and readme lines. -->
|
||||
<!-- Static skeleton of ModelsDiscoverDetails: header, metadata chips, download options and readme lines. -->
|
||||
<div class="space-y-6 p-6" data-slot="model-details-skeleton">
|
||||
<!-- Header: avatar, name with capability icons, base model line, HF link -->
|
||||
<div class="space-y-3">
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
*
|
||||
* MODELS DISCOVER — DETAILS
|
||||
*
|
||||
* The right-hand detail pane of the hub: header (avatar, name, stats, metadata
|
||||
* chips, capability badges), the download options area and the model-card README.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* **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';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsHeader** - Detail view header
|
||||
*
|
||||
* 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';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsSkeleton** - Detail view loading skeleton
|
||||
*
|
||||
* Static placeholder matching the detail layout: header with avatar and name,
|
||||
* metadata chips, the download options box and readme text lines.
|
||||
*/
|
||||
export { default as ModelsDiscoverDetailsSkeleton } from './ModelsDiscoverDetailsSkeleton.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsReadme** - Detail view README
|
||||
*
|
||||
* Renders the model card README as markdown.
|
||||
*/
|
||||
export { default as ModelsDiscoverDetailsReadme } from './ModelsDiscoverDetailsReadme.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsMetadata** - Detail view metadata row
|
||||
*
|
||||
* The detail view's metadata chips (model size, context, architecture, license,
|
||||
* chat template).
|
||||
*/
|
||||
export { default as ModelsDiscoverDetailsMetadata } from './ModelsDiscoverDetailsMetadata.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsMetadataItem** - Single metadata chip
|
||||
*
|
||||
* One label | value chip of the detail view's metadata row (model size,
|
||||
* context, architecture, license).
|
||||
*/
|
||||
export { default as ModelsDiscoverDetailsMetadataItem } from './ModelsDiscoverDetailsMetadataItem.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverChatTemplateDialog** - Chat template viewer
|
||||
*
|
||||
* Shows the model's chat template in a scrollable dialog with a copy button.
|
||||
*/
|
||||
export { default as ModelsDiscoverChatTemplateDialog } from './ModelsDiscoverChatTemplateDialog.svelte';
|
||||
|
||||
export * from './ModelsDiscoverDetailsDownloadOptions';
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import ModelId from '../ModelId.svelte';
|
||||
import ModelsDiscoverAvatar from './ModelsDiscoverAvatar.svelte';
|
||||
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';
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
*
|
||||
* MODELS DISCOVER — LIST
|
||||
*
|
||||
* The hub's sidebar column: a debounced search field above a navigable list of
|
||||
* HuggingFace GGUF models, with skeleton rows while loading.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverList** - Sidebar model list
|
||||
*
|
||||
* Renders the hub's model list as a navigable column. Each row links to the
|
||||
* model's detail route and highlights the active one.
|
||||
*/
|
||||
export { default as ModelsDiscoverList } from './ModelsDiscoverList.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverListSearch** - Sidebar search input
|
||||
*
|
||||
* Debounced search field for the model list.
|
||||
*/
|
||||
export { default as ModelsDiscoverListSearch } from './ModelsDiscoverListSearch.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverListItem** - Single sidebar row
|
||||
*
|
||||
* One model entry in the sidebar list. Links to `/models-hub/[org]/[model]`.
|
||||
*/
|
||||
export { default as ModelsDiscoverListItem } from './ModelsDiscoverListItem.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverListItemSkeleton** - Skeleton sidebar row
|
||||
*
|
||||
* Pulsing placeholder matching a ModelsDiscoverListItem row, shown while the
|
||||
* list is loading.
|
||||
*/
|
||||
export { default as ModelsDiscoverListItemSkeleton } from './ModelsDiscoverListItemSkeleton.svelte';
|
||||
@@ -1,9 +1,11 @@
|
||||
/**
|
||||
*
|
||||
* MODELS HUB
|
||||
* MODELS DISCOVER
|
||||
*
|
||||
* Components for the Models Hub route (`/models-hub`): a sidebar list of
|
||||
* HuggingFace GGUF models and a detail view for the selected model.
|
||||
* Components for the Models Discover hub: a sidebar search + list of
|
||||
* HuggingFace GGUF models and a detail view for the selected model, used as the
|
||||
* body of the discovery dialog. The list and detail trees live in their own
|
||||
* subfolders; this barrel re-exports them alongside the shared leaves.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -16,125 +18,22 @@
|
||||
*/
|
||||
export { default as ModelsDiscover } from './ModelsDiscover.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverList** - Sidebar model list
|
||||
*
|
||||
* Renders the hub's model list as a navigable column. Each row links to the
|
||||
* model's detail route and highlights the active one.
|
||||
*/
|
||||
export { default as ModelsDiscoverList } from './ModelsDiscoverList.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverListSearch** - Sidebar search input
|
||||
*
|
||||
* Debounced search field for the model list.
|
||||
*/
|
||||
export { default as ModelsDiscoverListSearch } from './ModelsDiscoverListSearch.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverItem** - Single sidebar row
|
||||
*
|
||||
* One model entry in the sidebar list. Links to `/models-hub/[org]/[model]`.
|
||||
*/
|
||||
export { default as ModelsDiscoverListItem } from './ModelsDiscoverListItem.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverListItemSkeleton** - Skeleton sidebar row
|
||||
*
|
||||
* Pulsing placeholder matching a ModelsDiscoverListItem row, shown while the
|
||||
* list is loading.
|
||||
*/
|
||||
export { default as ModelsDiscoverListItemSkeleton } from './ModelsDiscoverListItemSkeleton.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverAvatar** - Org avatar for a model row
|
||||
*
|
||||
* Shows the org's avatar image, falling back to a monogram on a stable hue
|
||||
* derived from the org name when the image fails to load.
|
||||
* derived from the org name when the image fails to load. Shared by the list,
|
||||
* the detail header and the model selector rows.
|
||||
*/
|
||||
export { default as ModelsDiscoverAvatar } from './ModelsDiscoverAvatar.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 ModelsDiscoverModelDetails } from './ModelsDiscoverModelDetails.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsHeader** - Detail view header
|
||||
*
|
||||
* Shows the model avatar (base org + quant org corner badge), name, base model
|
||||
* info, stats, metadata chips and capability badges.
|
||||
*/
|
||||
export { default as ModelsDiscoverModelDetailsHeader } from './ModelsDiscoverModelDetailsHeader.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsDownloadOptions** - GGUF download options
|
||||
*
|
||||
* Groups GGUF files by bit depth and renders one independent download
|
||||
* action chip per file, plus the standalone terminal command preview.
|
||||
*/
|
||||
export { default as ModelsDiscoverModelDetailsDownloadOptions } from './ModelsDiscoverModelDetailsDownloadOptions.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsDownloadOptionsRow** - One bit-depth group of quants
|
||||
*
|
||||
* A single bit-depth row inside ModelsDiscoverModelDetailsDownloadOptions: the
|
||||
* depth label with its memory hint and the quant chips of that depth.
|
||||
*/
|
||||
export { default as ModelsDiscoverModelDetailsDownloadOptionsRow } from './ModelsDiscoverModelDetailsDownloadOptionsRow.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsDownloadOptionsQuantDownloadButton** - One quant chip
|
||||
*
|
||||
* A single GGUF file as an independent action chip: download / retry when
|
||||
* idle, pause / resume / cancel while in flight, delete when downloaded.
|
||||
*/
|
||||
export { default as ModelsDiscoverModelDetailsDownloadOptionsQuantDownloadButton } from './ModelsDiscoverModelDetailsDownloadOptionsQuantDownloadButton.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsDownloadOptionsDownloadCommand** - Terminal command
|
||||
*
|
||||
* The `llama serve -hf ...` command box with inline quant selects and a copy
|
||||
* button; owns its picks, nothing two-way binds them to the quant chips.
|
||||
*/
|
||||
export { default as ModelsDiscoverModelDetailsDownloadOptionsDownloadCommand } from './ModelsDiscoverModelDetailsDownloadOptionsDownloadCommand.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsSkeleton** - Detail view loading skeleton
|
||||
*
|
||||
* Static placeholder matching the detail layout: header with avatar and name,
|
||||
* metadata chips, the download options box and readme text lines.
|
||||
*/
|
||||
export { default as ModelsDiscoverModelDetailsSkeleton } from './ModelsDiscoverModelDetailsSkeleton.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsMetadataItem** - Single metadata chip
|
||||
*
|
||||
* One label | value chip of the detail view's metadata row (model size,
|
||||
* context, architecture, license).
|
||||
*/
|
||||
export { default as ModelsDiscoverModelDetailsMetadataItem } from './ModelsDiscoverModelDetailsMetadataItem.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverChatTemplateDialog** - Chat template viewer
|
||||
*
|
||||
* Shows the model's chat template in a scrollable dialog with a copy button.
|
||||
*/
|
||||
export { default as ModelsDiscoverChatTemplateDialog } from './ModelsDiscoverChatTemplateDialog.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsDiscoverDetailsReadme** - Detail view README
|
||||
*
|
||||
* Renders the model card README as markdown.
|
||||
*/
|
||||
export { default as ModelsDiscoverModelDetailsReadme } from './ModelsDiscoverModelDetailsReadme.svelte';
|
||||
|
||||
/**
|
||||
* **DownloadProgressBar** - Thin download progress bar
|
||||
*
|
||||
* Normalizes bytes to a 0..100% bar; can pin to the bottom edge as an overlay.
|
||||
* Shared by the quant chips and the model selector's download rows.
|
||||
*/
|
||||
export { default as DownloadProgressBar } from './DownloadProgressBar.svelte';
|
||||
|
||||
export * from './ModelsDiscoverList';
|
||||
export * from './ModelsDiscoverDetails';
|
||||
|
||||
@@ -8,90 +8,11 @@
|
||||
*
|
||||
* Integrates with modelsStore for model data and serverStore for mode detection.
|
||||
*
|
||||
* The selection UI lives in the ModelsSelector subfolder; the shared model
|
||||
* display primitives (id / badge rendering) stay here.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* **ModelsSelectorDropdown** - Model selection dropdown (desktop)
|
||||
*
|
||||
* Dropdown for selecting AI models with status indicators,
|
||||
* search, and model information display. Adapts UI based on server mode.
|
||||
*
|
||||
* **Architecture:**
|
||||
* - Uses DropdownMenuSearchable for model list
|
||||
* - Integrates with modelsStore for model options and selection
|
||||
* - Detects router vs single mode from serverStore
|
||||
* - Opens DialogModelInformation for model details
|
||||
*
|
||||
* **Features:**
|
||||
* - Searchable model list with keyboard navigation
|
||||
* - Model status indicators (loading/ready/error/updating)
|
||||
* - Model capabilities badges (vision, tools, etc.)
|
||||
* - Current/active model highlighting
|
||||
* - Model information dialog on info button click
|
||||
* - Router mode: shows all available models with status
|
||||
* - Single mode: shows current model name only
|
||||
* - Loading/updating skeleton states
|
||||
* - Global selection support for form integration
|
||||
*
|
||||
* @example
|
||||
* ```svelte
|
||||
* <ModelsSelectorDropdown
|
||||
* currentModel={conversation.modelId}
|
||||
* onModelChange={(id, name) => updateModel(id)}
|
||||
* useGlobalSelection
|
||||
* />
|
||||
* ```
|
||||
*/
|
||||
export { default as ModelsSelectorDropdown } from './ModelsSelectorDropdown.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsSelectorList** - Grouped model options list
|
||||
*
|
||||
* Renders grouped model options (loaded, favorites, available) with section
|
||||
* headers and org subgroups. Shared between ModelsSelectorDropdown and ModelsSelectorSheet
|
||||
* to avoid template duplication.
|
||||
*
|
||||
* Accepts an optional `renderOption` snippet to customize how each option is
|
||||
* rendered (e.g., to add keyboard navigation or highlighting).
|
||||
*/
|
||||
export { default as ModelsSelectorList } from './ModelsSelectorList.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsSelectorDownloadItem** - Single in-flight download row
|
||||
*
|
||||
* One "Download in progress" row for the models selector: live progress bar,
|
||||
* pause / resume on click and a hover-revealed cancel, mirroring the discover
|
||||
* quant chips.
|
||||
*/
|
||||
export { default as ModelsSelectorDownloadItem } from './ModelsSelectorDownloadItem.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsSelectorOption** - Single model option row
|
||||
*
|
||||
* Renders a single model option with selection state, favorite toggle,
|
||||
* load/unload actions, status indicators, and an info button.
|
||||
* Used inside ModelsSelectorList or directly in custom render snippets.
|
||||
*/
|
||||
export { default as ModelsSelectorOption } from './ModelsSelectorOption.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsSelectorReasoningPanel** - Inline reasoning effort picker
|
||||
*
|
||||
* Collapsible row that expands in place to reveal the reasoning effort levels.
|
||||
* Used in the sticky footer of ModelsSelectorDropdown, where a flyout submenu
|
||||
* would float over the model list it belongs to.
|
||||
*/
|
||||
export { default as ModelsSelectorReasoningPanel } from './ModelsSelectorReasoningPanel.svelte';
|
||||
|
||||
/**
|
||||
* **ModelsSelectorSheet** - Mobile model selection sheet
|
||||
*
|
||||
* Bottom sheet variant of ModelsSelectorDropdown optimized for touch interaction
|
||||
* on mobile devices. Same functionality as ModelsSelectorDropdown but uses Sheet UI
|
||||
* instead of DropdownMenu.
|
||||
*/
|
||||
export { default as ModelsSelectorSheet } from './ModelsSelectorSheet.svelte';
|
||||
|
||||
/** * **ModelBadge** - Model name display badge
|
||||
*
|
||||
* Compact badge showing current model name with package icon.
|
||||
@@ -127,3 +48,5 @@ export { default as ModelBadge } from './ModelBadge.svelte';
|
||||
* Respects the user's `showRawModelNames` setting.
|
||||
*/
|
||||
export { default as ModelId } from './ModelId.svelte';
|
||||
|
||||
export * from './ModelsSelector';
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* with matching models across all of HuggingFace. Both paths fetch the same
|
||||
* fields (chat template, context length, repo files), so a row renders the same
|
||||
* badges and sizes whether it came from the catalog or from a query.
|
||||
* Detail data is loaded by ModelsDiscoverModelDetails, not here.
|
||||
* Detail data is loaded by ModelsDiscoverDetails, not here.
|
||||
*/
|
||||
|
||||
import { isAuxSidecar } from '$lib/constants';
|
||||
|
||||
+13
-13
@@ -1,11 +1,11 @@
|
||||
<script lang="ts" module>
|
||||
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 ModelsDiscoverModelDetails from '$lib/components/app/models/discover/ModelsDiscoverModelDetails.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 ModelsDiscoverChatTemplateDialog from '$lib/components/app/models/discover/ModelsDiscoverDetails/ModelsDiscoverChatTemplateDialog.svelte';
|
||||
import ModelsDiscoverDetails from '$lib/components/app/models/discover/ModelsDiscoverDetails/ModelsDiscoverDetails.svelte';
|
||||
import ModelsDiscoverDetailsDownloadOptions from '$lib/components/app/models/discover/ModelsDiscoverDetails/ModelsDiscoverDetailsDownloadOptions/ModelsDiscoverDetailsDownloadOptions.svelte';
|
||||
import ModelsDiscoverDetailsHeader from '$lib/components/app/models/discover/ModelsDiscoverDetails/ModelsDiscoverDetailsHeader.svelte';
|
||||
import ModelsDiscoverDetailsReadme from '$lib/components/app/models/discover/ModelsDiscoverDetails/ModelsDiscoverDetailsReadme.svelte';
|
||||
import type { HfModelSibling } from '$lib/types';
|
||||
|
||||
const { Story } = defineMeta({
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
<Story name="Header">
|
||||
<div class="w-160 p-4">
|
||||
<ModelsDiscoverModelDetailsHeader
|
||||
<ModelsDiscoverDetailsHeader
|
||||
baseModels={mockDetails.cardData?.base_model ? [String(mockDetails.cardData.base_model)] : []}
|
||||
details={mockDetails}
|
||||
hasReasoning
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
<Story name="Download options">
|
||||
<div class="w-200 p-4">
|
||||
<ModelsDiscoverModelDetailsDownloadOptions
|
||||
<ModelsDiscoverDetailsDownloadOptions
|
||||
bitDepthRows={[
|
||||
{ bitDepth: 4, files: files.filter((f) => f.path.includes('Q4_K_M')) },
|
||||
{ bitDepth: 8, files: files.filter((f) => f.path.includes('Q8_0')) },
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
<Story name="Download options (unknown device)">
|
||||
<div class="w-200 p-4">
|
||||
<ModelsDiscoverModelDetailsDownloadOptions
|
||||
<ModelsDiscoverDetailsDownloadOptions
|
||||
bitDepthRows={[
|
||||
{ bitDepth: 4, files: files.filter((f) => f.path.includes('Q4_K_M')) },
|
||||
{ bitDepth: 8, files: files.filter((f) => f.path.includes('Q8_0')) }
|
||||
@@ -74,7 +74,7 @@
|
||||
paused, downloaded and the failed retry badge. -->
|
||||
<Story name="Download options (download states)">
|
||||
<div class="w-200 p-4">
|
||||
<ModelsDiscoverModelDetailsDownloadOptions
|
||||
<ModelsDiscoverDetailsDownloadOptions
|
||||
bitDepthRows={[
|
||||
{ bitDepth: 4, files: files.filter((f) => f.path.includes('Q4_K_M')) },
|
||||
{ bitDepth: 8, files: files.filter((f) => f.path.includes('Q8_0')) },
|
||||
@@ -99,7 +99,7 @@
|
||||
|
||||
<Story name="Readme">
|
||||
<div class="w-160 p-4">
|
||||
<ModelsDiscoverModelDetailsReadme {readme} />
|
||||
<ModelsDiscoverDetailsReadme {readme} />
|
||||
</div>
|
||||
</Story>
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
|
||||
<Story name="Details (loading)">
|
||||
<div class="h-96 w-200 border">
|
||||
<ModelsDiscoverModelDetails
|
||||
<ModelsDiscoverDetails
|
||||
details={null}
|
||||
files={[]}
|
||||
loading
|
||||
@@ -123,7 +123,7 @@
|
||||
|
||||
<Story name="Details (error)">
|
||||
<div class="h-96 w-200 border">
|
||||
<ModelsDiscoverModelDetails
|
||||
<ModelsDiscoverDetails
|
||||
details={null}
|
||||
error="Model not found"
|
||||
files={[]}
|
||||
@@ -135,7 +135,7 @@
|
||||
|
||||
<Story name="Details (loaded)">
|
||||
<div class="h-96 w-200 overflow-y-auto border">
|
||||
<ModelsDiscoverModelDetails
|
||||
<ModelsDiscoverDetails
|
||||
details={mockDetails}
|
||||
{files}
|
||||
modelId={mockDetails.id ?? 'ggml-org/gemma-4-12b-it-GGUF'}
|
||||
@@ -2,8 +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 ModelsDiscoverList from '$lib/components/app/models/discover/ModelsDiscoverList.svelte';
|
||||
import ModelsDiscoverListItem from '$lib/components/app/models/discover/ModelsDiscoverListItem.svelte';
|
||||
import ModelsDiscoverList from '$lib/components/app/models/discover/ModelsDiscoverList/ModelsDiscoverList.svelte';
|
||||
import ModelsDiscoverListItem from '$lib/components/app/models/discover/ModelsDiscoverList/ModelsDiscoverListItem.svelte';
|
||||
|
||||
const { Story } = defineMeta({
|
||||
tags: ['autodocs'],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts" module>
|
||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||
import ModelsSelectorList from '$lib/components/app/models/ModelsSelectorList.svelte';
|
||||
import ModelsSelectorOption from '$lib/components/app/models/ModelsSelectorOption.svelte';
|
||||
import ModelsSelectorList from '$lib/components/app/models/ModelsSelector/ModelsSelectorList.svelte';
|
||||
import ModelsSelectorOption from '$lib/components/app/models/ModelsSelector/ModelsSelectorOption.svelte';
|
||||
import type { GroupedModelOptions, ModelItem } from '$lib/components/app/navigation/utils';
|
||||
import { ServerModelStatus } from '$lib/enums';
|
||||
import { modelsStore } from '$lib/stores/models/index.svelte';
|
||||
|
||||
Reference in New Issue
Block a user