import { useState, useEffect } from "react"; import { useRouter } from "@tanstack/react-router"; import { ArrowLeft, AlertTriangle } from "lucide-react"; import { useSettings } from "@/hooks/useSettings"; import { useLanguageModelProviders } from "@/hooks/useLanguageModelProviders"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { Skeleton } from "@/components/ui/skeleton"; import {} from "@/components/ui/accordion"; import { Button } from "@/components/ui/button"; import { Switch } from "@/components/ui/switch"; import { showError } from "@/lib/toast"; import { UserSettings, AzureProviderSetting, VertexProviderSetting, } from "@/lib/schemas"; import { ProviderSettingsHeader } from "./ProviderSettingsHeader"; import { ApiKeyConfiguration } from "./ApiKeyConfiguration"; import { ModelsSection } from "./ModelsSection"; interface ProviderSettingsPageProps { provider: string; } export function ProviderSettingsPage({ provider }: ProviderSettingsPageProps) { const { settings, envVars, loading: settingsLoading, error: settingsError, updateSettings, } = useSettings(); // Fetch all providers const { data: allProviders, isLoading: providersLoading, error: providersError, } = useLanguageModelProviders(); // Find the specific provider data from the fetched list const providerData = allProviders?.find((p) => p.id === provider); const supportsCustomModels = providerData?.type === "custom" || providerData?.type === "cloud"; const isDyad = provider === "auto"; const [apiKeyInput, setApiKeyInput] = useState(""); const [isSaving, setIsSaving] = useState(false); const [saveError, setSaveError] = useState(null); const router = useRouter(); // Use fetched data (or defaults for Dyad) const providerDisplayName = isDyad ? "Dyad" : (providerData?.name ?? "Unknown Provider"); const providerWebsiteUrl = isDyad ? "https://academy.dyad.sh/settings" : providerData?.websiteUrl; const hasFreeTier = isDyad ? false : providerData?.hasFreeTier; const envVarName = isDyad ? undefined : providerData?.envVarName; // Use provider ID (which is the 'provider' prop) const userApiKey = settings?.providerSettings?.[provider]?.apiKey?.value; // --- Configuration Logic --- Updated Priority --- const isValidUserKey = !!userApiKey && !userApiKey.startsWith("Invalid Key") && userApiKey !== "Not Set"; const hasEnvKey = !!(envVarName && envVars[envVarName]); const azureSettings = settings?.providerSettings?.azure as | AzureProviderSetting | undefined; const azureApiKeyFromSettings = (azureSettings?.apiKey?.value ?? "").trim(); const azureResourceNameFromSettings = ( azureSettings?.resourceName ?? "" ).trim(); const azureHasSavedSettings = Boolean( azureApiKeyFromSettings && azureResourceNameFromSettings, ); const azureHasEnvConfiguration = Boolean( envVars["AZURE_API_KEY"] && envVars["AZURE_RESOURCE_NAME"], ); const vertexSettings = settings?.providerSettings?.vertex as | VertexProviderSetting | undefined; const isVertexConfigured = Boolean( vertexSettings?.projectId && vertexSettings?.location && vertexSettings?.serviceAccountKey?.value, ); const isAzureConfigured = provider === "azure" ? azureHasSavedSettings || azureHasEnvConfiguration : false; const isConfigured = provider === "azure" ? isAzureConfigured : provider === "vertex" ? isVertexConfigured : isValidUserKey || hasEnvKey; // Configured if either is set // --- Save Handler --- const handleSaveKey = async () => { if (!apiKeyInput) { setSaveError("API Key cannot be empty."); return; } setIsSaving(true); setSaveError(null); try { const settingsUpdate: Partial = { providerSettings: { ...settings?.providerSettings, [provider]: { ...settings?.providerSettings?.[provider], apiKey: { value: apiKeyInput, }, }, }, }; if (isDyad) { settingsUpdate.enableDyadPro = true; } await updateSettings(settingsUpdate); setApiKeyInput(""); // Clear input on success // Optionally show a success message } catch (error: any) { console.error("Error saving API key:", error); setSaveError(error.message || "Failed to save API key."); } finally { setIsSaving(false); } }; // --- Delete Handler --- const handleDeleteKey = async () => { setIsSaving(true); setSaveError(null); try { await updateSettings({ providerSettings: { ...settings?.providerSettings, [provider]: { ...settings?.providerSettings?.[provider], apiKey: undefined, }, }, }); // Optionally show a success message } catch (error: any) { console.error("Error deleting API key:", error); setSaveError(error.message || "Failed to delete API key."); } finally { setIsSaving(false); } }; // --- Toggle Dyad Pro Handler --- const handleToggleDyadPro = async (enabled: boolean) => { setIsSaving(true); try { await updateSettings({ enableDyadPro: enabled, }); } catch (error: any) { showError(`Error toggling Dyad Pro: ${error}`); } finally { setIsSaving(false); } }; // Effect to clear input error when input changes useEffect(() => { if (saveError) { setSaveError(null); } }, [apiKeyInput]); // --- Loading State for Providers --- if (providersLoading) { return (
); } // --- Error State for Providers --- if (providersError) { return (

Configure Provider

Error Loading Provider Details Could not load provider data: {providersError.message}
); } // Handle case where provider is not found (e.g., invalid ID in URL) if (!providerData && !isDyad) { return (

Provider Not Found

Error The provider with ID "{provider}" could not be found.
); } return (
router.history.back()} /> {settingsLoading ? (
) : settingsError ? ( Error Loading Settings Could not load configuration data: {settingsError.message} ) : ( )} {isDyad && !settingsLoading && (

Enable Dyad Pro

Toggle to enable Dyad Pro

)} {/* Conditionally render CustomModelsSection */} {supportsCustomModels && providerData && ( )}
); }