"use client"; import { useAtomValue } from "jotai"; import { Bot, Check, ChevronDown, Cloud, Edit3, Globe, Plus, Settings2, Shuffle, Sparkles, User, Zap, } from "lucide-react"; import { useCallback, useMemo, useState } from "react"; import { toast } from "sonner"; import { updateLLMPreferencesMutationAtom } from "@/atoms/new-llm-config/new-llm-config-mutation.atoms"; import { globalNewLLMConfigsAtom, llmPreferencesAtom, newLLMConfigsAtom, } from "@/atoms/new-llm-config/new-llm-config-query.atoms"; import { activeSearchSpaceIdAtom } from "@/atoms/search-spaces/search-space-query.atoms"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, } from "@/components/ui/command"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { Spinner } from "@/components/ui/spinner"; import type { GlobalNewLLMConfig, NewLLMConfigPublic, } from "@/contracts/types/new-llm-config.types"; import { cn } from "@/lib/utils"; // Provider icons mapping const getProviderIcon = (provider: string, isAutoMode?: boolean) => { const iconClass = "size-4"; // Special icon for Auto mode if (isAutoMode || provider?.toUpperCase() === "AUTO") { return ; } switch (provider?.toUpperCase()) { case "OPENAI": return ; case "ANTHROPIC": return ; case "GOOGLE": return ; case "GROQ": return ; case "OLLAMA": return ; case "XAI": return ; default: return ; } }; interface ModelSelectorProps { onEdit: (config: NewLLMConfigPublic | GlobalNewLLMConfig, isGlobal: boolean) => void; onAddNew: () => void; className?: string; } export function ModelSelector({ onEdit, onAddNew, className }: ModelSelectorProps) { const [open, setOpen] = useState(false); const [searchQuery, setSearchQuery] = useState(""); // Fetch configs const { data: userConfigs, isLoading: userConfigsLoading } = useAtomValue(newLLMConfigsAtom); const { data: globalConfigs, isLoading: globalConfigsLoading } = useAtomValue(globalNewLLMConfigsAtom); const { data: preferences, isLoading: preferencesLoading } = useAtomValue(llmPreferencesAtom); const searchSpaceId = useAtomValue(activeSearchSpaceIdAtom); const { mutateAsync: updatePreferences } = useAtomValue(updateLLMPreferencesMutationAtom); const isLoading = userConfigsLoading || globalConfigsLoading || preferencesLoading; // Get current agent LLM config const currentConfig = useMemo(() => { if (!preferences) return null; const agentLlmId = preferences.agent_llm_id; if (agentLlmId === null || agentLlmId === undefined) return null; // Check if it's Auto mode (ID 0) or global config (negative ID) if (agentLlmId <= 0) { return globalConfigs?.find((c) => c.id === agentLlmId) ?? null; } // Otherwise, check user configs return userConfigs?.find((c) => c.id === agentLlmId) ?? null; }, [preferences, globalConfigs, userConfigs]); // Check if current config is Auto mode const isCurrentAutoMode = useMemo(() => { return currentConfig && "is_auto_mode" in currentConfig && currentConfig.is_auto_mode; }, [currentConfig]); // Filter configs based on search const filteredGlobalConfigs = useMemo(() => { if (!globalConfigs) return []; if (!searchQuery) return globalConfigs; const query = searchQuery.toLowerCase(); return globalConfigs.filter( (c) => c.name.toLowerCase().includes(query) || c.model_name.toLowerCase().includes(query) || c.provider.toLowerCase().includes(query) ); }, [globalConfigs, searchQuery]); const filteredUserConfigs = useMemo(() => { if (!userConfigs) return []; if (!searchQuery) return userConfigs; const query = searchQuery.toLowerCase(); return userConfigs.filter( (c) => c.name.toLowerCase().includes(query) || c.model_name.toLowerCase().includes(query) || c.provider.toLowerCase().includes(query) ); }, [userConfigs, searchQuery]); // Total model count for conditional search display const totalModels = useMemo(() => { return (globalConfigs?.length ?? 0) + (userConfigs?.length ?? 0); }, [globalConfigs, userConfigs]); const handleSelectConfig = useCallback( async (config: NewLLMConfigPublic | GlobalNewLLMConfig) => { // If already selected, just close if (currentConfig?.id === config.id) { setOpen(false); return; } if (!searchSpaceId) { toast.error("No search space selected"); return; } try { await updatePreferences({ search_space_id: Number(searchSpaceId), data: { agent_llm_id: config.id, }, }); toast.success(`Switched to ${config.name}`); setOpen(false); } catch (error) { console.error("Failed to switch model:", error); toast.error("Failed to switch model"); } }, [currentConfig, searchSpaceId, updatePreferences] ); const handleEditConfig = useCallback( (e: React.MouseEvent, config: NewLLMConfigPublic | GlobalNewLLMConfig, isGlobal: boolean) => { e.stopPropagation(); onEdit(config, isGlobal); setOpen(false); }, [onEdit] ); return ( {totalModels > 3 && (
)}

No models found

Try a different search term

{/* Global Configs Section */} {filteredGlobalConfigs.length > 0 && (
Global Models
{filteredGlobalConfigs.map((config) => { const isSelected = currentConfig?.id === config.id; const isAutoMode = "is_auto_mode" in config && config.is_auto_mode; return ( handleSelectConfig(config)} className={cn( "mx-2 rounded-lg mb-1 cursor-pointer group transition-all", "hover:bg-accent/50", isSelected && "bg-accent/80", isAutoMode && "border border-violet-200 dark:border-violet-800/50" )} >
{getProviderIcon(config.provider, isAutoMode)}
{config.name} {isAutoMode && ( Recommended )} {isSelected && }
{isAutoMode ? "Auto load balancing" : config.model_name} {!isAutoMode && config.citations_enabled && ( Citations )}
{!isAutoMode && ( )}
); })}
)} {filteredGlobalConfigs.length > 0 && filteredUserConfigs.length > 0 && ( )} {/* User Configs Section */} {filteredUserConfigs.length > 0 && (
Your Configurations
{filteredUserConfigs.map((config) => { const isSelected = currentConfig?.id === config.id; return ( handleSelectConfig(config)} className={cn( "mx-2 rounded-lg mb-1 cursor-pointer group transition-all", "hover:bg-accent/50", isSelected && "bg-accent/80" )} >
{getProviderIcon(config.provider)}
{config.name} {isSelected && }
{config.model_name} {config.citations_enabled && ( Citations )}
); })}
)} {/* Add New Config Button */}
); }