import { useEffect, useState } from 'react'; import { Check, ChevronDown, Cpu } from 'lucide-react'; import { api } from '@/api/client'; import type { Provider } from '@/api/types'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { BottomSheet } from '@/components/BottomSheet'; import { useViewport } from '@/hooks/useViewport'; interface Props { provider: string; model: string; onChange: (provider: string, model: string) => void | Promise; } function ProviderModelList({ providers, error, currentProvider, currentModel, onPick, }: { providers: Provider[] | null; error: string | null; currentProvider: string; currentModel: string; onPick: (provider: string, model: string) => void; }) { if (error) { return
{error}
; } if (providers === null) { return
Loading...
; } const singleProvider = providers.length === 1; return ( <> {providers.map((p) => (
{!singleProvider && (
{p.label}
)} {p.models.map((m) => ( ))}
))} ); } export function ProviderPicker({ provider, model, onChange }: Props) { const { isMobile } = useViewport(); const [providers, setProviders] = useState(null); const [error, setError] = useState(null); const [open, setOpen] = useState(false); useEffect(() => { if (!open || providers !== null) return; api.coder .providers() .then(setProviders) .catch((err) => setError(err instanceof Error ? err.message : 'failed to load providers'), ); }, [open, providers]); function handlePick(prov: string, mod: string) { setOpen(false); void onChange(prov, mod); } const currentProviderLabel = providers?.find((p) => p.name === provider)?.label ?? provider; const triggerText = providers && providers.length > 1 ? `${currentProviderLabel} / ${model}` : model; if (isMobile) { return ( <> setOpen(false)} title="Provider / Model">
); } return ( {error && (
{error}
)} {providers === null && !error && (
Loading...
)} {providers && providers.map((p) => { const singleProvider = providers.length === 1; return (
{!singleProvider && (
{p.label}
)} {p.models.map((m) => ( handlePick(p.name, m.id)} className="font-mono text-xs" > {m.label} ))}
); })}
); }