import type { ProviderInfo } from '~/types/model'; import { useEffect, useState, useRef } from 'react'; import type { ModelInfo } from '~/lib/modules/llm/types'; import { classNames } from '~/utils/classNames'; interface ModelSelectorProps { model?: string; setModel?: (model: string) => void; provider?: ProviderInfo; setProvider?: (provider: ProviderInfo) => void; modelList: ModelInfo[]; providerList: ProviderInfo[]; apiKeys: Record; modelLoading?: string; } export const ModelSelector = ({ model, setModel, provider, setProvider, modelList, providerList, modelLoading, }: ModelSelectorProps) => { const [modelSearchQuery, setModelSearchQuery] = useState(''); const [isModelDropdownOpen, setIsModelDropdownOpen] = useState(false); const searchInputRef = useRef(null); // Filter models based on search query const filteredModels = [...modelList] .filter((e) => e.provider === provider?.name && e.name) .filter( (model) => model.label.toLowerCase().includes(modelSearchQuery.toLowerCase()) || model.name.toLowerCase().includes(modelSearchQuery.toLowerCase()), ); // Focus search input when dropdown opens useEffect(() => { if (isModelDropdownOpen && searchInputRef.current) { searchInputRef.current.focus(); } }, [isModelDropdownOpen]); // Update enabled providers when cookies change useEffect(() => { // If current provider is disabled, switch to first enabled provider if (providerList.length === 0) { return; } if (provider && !providerList.map((p) => p.name).includes(provider.name)) { const firstEnabledProvider = providerList[0]; setProvider?.(firstEnabledProvider); // Also update the model to the first available one for the new provider const firstModel = modelList.find((m) => m.provider === firstEnabledProvider.name); if (firstModel) { setModel?.(firstModel.name); } } }, [providerList, provider, setProvider, modelList, setModel]); if (providerList.length === 0) { return (

No providers are currently enabled. Please enable at least one provider in the settings to start using the chat.

); } return (
setIsModelDropdownOpen(!isModelDropdownOpen)} >
{modelList.find((m) => m.name === model)?.label || 'Select model'}
{isModelDropdownOpen && (
setModelSearchQuery(e.target.value)} placeholder="Search models..." className={classNames( 'w-full pl-8 pr-3 py-1.5 rounded-md text-sm', 'bg-bolt-elements-background-depth-2 border border-bolt-elements-borderColor', 'text-bolt-elements-textPrimary placeholder:text-bolt-elements-textTertiary', 'focus:outline-none focus:ring-2 focus:ring-bolt-elements-focus', 'transition-all', )} onClick={(e) => e.stopPropagation()} />
{modelLoading === 'all' || modelLoading === provider?.name ? (
Loading...
) : filteredModels.length === 0 ? (
No models found
) : ( filteredModels.map((modelOption, index) => (
{ e.stopPropagation(); setModel?.(modelOption.name); setIsModelDropdownOpen(false); setModelSearchQuery(''); }} > {modelOption.label}
)) )}
)}
); };