"use client"; import { useState, useEffect } from "react"; import OpenAIConfig from "./OpenAIConfig"; import GoogleConfig from "./GoogleConfig"; import AnthropicConfig from "./AnthropicConfig"; import OllamaConfig from "./OllamaConfig"; import CustomConfig from "./CustomConfig"; import CodexConfig from "./CodexConfig"; import { updateLLMConfig, changeProvider as changeProviderUtil, } from "@/utils/providerUtils"; import { LLMConfig } from "@/types/llm_config"; import ImageSelectionConfig from "./ImageSelectionConfig"; import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; // 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 [openImageProviderSelect, setOpenImageProviderSelect] = useState(false); const isImageGenerationDisabled = llmConfig.DISABLE_IMAGE_GENERATION ?? false; useEffect(() => { onConfigChange(llmConfig); }, [llmConfig]); useEffect(() => { const needsModelSelection = (llmConfig.LLM === "openai" && !llmConfig.OPENAI_MODEL) || (llmConfig.LLM === "google" && !llmConfig.GOOGLE_MODEL) || (llmConfig.LLM === "ollama" && !llmConfig.OLLAMA_MODEL) || (llmConfig.LLM === "custom" && !llmConfig.CUSTOM_MODEL) || (llmConfig.LLM === "anthropic" && !llmConfig.ANTHROPIC_MODEL) || (llmConfig.LLM === "codex" && !llmConfig.CODEX_MODEL); const needsProviderApiKey = (llmConfig.LLM === "openai" && !llmConfig.OPENAI_API_KEY) || (llmConfig.LLM === "google" && !llmConfig.GOOGLE_API_KEY) || (llmConfig.LLM === "anthropic" && !llmConfig.ANTHROPIC_API_KEY); const needsImageProviderApiKey = !llmConfig.DISABLE_IMAGE_GENERATION && ((llmConfig.IMAGE_PROVIDER === "dall-e-3" && !llmConfig.OPENAI_API_KEY) || (llmConfig.IMAGE_PROVIDER === "gpt-image-1.5" && !llmConfig.OPENAI_API_KEY) || (llmConfig.IMAGE_PROVIDER === "gemini_flash" && !llmConfig.GOOGLE_API_KEY) || (llmConfig.IMAGE_PROVIDER === "nanobanana_pro" && !llmConfig.GOOGLE_API_KEY) || (llmConfig.IMAGE_PROVIDER === "pexels" && !llmConfig.PEXELS_API_KEY) || (llmConfig.IMAGE_PROVIDER === "pixabay" && !llmConfig.PIXABAY_API_KEY)); const needsApiKey = needsProviderApiKey || needsImageProviderApiKey; const needsOllamaUrl = llmConfig.LLM === "ollama" && !llmConfig.OLLAMA_URL; const needsComfyUIConfig = !llmConfig.DISABLE_IMAGE_GENERATION && llmConfig.IMAGE_PROVIDER === "comfyui" && (!llmConfig.COMFYUI_URL || !llmConfig.COMFYUI_WORKFLOW); setButtonState({ isLoading: false, isDisabled: needsModelSelection || needsApiKey || needsOllamaUrl || needsComfyUIConfig, text: needsModelSelection ? "Please Select a Model" : needsApiKey ? "Please Enter API Key" : needsOllamaUrl ? "Please Enter Ollama URL" : needsComfyUIConfig ? "Please Configure ComfyUI" : "Save Configuration", showProgress: false, }); }, [llmConfig]); const input_field_changed = (new_value: string | boolean, field: string) => { const updatedConfig = updateLLMConfig(llmConfig, field, new_value); setLlmConfig(updatedConfig); }; const getApiKeyValue = (field?: string) => { switch (field) { case "OPENAI_API_KEY": return llmConfig.OPENAI_API_KEY || ""; case "GOOGLE_API_KEY": return llmConfig.GOOGLE_API_KEY || ""; case "ANTHROPIC_API_KEY": return llmConfig.ANTHROPIC_API_KEY || ""; case "PEXELS_API_KEY": return llmConfig.PEXELS_API_KEY || ""; case "PIXABAY_API_KEY": return llmConfig.PIXABAY_API_KEY || ""; default: return ""; } }; const handleApiKeyInputChange = (field: string | undefined, value: string) => { switch (field) { case "OPENAI_API_KEY": input_field_changed(value, "openai_api_key"); break; case "GOOGLE_API_KEY": input_field_changed(value, "google_api_key"); break; case "ANTHROPIC_API_KEY": input_field_changed(value, "anthropic_api_key"); break; case "PEXELS_API_KEY": input_field_changed(value, "pexels_api_key"); break; case "PIXABAY_API_KEY": input_field_changed(value, "pixabay_api_key"); break; default: break; } }; const handleProviderChange = (provider: string) => { const newConfig = changeProviderUtil(llmConfig, provider); setLlmConfig(newConfig); }; useEffect(() => { if (!llmConfig.USE_CUSTOM_URL) { setLlmConfig({ ...llmConfig, OLLAMA_URL: "http://localhost:11434" }); } else { if (!llmConfig.OLLAMA_URL) { setLlmConfig({ ...llmConfig, OLLAMA_URL: "http://localhost:11434" }); } } }, [llmConfig.USE_CUSTOM_URL]); useEffect(() => { setLlmConfig((prevConfig) => { const updates: Partial = {}; if (!prevConfig.DISABLE_IMAGE_GENERATION && !prevConfig.IMAGE_PROVIDER) { if (prevConfig.LLM === "openai") { updates.IMAGE_PROVIDER = "gpt-image-1.5"; } else if (prevConfig.LLM === "google") { updates.IMAGE_PROVIDER = "gemini_flash"; } else { updates.IMAGE_PROVIDER = "pexels"; } } if (!prevConfig.OLLAMA_URL) { updates.OLLAMA_URL = "http://localhost:11434"; } if (Object.keys(updates).length === 0) { return prevConfig; } return { ...prevConfig, ...updates }; }); }, []); useEffect(() => { setLlmConfig((prevConfig) => { const updates: Partial = {}; if ( prevConfig.IMAGE_PROVIDER === "dall-e-3" && !prevConfig.DALL_E_3_QUALITY ) { updates.DALL_E_3_QUALITY = "standard"; } if ( prevConfig.IMAGE_PROVIDER === "gpt-image-1.5" && !prevConfig.GPT_IMAGE_1_5_QUALITY ) { updates.GPT_IMAGE_1_5_QUALITY = "medium"; } if (Object.keys(updates).length === 0) { return prevConfig; } return { ...prevConfig, ...updates }; }); }, [llmConfig.IMAGE_PROVIDER]); return (
{/* Provider Selection - Fixed Header */}
OpenAI Google Anthropic Ollama Custom ChatGPT
{/* Scrollable Content */}
{/* OpenAI Content */} {/* Google Content */} {/* Anthropic Content */} {/* Ollama Content */} {/* Custom Content */} {/* ChatGPT / Codex Content */} {/* Image Generation Toggle */} {/*
{ input_field_changed(checked, "disable_image_generation"); if (checked) { setOpenImageProviderSelect(false); } }} />

When enabled, slides will not include automatically generated images.

*/} {/* Model Information */} {/*

Selected Models

Using{" "} {llmConfig.LLM === "ollama" ? llmConfig.OLLAMA_MODEL ?? "xxxxx" : llmConfig.LLM === "custom" ? llmConfig.CUSTOM_MODEL ?? "xxxxx" : llmConfig.LLM === "anthropic" ? llmConfig.ANTHROPIC_MODEL ?? "xxxxx" : llmConfig.LLM === "google" ? llmConfig.GOOGLE_MODEL ?? "xxxxx" : llmConfig.LLM === "openai" ? llmConfig.OPENAI_MODEL ?? "xxxxx" : llmConfig.LLM === "codex" ? llmConfig.CODEX_MODEL ?? "xxxxx" : "xxxxx"}{" "} for text generation{" "} {isImageGenerationDisabled ? ( "and image generation is disabled." ) : ( <> and{" "} {llmConfig.IMAGE_PROVIDER && IMAGE_PROVIDERS[llmConfig.IMAGE_PROVIDER] ? IMAGE_PROVIDERS[llmConfig.IMAGE_PROVIDER].label : "xxxxx"}{" "} for images )}

*/} {/* */}
); }