import { useState } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { ArrowDown, ArrowUp } from 'lucide-react' import { apiFetch } from '@/lib/api' import { Button } from '@/components/ui/button' import { Switch } from '@/components/ui/switch' import { PageHeader } from '@/components/page-header' import { FloatingBar } from '@/components/floating-bar' import { ModelsTabs } from '@/components/models-tabs' interface ProviderEntry { id: number platform: string modelId: string displayName: string priority: number enabled: boolean quotaLabel: string keyCount: number } interface Family { family: string dimensions: number maxInputTokens: number | null isDefault: boolean providers: ProviderEntry[] } interface EmbeddingsData { defaultFamily: string families: Family[] } interface UsageData { families: { family: string; requestsToday: number; tokensMonth: number }[] } function formatTokens(n: number): string { if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M` if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K` return String(n) } export default function EmbeddingsPage() { const queryClient = useQueryClient() // Local unsaved edits, same pattern as the chat fallback page. const [localFamilies, setLocalFamilies] = useState(null) const [localDefault, setLocalDefault] = useState(null) const { data, isLoading } = useQuery({ queryKey: ['embeddings'], queryFn: () => apiFetch('/api/embeddings'), }) const { data: usage } = useQuery({ queryKey: ['embeddings', 'usage'], queryFn: () => apiFetch('/api/embeddings/usage'), refetchInterval: 30_000, }) const usageByFamily = new Map((usage?.families ?? []).map(u => [u.family, u])) const saveMutation = useMutation({ mutationFn: (body: { defaultFamily?: string; providers?: { id: number; priority: number; enabled: boolean }[] }) => apiFetch('/api/embeddings', { method: 'PUT', body: JSON.stringify(body) }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['embeddings'] }) setLocalFamilies(null) setLocalDefault(null) }, }) const families = localFamilies ?? data?.families ?? [] const defaultFamily = localDefault ?? data?.defaultFamily ?? '' const hasChanges = localFamilies !== null || localDefault !== null function updateProvider(familyName: string, id: number, patch: Partial) { setLocalFamilies(families.map(f => f.family === familyName ? { ...f, providers: f.providers.map(p => (p.id === id ? { ...p, ...patch } : p)) } : f, )) } function moveProvider(familyName: string, index: number, dir: -1 | 1) { setLocalFamilies(families.map(f => { if (f.family !== familyName) return f const list = [...f.providers] const j = index + dir if (j < 0 || j >= list.length) return f ;[list[index], list[j]] = [list[j], list[index]] return { ...f, providers: list.map((p, i) => ({ ...p, priority: i + 1 })) } })) } function handleSave() { saveMutation.mutate({ ...(localDefault !== null ? { defaultFamily: localDefault } : {}), ...(localFamilies !== null ? { providers: families.flatMap(f => f.providers.map(p => ({ id: p.id, priority: p.priority, enabled: p.enabled }))) } : {}), }) } function discard() { setLocalFamilies(null) setLocalDefault(null) } return (
} />

model: "auto" on{' '} POST /v1/embeddings routes to the default family. Naming a family (or a provider model id) pins that family; providers inside it are tried in order.

{isLoading ? (

Loading…

) : ( families.map(f => { const u = usageByFamily.get(f.family) const noKeys = f.providers.every(p => p.keyCount === 0) return (

{f.family}

{f.dimensions}d {f.maxInputTokens && ( {formatTokens(f.maxInputTokens)} tok max )} {f.family === defaultFamily ? ( Default · auto ) : ( )}
{u ? <>{u.requestsToday} req today · {formatTokens(u.tokensMonth)} tok this month : '—'}
{f.providers.map((p, i) => (
{i + 1}
{p.platform} {p.modelId} {p.keyCount === 0 && ( no key )}
{p.quotaLabel}
{f.providers.length > 1 && (
)} updateProvider(f.family, p.id, { enabled: c })} />
))}
) }) )} Unsaved changes
) }