import { useState, useCallback, useEffect } from 'react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Checkbox } from '@/components/ui/checkbox'; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '@/components/ui/alert-dialog'; import { Loader2, CheckCircle2, XCircle, Eye, EyeOff, RotateCcw, Plus, Zap, Settings2, Trash2, Sparkles, Wrench, FileText, Send, } from 'lucide-react'; import { useI18n } from '@/lib/hooks/use-i18n'; import type { ProviderConfig } from '@/lib/ai/providers'; import type { ProvidersConfig } from '@/lib/types/settings'; import { createVerifyModelRequest, formatContextWindow } from './utils'; import { cn } from '@/lib/utils'; interface ProviderConfigPanelProps { provider: ProviderConfig; initialApiKey: string; initialBaseUrl: string; initialRequiresApiKey: boolean; providersConfig: ProvidersConfig; onConfigChange: (apiKey: string, baseUrl: string, requiresApiKey: boolean) => void; onSave: () => void; // Auto-save on blur onEditModel: (index: number) => void; onDeleteModel: (index: number) => void; onAddModel: () => void; onResetToDefault?: () => void; // Reset provider to default configuration isBuiltIn: boolean; // To determine if reset button should be shown } export function ProviderConfigPanel({ provider, initialApiKey, initialBaseUrl, initialRequiresApiKey, providersConfig, onConfigChange, onSave, onEditModel, onDeleteModel, onAddModel, onResetToDefault, isBuiltIn, }: ProviderConfigPanelProps) { const { t } = useI18n(); // Local state for this provider const [apiKey, setApiKey] = useState(initialApiKey); const [baseUrl, setBaseUrl] = useState(initialBaseUrl); const [requiresApiKey, setRequiresApiKey] = useState(initialRequiresApiKey); const [showApiKey, setShowApiKey] = useState(false); const [testStatus, setTestStatus] = useState<'idle' | 'testing' | 'success' | 'error'>('idle'); const [testMessage, setTestMessage] = useState(''); const [showResetDialog, setShowResetDialog] = useState(false); // Update local state when provider changes or initial values change useEffect(() => { // eslint-disable-next-line react-hooks/set-state-in-effect -- Sync local state from props on provider change setApiKey(initialApiKey); setBaseUrl(initialBaseUrl); setRequiresApiKey(initialRequiresApiKey); setTestStatus('idle'); setTestMessage(''); }, [provider.id, initialApiKey, initialBaseUrl, initialRequiresApiKey]); // Notify parent of changes const handleApiKeyChange = (key: string) => { setApiKey(key); onConfigChange(key, baseUrl, requiresApiKey); }; const handleBaseUrlChange = (url: string) => { setBaseUrl(url); onConfigChange(apiKey, url, requiresApiKey); }; const handleRequiresApiKeyChange = (requires: boolean) => { setRequiresApiKey(requires); onConfigChange(apiKey, baseUrl, requires); }; const handleTestApi = useCallback(async () => { setTestStatus('testing'); setTestMessage(''); const availableModels = providersConfig[provider.id]?.models || []; if (availableModels.length === 0) { setTestStatus('error'); setTestMessage(t('settings.noModelsAvailable') || 'No models available for testing'); return; } const testModelId = availableModels[0].id; try { const response = await fetch('/api/verify-model', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify( createVerifyModelRequest({ providerId: provider.id, modelId: testModelId, apiKey, baseUrl, providerType: provider.type, requiresApiKey, }), ), }); const data = await response.json(); if (data.success) { setTestStatus('success'); setTestMessage(t('settings.connectionSuccess')); } else { setTestStatus('error'); setTestMessage(data.error || t('settings.connectionFailed')); } } catch (_error) { setTestStatus('error'); setTestMessage(t('settings.connectionFailed')); } }, [apiKey, baseUrl, provider.id, provider.type, requiresApiKey, providersConfig, t]); const models = providersConfig[provider.id]?.models || []; const isServerConfigured = providersConfig[provider.id]?.isServerConfigured; return (
{testMessage}
{t('settings.requestUrl')}: {fullUrl}
); })()}