import { useState, useCallback, useEffect } from 'react'; import { Dialog, DialogContent, DialogTitle, DialogDescription } from '@/components/ui/dialog'; 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 { Sparkles, Wrench, Zap, Loader2, CheckCircle, XCircle } from 'lucide-react'; import { useI18n } from '@/lib/hooks/use-i18n'; import type { EditingModel } from '@/lib/types/settings'; import type { ProviderId } from '@/lib/ai/providers'; import { cn } from '@/lib/utils'; import { createVerifyModelRequest } from './utils'; interface ModelEditDialogProps { open: boolean; onOpenChange: (open: boolean) => void; editingModel: EditingModel | null; setEditingModel: (model: EditingModel | null) => void; onSave: () => void; onAutoSave?: () => void; // Auto-save on blur providerId: ProviderId; apiKey: string; baseUrl?: string; providerType?: string; requiresApiKey?: boolean; isServerConfigured?: boolean; } export function ModelEditDialog({ open, onOpenChange, editingModel, setEditingModel, onSave, onAutoSave, providerId, apiKey, baseUrl, providerType, requiresApiKey, isServerConfigured, }: ModelEditDialogProps) { const { t } = useI18n(); const [testStatus, setTestStatus] = useState<'idle' | 'testing' | 'success' | 'error'>('idle'); const [testMessage, setTestMessage] = useState(''); // Reset test status when dialog closes useEffect(() => { if (!open) { // eslint-disable-next-line react-hooks/set-state-in-effect -- Reset state when dialog closes setTestStatus('idle'); setTestMessage(''); } }, [open]); const handleClose = () => { onOpenChange(false); setEditingModel(null); }; const handleTestModel = useCallback(async () => { if (!editingModel) { return; } setTestStatus('testing'); setTestMessage(''); try { const response = await fetch('/api/verify-model', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify( createVerifyModelRequest({ providerId, modelId: editingModel.model.id, apiKey, baseUrl, providerType, 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')); } }, [editingModel, apiKey, baseUrl, providerId, providerType, requiresApiKey, t]); if (!editingModel) return null; return ( {editingModel.modelIndex === null ? t('settings.addNewModel') : t('settings.editModel')} {editingModel.modelIndex === null ? t('settings.addNewModelDescription') : t('settings.editModelDescription')}

{editingModel.modelIndex === null ? t('settings.addNewModel') : t('settings.editModel')}

{/* Model ID */}
{ const newId = e.target.value; const currentName = editingModel.model.name; const currentId = editingModel.model.id; // Auto-sync name if it's empty or matches the old ID const shouldSyncName = !currentName || currentName === currentId; setEditingModel({ ...editingModel, model: { ...editingModel.model, id: newId, name: shouldSyncName ? newId : currentName, }, }); // Reset test status when model ID changes setTestStatus('idle'); setTestMessage(''); }} onBlur={() => onAutoSave?.()} />
{/* Display Name */}
setEditingModel({ ...editingModel, model: { ...editingModel.model, name: e.target.value }, }) } onBlur={() => onAutoSave?.()} />
{/* Capabilities */}
{ setEditingModel({ ...editingModel, model: { ...editingModel.model, capabilities: { ...editingModel.model.capabilities, vision: checked as boolean, }, }, }); onAutoSave?.(); }} />
{ setEditingModel({ ...editingModel, model: { ...editingModel.model, capabilities: { ...editingModel.model.capabilities, tools: checked as boolean, }, }, }); onAutoSave?.(); }} />
{ setEditingModel({ ...editingModel, model: { ...editingModel.model, capabilities: { ...editingModel.model.capabilities, streaming: checked as boolean, }, }, }); onAutoSave?.(); }} />
{/* Advanced Settings */}
setEditingModel({ ...editingModel, model: { ...editingModel.model, contextWindow: e.target.value ? parseInt(e.target.value) : undefined, }, }) } onBlur={() => onAutoSave?.()} />
setEditingModel({ ...editingModel, model: { ...editingModel.model, outputWindow: e.target.value ? parseInt(e.target.value) : undefined, }, }) } onBlur={() => onAutoSave?.()} />
{/* Test Model */}
{testMessage && (
{testStatus === 'success' && } {testStatus === 'error' && }

{testMessage}

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