"use client"; import { useAtomValue } from "jotai"; import { AlertCircle, Bot, CheckCircle, CircleDashed, FileText, ImageIcon, RefreshCw, RotateCcw, Save, Shuffle, } from "lucide-react"; import { AnimatePresence, motion } from "motion/react"; import { useEffect, useState } from "react"; import { toast } from "sonner"; import { globalImageGenConfigsAtom, imageGenConfigsAtom, } from "@/atoms/image-gen-config/image-gen-config-query.atoms"; 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 { Alert, AlertDescription } from "@/components/ui/alert"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Skeleton } from "@/components/ui/skeleton"; import { getProviderIcon } from "@/lib/provider-icons"; import { cn } from "@/lib/utils"; const ROLE_DESCRIPTIONS = { agent: { icon: Bot, title: "Agent LLM", description: "Primary LLM for chat interactions and agent operations", color: "text-blue-600 dark:text-blue-400", bgColor: "bg-blue-500/10", prefKey: "agent_llm_id" as const, configType: "llm" as const, }, document_summary: { icon: FileText, title: "Document Summary LLM", description: "Handles document summarization and research synthesis", color: "text-purple-600 dark:text-purple-400", bgColor: "bg-purple-500/10", prefKey: "document_summary_llm_id" as const, configType: "llm" as const, }, image_generation: { icon: ImageIcon, title: "Image Generation Model", description: "Model used for AI image generation (DALL-E, GPT Image, etc.)", color: "text-teal-600 dark:text-teal-400", bgColor: "bg-teal-500/10", prefKey: "image_generation_config_id" as const, configType: "image" as const, }, }; interface LLMRoleManagerProps { searchSpaceId: number; } export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) { // LLM configs const { data: newLLMConfigs = [], isFetching: configsLoading, error: configsError, refetch: refreshConfigs, } = useAtomValue(newLLMConfigsAtom); const { data: globalConfigs = [], isFetching: globalConfigsLoading, error: globalConfigsError, } = useAtomValue(globalNewLLMConfigsAtom); // Image gen configs const { data: userImageConfigs = [], isFetching: imageConfigsLoading, error: imageConfigsError, } = useAtomValue(imageGenConfigsAtom); const { data: globalImageConfigs = [], isFetching: globalImageConfigsLoading, error: globalImageConfigsError, } = useAtomValue(globalImageGenConfigsAtom); // Preferences const { data: preferences = {}, isFetching: preferencesLoading, error: preferencesError, } = useAtomValue(llmPreferencesAtom); const { mutateAsync: updatePreferences } = useAtomValue(updateLLMPreferencesMutationAtom); const [assignments, setAssignments] = useState({ agent_llm_id: preferences.agent_llm_id ?? "", document_summary_llm_id: preferences.document_summary_llm_id ?? "", image_generation_config_id: preferences.image_generation_config_id ?? "", }); const [hasChanges, setHasChanges] = useState(false); const [isSaving, setIsSaving] = useState(false); useEffect(() => { const newAssignments = { agent_llm_id: preferences.agent_llm_id ?? "", document_summary_llm_id: preferences.document_summary_llm_id ?? "", image_generation_config_id: preferences.image_generation_config_id ?? "", }; setAssignments(newAssignments); setHasChanges(false); }, [preferences]); const handleRoleAssignment = (prefKey: string, configId: string) => { const newAssignments = { ...assignments, [prefKey]: configId === "unassigned" ? "" : parseInt(configId), }; setAssignments(newAssignments); const currentPrefs = { agent_llm_id: preferences.agent_llm_id ?? "", document_summary_llm_id: preferences.document_summary_llm_id ?? "", image_generation_config_id: preferences.image_generation_config_id ?? "", }; const hasChangesNow = Object.keys(newAssignments).some( (key) => newAssignments[key as keyof typeof newAssignments] !== currentPrefs[key as keyof typeof currentPrefs] ); setHasChanges(hasChangesNow); }; const handleSave = async () => { setIsSaving(true); const toNumericOrUndefined = (val: string | number) => typeof val === "string" ? (val ? parseInt(val) : undefined) : val; const numericAssignments = { agent_llm_id: toNumericOrUndefined(assignments.agent_llm_id), document_summary_llm_id: toNumericOrUndefined(assignments.document_summary_llm_id), image_generation_config_id: toNumericOrUndefined(assignments.image_generation_config_id), }; await updatePreferences({ search_space_id: searchSpaceId, data: numericAssignments, }); setHasChanges(false); toast.success("Role assignments saved successfully!"); setIsSaving(false); }; const handleReset = () => { setAssignments({ agent_llm_id: preferences.agent_llm_id ?? "", document_summary_llm_id: preferences.document_summary_llm_id ?? "", image_generation_config_id: preferences.image_generation_config_id ?? "", }); setHasChanges(false); }; const isAssignmentComplete = assignments.agent_llm_id !== "" && assignments.agent_llm_id !== null && assignments.agent_llm_id !== undefined && assignments.document_summary_llm_id !== "" && assignments.document_summary_llm_id !== null && assignments.document_summary_llm_id !== undefined && assignments.image_generation_config_id !== "" && assignments.image_generation_config_id !== null && assignments.image_generation_config_id !== undefined; // Combine global and custom LLM configs const allLLMConfigs = [ ...globalConfigs.map((config) => ({ ...config, is_global: true })), ...newLLMConfigs.filter((config) => config.id && config.id.toString().trim() !== ""), ]; // Combine global and custom image gen configs const allImageConfigs = [ ...globalImageConfigs.map((config) => ({ ...config, is_global: true })), ...(userImageConfigs ?? []).filter((config) => config.id && config.id.toString().trim() !== ""), ]; const isLoading = configsLoading || preferencesLoading || globalConfigsLoading || imageConfigsLoading || globalImageConfigsLoading; const hasError = configsError || preferencesError || globalConfigsError || imageConfigsError || globalImageConfigsError; const hasAnyConfigs = allLLMConfigs.length > 0 || allImageConfigs.length > 0; return (
{role.description}
Auto Mode
Routes across all available providers
{assignedConfig.model_name}
{assignedConfig.api_base}
)}You have unsaved changes