import { useRouter, useSearchParams } from "next/navigation"; import { type ReactNode, useEffect, useState } from "react"; import { useGetSettingsQuery } from "@/app/api/queries/useGetSettingsQuery"; import AnthropicLogo from "@/components/icons/anthropic-logo"; import IBMLogo from "@/components/icons/ibm-logo"; import OllamaLogo from "@/components/icons/ollama-logo"; import OpenAILogo from "@/components/icons/openai-logo"; import { useProviderHealth } from "@/components/provider-health-banner"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { useAuth } from "@/contexts/auth-context"; import { cn } from "@/lib/utils"; import type { ModelProvider } from "../_helpers/model-helpers"; import AnthropicSettingsDialog from "./anthropic-settings-dialog"; import OllamaSettingsDialog from "./ollama-settings-dialog"; import OpenAISettingsDialog from "./openai-settings-dialog"; import WatsonxSettingsDialog from "./watsonx-settings-dialog"; export const ModelProviders = () => { const { isAuthenticated, isNoAuthMode } = useAuth(); const searchParams = useSearchParams(); const router = useRouter(); const { data: settings = {} } = useGetSettingsQuery({ enabled: isAuthenticated || isNoAuthMode, }); const { health } = useProviderHealth(); const [dialogOpen, setDialogOpen] = useState(); const allProviderKeys: ModelProvider[] = [ "openai", "ollama", "watsonx", "anthropic", ]; // Handle URL search param to open dialogs useEffect(() => { const searchParam = searchParams.get("setup"); if (searchParam && allProviderKeys.includes(searchParam as ModelProvider)) { setDialogOpen(searchParam as ModelProvider); } }, [searchParams]); // Function to close dialog and remove search param const handleCloseDialog = () => { setDialogOpen(undefined); // Remove search param from URL const params = new URLSearchParams(searchParams.toString()); params.delete("setup"); const newUrl = params.toString() ? `${window.location.pathname}?${params.toString()}` : window.location.pathname; router.replace(newUrl); }; const modelProvidersMap: Record< ModelProvider, { name: string; logo: (props: React.SVGProps) => ReactNode; logoColor: string; logoBgColor: string; } > = { openai: { name: "OpenAI", logo: OpenAILogo, logoColor: "text-black", logoBgColor: "bg-white", }, anthropic: { name: "Anthropic", logo: AnthropicLogo, logoColor: "text-[#D97757]", logoBgColor: "bg-white", }, ollama: { name: "Ollama", logo: OllamaLogo, logoColor: "text-black", logoBgColor: "bg-white", }, watsonx: { name: "IBM watsonx.ai", logo: IBMLogo, logoColor: "text-white", logoBgColor: "bg-[#1063FE]", }, }; const currentLlmProvider = (settings.agent?.llm_provider as ModelProvider) || "openai"; const currentEmbeddingProvider = (settings.knowledge?.embedding_provider as ModelProvider) || "openai"; return ( <>
{allProviderKeys.map((providerKey) => { const { name, logo: Logo, logoColor, logoBgColor, } = modelProvidersMap[providerKey]; const isLlmProvider = providerKey === currentLlmProvider; const isEmbeddingProvider = providerKey === currentEmbeddingProvider; // Check if this specific provider is unhealthy const hasLlmError = isLlmProvider && health?.llm_error; const hasEmbeddingError = isEmbeddingProvider && health?.embedding_error; const isProviderUnhealthy = hasLlmError || hasEmbeddingError; return (
{ }
{name} {isProviderUnhealthy && ( )}
); })}
); }; export default ModelProviders;