import { Box, Button, Checkbox, Dialog, DialogActions, DialogContent, DialogTitle, FormControl, FormControlLabel, FormGroup, InputLabel, MenuItem, Select, TextField, Typography, } from '@mui/material'; import defaultProvidersConfig from '@services/externalAPI/defaultProviders'; import { ModelFeature, ModelInfo } from '@services/externalAPI/interface'; import { useEffect, useRef } from 'react'; import { useTranslation } from 'react-i18next'; interface ModelDialogProps { open: boolean; onClose: () => void; onAddModel: () => void; currentProvider: string | null; providerClass?: string; newModelForm: { name: string; caption: string; features: ModelFeature[]; parameters?: Record; }; availableDefaultModels: ModelInfo[]; selectedDefaultModel: string; onSelectDefaultModel: (model: string) => void; onModelFormChange: (field: string, value: string | ModelFeature[] | Record) => void; onFeatureChange: (feature: ModelFeature, checked: boolean) => void; editMode?: boolean; } export function NewModelDialog({ open, onClose, onAddModel, currentProvider, providerClass, newModelForm, availableDefaultModels, selectedDefaultModel, onSelectDefaultModel, onModelFormChange, onFeatureChange, editMode = false, }: ModelDialogProps) { const { t } = useTranslation(['translation', 'agent']); const lastSelectedModelReference = useRef(null); // Handle workflow file selection for ComfyUI const handleSelectWorkflowFile = async () => { const result = await window.service.native.pickFile([{ name: 'JSON Files', extensions: ['json'] }]); if (result.length > 0) { const workflowPath = result[0]; const parameters = { ...(newModelForm.parameters || {}), workflowPath }; onModelFormChange('parameters', parameters); } }; // When a preset model is selected, fill in its details to the form useEffect(() => { // 只有当选择的模型与上次不同时才进行更新 if (selectedDefaultModel !== lastSelectedModelReference.current) { lastSelectedModelReference.current = selectedDefaultModel; if (selectedDefaultModel) { const selectedModel = availableDefaultModels.find(m => m.name === selectedDefaultModel); if (selectedModel) { onModelFormChange('name', selectedModel.name); onModelFormChange('caption', selectedModel.caption || ''); onModelFormChange('features', selectedModel.features || ['language' as ModelFeature]); } } } }, [selectedDefaultModel, availableDefaultModels, onModelFormChange]); return ( {t('Preference.AddNewModel', { ns: 'agent' })} {currentProvider && ( <> {availableDefaultModels.length > 0 && ( {t('Preference.SelectFromPresets', { ns: 'agent' })} {t('Preference.PresetModels', { ns: 'agent' })} )} {t('Preference.ModelDetails', { ns: 'agent' })} { onModelFormChange('name', event.target.value); }} fullWidth margin='normal' slotProps={{ htmlInput: { 'data-testid': 'new-model-name-input' } }} /> { onModelFormChange('caption', event.target.value); }} fullWidth margin='normal' helperText={t('Preference.ModelCaptionHelp', { ns: 'agent' })} /> {t('Preference.ModelFeatures', { ns: 'agent' })} {defaultProvidersConfig.modelFeatures.map((feature) => ( { onFeatureChange(feature.value as ModelFeature, event.target.checked); }} /> } label={t(feature.i18nKey, { ns: 'agent' })} /> ))} {/* ComfyUI workflow path */} {providerClass === 'comfyui' && ( {t('Preference.WorkflowFile', { ns: 'agent' })} { const parameters = { ...(newModelForm.parameters || {}), workflowPath: event.target.value }; onModelFormChange('parameters', parameters); }} fullWidth margin='normal' slotProps={{ htmlInput: { 'data-testid': 'workflow-path-input' } }} helperText={t('Preference.WorkflowFileHelp', { ns: 'agent' })} /> )} )} ); }