This commit is contained in:
Aidan Bleser 2025-06-18 08:53:56 -05:00
parent 58b0031bd4
commit 7161858a0d

View file

@ -32,23 +32,6 @@
import MicrosoftIcon from '~icons/simple-icons/microsoft'; import MicrosoftIcon from '~icons/simple-icons/microsoft';
import OpenaiIcon from '~icons/simple-icons/openai'; import OpenaiIcon from '~icons/simple-icons/openai';
import XIcon from '~icons/simple-icons/x'; import XIcon from '~icons/simple-icons/x';
import BrainIcon from '~icons/lucide/brain';
import CpuIcon from '~icons/lucide/cpu';
import ZapIcon from '~icons/lucide/zap';
import Cohere from '$lib/components/icons/cohere.svelte';
import Deepseek from '$lib/components/icons/deepseek.svelte';
import { Popover } from 'melt/builders';
import type { Component } from 'svelte';
import LogosClaudeIcon from '~icons/logos/claude-icon';
import LogosMistralAiIcon from '~icons/logos/mistral-ai-icon';
import MaterialIconThemeGeminiAi from '~icons/material-icon-theme/gemini-ai';
import { capitalize } from '$lib/utils/strings';
import { supportsImages } from '$lib/utils/model-capabilities';
import { models as modelsState } from '$lib/state/models.svelte';
import { Provider } from '$lib/types';
import Tooltip from '$lib/components/ui/tooltip.svelte';
import fuzzysearch from '$lib/utils/fuzzy-search';
import { IsMobile } from '$lib/hooks/is-mobile.svelte';
type Props = { type Props = {
class?: string; class?: string;
@ -139,12 +122,10 @@
return 'other'; return 'other';
} }
let search = $state('');
const filteredModels = $derived( const filteredModels = $derived(
fuzzysearch({ fuzzysearch({
haystack: enabledArr, haystack: enabledArr,
needle: search, needle: gridCommand.inputValue,
property: 'model_id', property: 'model_id',
}) })
); );
@ -257,11 +238,7 @@
{...popover.content} {...popover.content}
class="border-border bg-popover mt-1 max-h-200 min-w-80 flex-col overflow-hidden rounded-xl border p-0 backdrop-blur-sm data-[open]:flex" class="border-border bg-popover mt-1 max-h-200 min-w-80 flex-col overflow-hidden rounded-xl border p-0 backdrop-blur-sm data-[open]:flex"
> >
<Command.Root <div class="flex h-full flex-col overflow-hidden md:w-[572px]" {...gridCommand.root}>
shouldFilter={false}
class="flex h-full flex-col overflow-hidden md:w-[572px]"
columns={isMobile.current ? undefined : 4}
>
<label <label
class="group/label border-border relative flex items-center gap-2 border-b px-4 py-3 text-sm" class="group/label border-border relative flex items-center gap-2 border-b px-4 py-3 text-sm"
> >
@ -269,7 +246,6 @@
<input <input
class="w-full outline-none" class="w-full outline-none"
placeholder="Search models..." placeholder="Search models..."
bind:value={search}
{@attach (node) => { {@attach (node) => {
if (popover.open) { if (popover.open) {
node.focus(); node.focus();
@ -288,107 +264,95 @@
})} })}
/> />
</label> </label>
<Command.List class="h-[300px] overflow-y-auto md:h-[430px]"> <div class="h-[300px] overflow-y-auto md:h-[430px]">
<Command.Viewport> {#each groupedModels as [company, models] (company)}
<Command.Empty <div {...gridCommand.group} class="space-y-2">
class="text-muted-foreground flex items-center justify-center p-4 text-sm md:h-[120px]" <p
> class="text-heading/75 flex scroll-m-2 items-center gap-2 px-3 pt-3 pb-1 text-xs font-semibold tracking-wide capitalize"
No models available. Enable some models in the account settings. {...gridCommand.groupHeading}
</Command.Empty> >
{#each groupedModels as [company, models] (company)} {company}
<Command.Group class="space-y-2"> </p>
<Command.GroupHeading <div class="flex flex-col gap-2 px-3 pb-3 md:grid md:grid-cols-4 md:gap-3">
class="text-heading/75 flex items-center gap-2 px-3 pt-3 pb-1 text-xs font-semibold tracking-wide capitalize md:scroll-m-[180px]" {#each models as model (model._id)}
> {@const isSelected = settings.modelId === model.model_id}
{company} {@const formatted = formatModelName(model.model_id)}
</Command.GroupHeading> {@const openRouterModel = modelsState
<Command.GroupItems .from(Provider.OpenRouter)
class="flex flex-col gap-2 px-3 pb-3 md:grid md:grid-cols-4 md:gap-3" .find((m) => m.id === model.model_id)}
>
{#each models as model (model._id)}
{@const isSelected = settings.modelId === model.model_id}
{@const formatted = formatModelName(model.model_id)}
{#if isMobile.current}
<Command.Item
value={model.model_id}
onSelect={() => selectModel(model.model_id)}
class={cn(
'border-border flex h-10 items-center justify-between rounded-lg border p-2',
'relative scroll-m-2 select-none',
'data-selected:bg-accent/50 data-selected:text-accent-foreground',
isSelected && 'border-reflect border-none'
)}
>
<div class="flex items-center gap-2">
{#if getModelIcon(model.model_id)}
{@const ModelIcon = getModelIcon(model.model_id)}
<ModelIcon class="size-6 shrink-0" />
{/if}
<p class="font-fake-proxima text-center leading-tight font-bold">
{formatted.full}
</p>
</div>
{@const openRouterModel = modelsState {#if isMobile.current}
.from(Provider.OpenRouter) <div
.find((m) => m.id === model.model_id)} {...gridCommand.getItem(model.model_id)}
{#if openRouterModel && supportsImages(openRouterModel)} class={cn(
<Tooltip> 'border-border flex h-10 items-center justify-between rounded-lg border p-2',
{#snippet trigger(tooltip)} 'relative scroll-m-2 select-none',
<div class="" {...tooltip.trigger}> 'data-highlighted:bg-accent/50 data-highlighted:text-accent-foreground',
<EyeIcon class="size-3" /> isSelected && 'border-reflect border-none'
</div> )}
{/snippet} >
Supports image anaylsis <div class="flex items-center gap-2">
</Tooltip>
{/if}
</Command.Item>
{:else}
<Command.Item
value={model.model_id}
onSelect={() => selectModel(model.model_id)}
class={cn(
'border-border flex h-40 w-32 flex-col items-center justify-center rounded-lg border p-2',
'relative select-none',
'data-selected:bg-accent/50 data-selected:text-accent-foreground',
isSelected && 'border-reflect border-none'
)}
>
{#if getModelIcon(model.model_id)} {#if getModelIcon(model.model_id)}
{@const ModelIcon = getModelIcon(model.model_id)} {@const ModelIcon = getModelIcon(model.model_id)}
<ModelIcon class="size-6 shrink-0" /> <ModelIcon class="size-6 shrink-0" />
{/if} {/if}
<p class="font-fake-proxima mt-2 text-center leading-tight font-bold"> <p class="font-fake-proxima text-center leading-tight font-bold">
{formatted.primary} {formatted.full}
</p>
<p class="mt-0 text-center text-xs leading-tight font-medium">
{formatted.secondary}
</p> </p>
</div>
{@const openRouterModel = modelsState {#if openRouterModel && supportsImages(openRouterModel)}
.from(Provider.OpenRouter) <Tooltip>
.find((m) => m.id === model.model_id)} {#snippet trigger(tooltip)}
{#if openRouterModel && supportsImages(openRouterModel)} <div class="" {...tooltip.trigger}>
<Tooltip> <EyeIcon class="size-3" />
{#snippet trigger(tooltip)} </div>
<div {/snippet}
class="abs-x-center text-muted-foreground absolute bottom-3 flex items-center gap-1 text-xs" Supports image anaylsis
{...tooltip.trigger} </Tooltip>
> {/if}
<EyeIcon class="size-3" /> </div>
</div> {:else}
{/snippet} <div
Supports image anaylsis {...gridCommand.getItem(model.model_id)}
</Tooltip> class={cn(
{/if} 'border-border flex h-40 w-32 scroll-m-2 flex-col items-center justify-center rounded-lg border p-2',
</Command.Item> 'relative select-none',
{/if} 'data-highlighted:bg-accent/50 data-highlighted:text-accent-foreground',
{/each} isSelected && 'border-reflect border-none'
</Command.GroupItems> )}
</Command.Group> >
{/each} {#if getModelIcon(model.model_id)}
</Command.Viewport> {@const ModelIcon = getModelIcon(model.model_id)}
</Command.List> <ModelIcon class="size-6 shrink-0" />
</Command.Root> {/if}
<p class="font-fake-proxima mt-2 text-center leading-tight font-bold">
{formatted.primary}
</p>
<p class="mt-0 text-center text-xs leading-tight font-medium">
{formatted.secondary}
</p>
{#if openRouterModel && supportsImages(openRouterModel)}
<Tooltip>
{#snippet trigger(tooltip)}
<div
class="abs-x-center text-muted-foreground absolute bottom-3 flex items-center gap-1 text-xs"
{...tooltip.trigger}
>
<EyeIcon class="size-3" />
</div>
{/snippet}
Supports image anaylsis
</Tooltip>
{/if}
</div>
{/if}
{/each}
</div>
</div>
{/each}
</div>
</div>
</div> </div>
{/if} {/if}