import type { FC } from 'react' import { memo, useCallback, useEffect, useMemo, useRef, useState, } from 'react' import { RiCloseLine } from '@remixicon/react' import { useTranslation } from 'react-i18next' import type { CustomConfigurationModelFixedFields, ModelProvider, } from '../declarations' import { ConfigurationMethodEnum, FormTypeEnum, ModelModalModeEnum, } from '../declarations' import { useLanguage, } from '../hooks' import Button from '@/app/components/base/button' import { Lock01 } from '@/app/components/base/icons/src/vender/solid/security' import { LinkExternal02 } from '@/app/components/base/icons/src/vender/line/general' import { PortalToFollowElem, PortalToFollowElemContent, } from '@/app/components/base/portal-to-follow-elem' import Confirm from '@/app/components/base/confirm' import { useAppContext } from '@/context/app-context' import AuthForm from '@/app/components/base/form/form-scenarios/auth' import type { FormRefObject, FormSchema, } from '@/app/components/base/form/types' import { useModelFormSchemas } from '../model-auth/hooks' import type { Credential, CustomModel, } from '../declarations' import Loading from '@/app/components/base/loading' import { useAuth, useCredentialData, } from '@/app/components/header/account-setting/model-provider-page/model-auth/hooks' import ModelIcon from '@/app/components/header/account-setting/model-provider-page/model-icon' import Badge from '@/app/components/base/badge' import { useRenderI18nObject } from '@/hooks/use-i18n' import { CredentialSelector } from '../model-auth' type ModelModalProps = { provider: ModelProvider configurateMethod: ConfigurationMethodEnum currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields onCancel: () => void onSave: (formValues?: Record) => void onRemove: (formValues?: Record) => void model?: CustomModel credential?: Credential isModelCredential?: boolean mode?: ModelModalModeEnum } const ModelModal: FC = ({ provider, configurateMethod, currentCustomConfigurationModelFixedFields, onCancel, onSave, model, credential, isModelCredential, mode = ModelModalModeEnum.configProviderCredential, }) => { const renderI18nObject = useRenderI18nObject() const providerFormSchemaPredefined = configurateMethod === ConfigurationMethodEnum.predefinedModel const { isLoading, credentialData, } = useCredentialData(provider, providerFormSchemaPredefined, isModelCredential, credential, model) const { handleSaveCredential, handleConfirmDelete, deleteCredentialId, closeConfirmDelete, openConfirmDelete, doingAction, handleActiveCredential, } = useAuth( provider, configurateMethod, currentCustomConfigurationModelFixedFields, { isModelCredential, mode, }, ) const { credentials: formSchemasValue, available_credentials, } = credentialData as any const { isCurrentWorkspaceManager } = useAppContext() const { t } = useTranslation() const language = useLanguage() const { formSchemas, formValues, modelNameAndTypeFormSchemas, modelNameAndTypeFormValues, } = useModelFormSchemas(provider, providerFormSchemaPredefined, formSchemasValue, credential, model) const formRef1 = useRef(null) const [selectedCredential, setSelectedCredential] = useState() const formRef2 = useRef(null) const isEditMode = !!Object.keys(formValues).filter((key) => { return key !== '__model_name' && key !== '__model_type' && !!formValues[key] }).length && isCurrentWorkspaceManager const handleSave = useCallback(async () => { if (mode === ModelModalModeEnum.addCustomModelToModelList && selectedCredential && !selectedCredential?.addNewCredential) { handleActiveCredential(selectedCredential, model) onCancel() return } let modelNameAndTypeIsCheckValidated = true let modelNameAndTypeValues: Record = {} if (mode === ModelModalModeEnum.configCustomModel) { const formResult = formRef1.current?.getFormValues({ needCheckValidatedValues: true, }) || { isCheckValidated: false, values: {} } modelNameAndTypeIsCheckValidated = formResult.isCheckValidated modelNameAndTypeValues = formResult.values } if (mode === ModelModalModeEnum.configModelCredential && model) { modelNameAndTypeValues = { __model_name: model.model, __model_type: model.model_type, } } if (mode === ModelModalModeEnum.addCustomModelToModelList && selectedCredential?.addNewCredential && model) { modelNameAndTypeValues = { __model_name: model.model, __model_type: model.model_type, } } const { isCheckValidated, values, } = formRef2.current?.getFormValues({ needCheckValidatedValues: true, needTransformWhenSecretFieldIsPristine: true, }) || { isCheckValidated: false, values: {} } if (!isCheckValidated || !modelNameAndTypeIsCheckValidated) return const { __model_name, __model_type, } = modelNameAndTypeValues const { __authorization_name__, ...rest } = values if (__model_name && __model_type) { await handleSaveCredential({ credential_id: credential?.credential_id, credentials: rest, name: __authorization_name__, model: __model_name, model_type: __model_type, }) } else { await handleSaveCredential({ credential_id: credential?.credential_id, credentials: rest, name: __authorization_name__, }) } onSave(values) }, [handleSaveCredential, credential?.credential_id, model, onSave, mode, selectedCredential, handleActiveCredential]) const modalTitle = useMemo(() => { let label = t('common.modelProvider.auth.apiKeyModal.title') if (mode === ModelModalModeEnum.configCustomModel || mode === ModelModalModeEnum.addCustomModelToModelList) label = t('common.modelProvider.auth.addModel') if (mode === ModelModalModeEnum.configModelCredential) { if (credential) label = t('common.modelProvider.auth.editModelCredential') else label = t('common.modelProvider.auth.addModelCredential') } return (
{label}
) }, [t, mode, credential]) const modalDesc = useMemo(() => { if (providerFormSchemaPredefined) { return (
{t('common.modelProvider.auth.apiKeyModal.desc')}
) } return null }, [providerFormSchemaPredefined, t]) const modalModel = useMemo(() => { if (mode === ModelModalModeEnum.configCustomModel) { return (
{renderI18nObject(provider.label)}
) } if (model && (mode === ModelModalModeEnum.configModelCredential || mode === ModelModalModeEnum.addCustomModelToModelList)) { return (
{model.model}
{model.model_type}
) } return null }, [model, provider, mode, renderI18nObject]) const showCredentialLabel = useMemo(() => { if (mode === ModelModalModeEnum.configCustomModel) return true if (mode === ModelModalModeEnum.addCustomModelToModelList) return selectedCredential?.addNewCredential }, [mode, selectedCredential]) const showCredentialForm = useMemo(() => { if (mode !== ModelModalModeEnum.addCustomModelToModelList) return true return selectedCredential?.addNewCredential }, [mode, selectedCredential]) const saveButtonText = useMemo(() => { if (mode === ModelModalModeEnum.addCustomModelToModelList || mode === ModelModalModeEnum.configCustomModel) return t('common.operation.add') return t('common.operation.save') }, [mode, t]) const handleDeleteCredential = useCallback(() => { handleConfirmDelete() onCancel() }, [handleConfirmDelete]) const handleModelNameAndTypeChange = useCallback((field: string, value: any) => { const { getForm, } = formRef2.current as FormRefObject || {} if (getForm()) getForm()?.setFieldValue(field, value) }, []) const notAllowCustomCredential = provider.allow_custom_token === false useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if (event.key === 'Escape') { event.stopPropagation() onCancel() } } document.addEventListener('keydown', handleKeyDown, true) return () => { document.removeEventListener('keydown', handleKeyDown, true) } }, [onCancel]) return (
{modalTitle} {modalDesc} {modalModel}
{ mode === ModelModalModeEnum.configCustomModel && ( { return { ...formSchema, name: formSchema.variable, } }) as FormSchema[]} defaultValues={modelNameAndTypeFormValues} inputClassName='justify-start' ref={formRef1} onChange={handleModelNameAndTypeChange} /> ) } { mode === ModelModalModeEnum.addCustomModelToModelList && ( ) } { showCredentialLabel && (
{t('common.modelProvider.auth.modelCredential')}
) } { isLoading && (
) } { !isLoading && showCredentialForm && ( { return { ...formSchema, name: formSchema.variable, showRadioUI: formSchema.type === FormTypeEnum.radio, } }) as FormSchema[]} defaultValues={formValues} inputClassName='justify-start' ref={formRef2} /> ) }
{ (provider.help && (provider.help.title || provider.help.url)) ? ( !provider.help.url && e.preventDefault()} > {provider.help.title?.[language] || provider.help.url[language] || provider.help.title?.en_US || provider.help.url.en_US} ) :
}
{ isEditMode && ( ) }
{ (mode === ModelModalModeEnum.configCustomModel || mode === ModelModalModeEnum.configProviderCredential) && (
{t('common.modelProvider.encrypted.front')} PKCS1_OAEP {t('common.modelProvider.encrypted.back')}
) }
{ deleteCredentialId && ( ) }
) } export default memo(ModelModal)