"use client"; import { useAtomValue } from "jotai"; import { AlertCircle, Bot, CheckCircle, FileText, Loader2, RefreshCw, RotateCcw, Save, } from "lucide-react"; import { motion } from "motion/react"; import { useEffect, 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 { Alert, AlertDescription } from "@/components/ui/alert"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; const ROLE_DESCRIPTIONS = { agent: { icon: Bot, title: "Agent LLM", description: "Primary LLM for chat interactions and agent operations", color: "bg-blue-100 text-blue-800 border-blue-200", examples: "Chat responses, agent tasks, real-time interactions", characteristics: ["Fast responses", "Conversational", "Agent operations"], }, document_summary: { icon: FileText, title: "Document Summary LLM", description: "Handles document summarization", color: "bg-purple-100 text-purple-800 border-purple-200", examples: "Document analysis, podcasts, research synthesis", characteristics: ["Large context window", "Deep reasoning", "Summarization"], }, }; interface LLMRoleManagerProps { searchSpaceId: number; } export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) { // Use new LLM config system const { data: newLLMConfigs = [], isFetching: configsLoading, error: configsError, refetch: refreshConfigs, } = useAtomValue(newLLMConfigsAtom); const { data: globalConfigs = [], isFetching: globalConfigsLoading, error: globalConfigsError, refetch: refreshGlobalConfigs, } = useAtomValue(globalNewLLMConfigsAtom); 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 || "", }); 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 || "", }; setAssignments(newAssignments); setHasChanges(false); }, [preferences]); const handleRoleAssignment = (role: string, configId: string) => { const newAssignments = { ...assignments, [role]: configId === "unassigned" ? "" : parseInt(configId), }; setAssignments(newAssignments); // Check if there are changes compared to current preferences const currentPrefs = { agent_llm_id: preferences.agent_llm_id || "", document_summary_llm_id: preferences.document_summary_llm_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 numericAssignments = { agent_llm_id: typeof assignments.agent_llm_id === "string" ? assignments.agent_llm_id ? parseInt(assignments.agent_llm_id) : undefined : assignments.agent_llm_id, document_summary_llm_id: typeof assignments.document_summary_llm_id === "string" ? assignments.document_summary_llm_id ? parseInt(assignments.document_summary_llm_id) : undefined : assignments.document_summary_llm_id, }; await updatePreferences({ search_space_id: searchSpaceId, data: numericAssignments, }); setHasChanges(false); toast.success("LLM 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 || "", }); setHasChanges(false); }; const isAssignmentComplete = assignments.agent_llm_id && assignments.document_summary_llm_id; // Combine global and custom configs (new system) const allConfigs = [ ...globalConfigs.map((config) => ({ ...config, is_global: true })), ...newLLMConfigs.filter((config) => config.id && config.id.toString().trim() !== ""), ]; const availableConfigs = allConfigs; const isLoading = configsLoading || preferencesLoading || globalConfigsLoading; const hasError = configsError || preferencesError || globalConfigsError; return (
{/* Header */}
{/* Error Alert */} {hasError && ( {(configsError?.message ?? "Failed to load LLM configurations") || (preferencesError?.message ?? "Failed to load preferences") || (globalConfigsError?.message ?? "Failed to load global configurations")} )} {/* Loading State */} {isLoading && (
{configsLoading && preferencesLoading ? "Loading configurations and preferences..." : configsLoading ? "Loading configurations..." : "Loading preferences..."}
)} {/* Info Alert */} {!isLoading && !hasError && (
{availableConfigs.length === 0 ? ( No LLM configurations found. Please add at least one LLM provider in the Agent Configs tab before assigning roles. ) : !isAssignmentComplete ? ( Complete all role assignments to enable full functionality. Each role serves different purposes in your workflow. ) : ( All roles are assigned and ready to use! Your LLM configuration is complete. )} {/* Role Assignment Cards */} {availableConfigs.length > 0 && (
{Object.entries(ROLE_DESCRIPTIONS).map(([key, role]) => { const IconComponent = role.icon; const currentAssignment = assignments[`${key}_llm_id` as keyof typeof assignments]; const assignedConfig = availableConfigs.find( (config) => config.id === currentAssignment ); return (
{role.title} {role.description}
{currentAssignment && ( )}
{assignedConfig && (
Assigned: {assignedConfig.provider} {assignedConfig.name} {"is_global" in assignedConfig && assignedConfig.is_global && ( 🌐 Global )}
Model: {assignedConfig.model_name}
{assignedConfig.api_base && (
Base: {assignedConfig.api_base}
)}
)}
); })}
)} {/* Action Buttons */} {hasChanges && (
)}
)}
); }