"use client"; import { useState, useEffect } from "react"; import { Tabs, TabsList, TabsTrigger, TabsContent } from "./ui/tabs"; import { Check, ChevronsUpDown, Info } from "lucide-react"; import { Button } from "./ui/button"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "./ui/command"; import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover"; import { cn } from "@/lib/utils"; import OpenAIConfig from "./OpenAIConfig"; import GoogleConfig from "./GoogleConfig"; import OllamaConfig from "./OllamaConfig"; import CustomConfig from "./CustomConfig"; import { OllamaModel, LLMConfig, updateLLMConfig, changeProvider as changeProviderUtil, fetchOllamaModelsWithConfig, setOllamaConfig, fetchCustomModels, } from "@/utils/providerUtils"; import { IMAGE_PROVIDERS, LLM_PROVIDERS } from "@/utils/providerConstants"; // Button state interface interface ButtonState { isLoading: boolean; isDisabled: boolean; text: string; showProgress: boolean; progressPercentage?: number; status?: string; } interface LLMProviderSelectionProps { initialLLMConfig: LLMConfig; onConfigChange: (config: LLMConfig) => void; buttonState: ButtonState; setButtonState: (state: ButtonState | ((prev: ButtonState) => ButtonState)) => void; } export default function LLMProviderSelection({ initialLLMConfig, onConfigChange, setButtonState, }: LLMProviderSelectionProps) { const [llmConfig, setLlmConfig] = useState(initialLLMConfig); const [ollamaModels, setOllamaModels] = useState([]); const [customModels, setCustomModels] = useState([]); const [customModelsLoading, setCustomModelsLoading] = useState(false); const [customModelsChecked, setCustomModelsChecked] = useState(false); const [ollamaModelsLoading, setOllamaModelsLoading] = useState(false); const [useCustomOllamaUrl, setUseCustomOllamaUrl] = useState( initialLLMConfig.USE_CUSTOM_URL || false ); const [openModelSelect, setOpenModelSelect] = useState(false); const [openImageProviderSelect, setOpenImageProviderSelect] = useState(false); useEffect(() => { onConfigChange(llmConfig); }, [llmConfig]); useEffect(() => { const needsModelSelection = (llmConfig.LLM === "ollama" && !llmConfig.OLLAMA_MODEL) || (llmConfig.LLM === "custom" && !llmConfig.CUSTOM_MODEL); const needsApiKey = ((llmConfig.IMAGE_PROVIDER === "dall-e-3" || llmConfig.LLM === "openai") && !llmConfig.OPENAI_API_KEY) || ((llmConfig.IMAGE_PROVIDER === "gemini_flash" || llmConfig.LLM === "google") && !llmConfig.GOOGLE_API_KEY) || (llmConfig.IMAGE_PROVIDER === "pexels" && !llmConfig.PEXELS_API_KEY) || (llmConfig.IMAGE_PROVIDER === "pixabay" && !llmConfig.PIXABAY_API_KEY); setButtonState({ isLoading: false, isDisabled: needsModelSelection || needsApiKey, text: needsModelSelection ? "Please Select a Model" : needsApiKey ? "Please Enter API Key" : "Save Configuration", showProgress: false }); }, [llmConfig]); const input_field_changed = (new_value: string, field: string) => { const updatedConfig = updateLLMConfig(llmConfig, field, new_value); setLlmConfig(updatedConfig); }; const handleProviderChange = (provider: string) => { const newConfig = changeProviderUtil(llmConfig, provider); setLlmConfig(newConfig); if (provider === "ollama") { fetchOllamaModels(); } }; const fetchOllamaModels = async () => { try { setOllamaModelsLoading(true); const result = await fetchOllamaModelsWithConfig(llmConfig); setOllamaModels(result.models); if (result.updatedConfig) { setLlmConfig(result.updatedConfig); } } catch (error) { console.error("Error fetching Ollama models:", error); setOllamaModels([]); } finally { setOllamaModelsLoading(false); } }; const fetchCustomModelsHandler = async () => { try { setCustomModelsLoading(true); const models = await fetchCustomModels( llmConfig.CUSTOM_LLM_URL || "", llmConfig.CUSTOM_LLM_API_KEY || "" ); setCustomModels(models); setCustomModelsChecked(true); } catch (error) { console.error("Error fetching custom models:", error); setCustomModels([]); } finally { setCustomModelsLoading(false); } }; const setOllamaConfigHandler = () => { const updatedConfig = setOllamaConfig(llmConfig, useCustomOllamaUrl); setLlmConfig(updatedConfig); }; useEffect(() => { if (llmConfig.LLM === "ollama") { fetchOllamaModels(); } }, [llmConfig.LLM]); useEffect(() => { setOllamaConfigHandler(); }, [useCustomOllamaUrl]); useEffect(() => { if (llmConfig.LLM === "custom") { setCustomModels([]); setCustomModelsChecked(false); setLlmConfig({ ...llmConfig, CUSTOM_MODEL: "" }); } }, [llmConfig.CUSTOM_LLM_URL, llmConfig.CUSTOM_LLM_API_KEY]); useEffect(() => { if (!llmConfig.IMAGE_PROVIDER) { if (llmConfig.LLM === "openai") { setLlmConfig({ ...llmConfig, IMAGE_PROVIDER: "dall-e-3" }); } else if (llmConfig.LLM === "google") { setLlmConfig({ ...llmConfig, IMAGE_PROVIDER: "gemini_flash" }); } else { setLlmConfig({ ...llmConfig, IMAGE_PROVIDER: "pexels" }); } } }, []); return (
{/* Provider Selection - Fixed Header */}
OpenAI Google Ollama Custom
{/* Scrollable Content */}
{/* OpenAI Content */} {/* Google Content */} {/* Ollama Content */} { input_field_changed(modelName, "ollama_model"); }} /> {/* Custom Content */} {/* Image Provider Selection */}
No provider found. {Object.values(IMAGE_PROVIDERS).map( (provider, index) => ( { input_field_changed(value, "image_provider"); setOpenImageProviderSelect(false); }} >
{provider.label}
{provider.description}
) )}
{/* Dynamic API Key Input for Image Provider */} {llmConfig.IMAGE_PROVIDER && IMAGE_PROVIDERS[llmConfig.IMAGE_PROVIDER] && (() => { const provider = IMAGE_PROVIDERS[llmConfig.IMAGE_PROVIDER]; // Show info message when using same API key as main provider if (provider.value === "dall-e-3" && llmConfig.LLM === "openai") { return <>; } if (provider.value === "gemini_flash" && llmConfig.LLM === "google") { return <>; } // Show API key input for other providers return (
{ if (provider.apiKeyField === "PEXELS_API_KEY") { input_field_changed(e.target.value, "pexels_api_key"); } else if (provider.apiKeyField === "PIXABAY_API_KEY") { input_field_changed(e.target.value, "pixabay_api_key"); } }} />

API key for {provider.label} image generation

); })()} {/* Model Information */}

Selected Models

Using{" "} {llmConfig.LLM === "ollama" ? llmConfig.OLLAMA_MODEL ?? "xxxxx" : llmConfig.LLM === "custom" ? llmConfig.CUSTOM_MODEL ?? "xxxxx" : LLM_PROVIDERS[llmConfig.LLM!]?.model_label || "xxxxx"}{" "} for text generation and{" "} {llmConfig.IMAGE_PROVIDER && IMAGE_PROVIDERS[llmConfig.IMAGE_PROVIDER] ? IMAGE_PROVIDERS[llmConfig.IMAGE_PROVIDER].label : "xxxxx"}{" "} for images

); }