feat: add vendor filter dropdown and sorted model listing to chat UI

- Add vendor selector dropdown to filter available models
- Introduce `selectedVendor` writable store for vendor selection
- Add `vendorNames` derived store with sorted unique vendor names
- Add `filteredModels` derived store filtered by selected vendor
- Fix model deduplication to use `vendor:name` composite key
- Sort models by vendor then name, case-insensitive
- Display vendor prefix in model option labels
This commit is contained in:
Kayvan Sylvan 2026-02-25 22:14:03 -08:00
parent cb11e97ea8
commit e6d9490dc9
2 changed files with 35 additions and 5 deletions

View file

@ -1,20 +1,29 @@
<script lang="ts">
import { onMount } from 'svelte';
import { Select } from "$lib/components/ui/select";
import { modelConfig, availableModels, loadAvailableModels } from "$lib/store/model-store";
import { modelConfig, loadAvailableModels, selectedVendor, vendorNames, filteredModels } from "$lib/store/model-store";
onMount(async () => {
await loadAvailableModels();
});
</script>
<div class="min-w-0">
<div class="min-w-0 flex flex-col gap-2">
<Select
bind:value={$selectedVendor}
class="bg-primary-800/30 border-none hover:bg-primary-800/40 transition-colors"
>
<option value="">All Vendors</option>
{#each $vendorNames as vendor (vendor)}
<option value={vendor}>{vendor}</option>
{/each}
</Select>
<Select
bind:value={$modelConfig.model}
class="bg-primary-800/30 border-none hover:bg-primary-800/40 transition-colors"
>
<option value="">Default Model</option>
{#each $availableModels as model (model.name)}
{#each $filteredModels as model (`${model.vendor}:${model.name}`)}
<option value={model.name}>{model.vendor} - {model.name}</option>
{/each}
</Select>

View file

@ -1,4 +1,4 @@
import { writable } from 'svelte/store';
import { derived, writable } from 'svelte/store';
import { modelsApi } from '$lib/api/models';
import { configApi } from '$lib/api/config';
import type { VendorModel, ModelConfig } from '$lib/interfaces/model-interface';
@ -13,13 +13,34 @@ export const modelConfig = writable<ModelConfig>({
});
export const availableModels = writable<VendorModel[]>([]);
export const selectedVendor = writable<string>('');
// Sorted unique vendor names
export const vendorNames = derived(availableModels, ($models) =>
[...new Set($models.map(m => m.vendor))].sort((a, b) =>
a.toLowerCase().localeCompare(b.toLowerCase())
)
);
// Models filtered by selected vendor
export const filteredModels = derived(
[availableModels, selectedVendor],
([$models, $vendor]) =>
$vendor ? $models.filter(m => m.vendor === $vendor) : $models
);
// Initialize available models
export async function loadAvailableModels() {
try {
const models = await modelsApi.getAvailable();
console.log('Load models:', models);
const uniqueModels = [...new Map(models.map(model => [model.name, model])).values()];
const uniqueModels = [...new Map(models.map(model => [`${model.vendor}:${model.name}`, model])).values()];
// Sort like CLI: vendor name (case-insensitive), then model name (case-insensitive)
uniqueModels.sort((a, b) => {
const vendorCmp = a.vendor.toLowerCase().localeCompare(b.vendor.toLowerCase());
if (vendorCmp !== 0) return vendorCmp;
return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
});
availableModels.set(uniqueModels);
} catch (error) {
console.error('Client failed to load available models:', error);