|
@@ -11,12 +11,14 @@ import type {
|
|
|
CredentialFormSchema,
|
|
|
CredentialFormSchemaRadio,
|
|
|
CredentialFormSchemaSelect,
|
|
|
- CustomConfigrationModelFixedFields,
|
|
|
+ CustomConfigurationModelFixedFields,
|
|
|
FormValue,
|
|
|
+ ModelLoadBalancingConfig,
|
|
|
+ ModelLoadBalancingConfigEntry,
|
|
|
ModelProvider,
|
|
|
} from '../declarations'
|
|
|
import {
|
|
|
- ConfigurateMethodEnum,
|
|
|
+ ConfigurationMethodEnum,
|
|
|
CustomConfigurationStatusEnum,
|
|
|
FormTypeEnum,
|
|
|
} from '../declarations'
|
|
@@ -28,11 +30,12 @@ import {
|
|
|
} from '../utils'
|
|
|
import {
|
|
|
useLanguage,
|
|
|
- useProviderCrenditialsFormSchemasValue,
|
|
|
+ useProviderCredentialsAndLoadBalancing,
|
|
|
} from '../hooks'
|
|
|
import ProviderIcon from '../provider-icon'
|
|
|
import { useValidate } from '../../key-validator/hooks'
|
|
|
import { ValidatedStatus } from '../../key-validator/declarations'
|
|
|
+import ModelLoadBalancingConfigs from '../provider-added-card/model-load-balancing-configs'
|
|
|
import Form from './Form'
|
|
|
import Button from '@/app/components/base/button'
|
|
|
import { Lock01 } from '@/app/components/base/icons/src/vender/solid/security'
|
|
@@ -47,8 +50,8 @@ import ConfirmCommon from '@/app/components/base/confirm/common'
|
|
|
|
|
|
type ModelModalProps = {
|
|
|
provider: ModelProvider
|
|
|
- configurateMethod: ConfigurateMethodEnum
|
|
|
- currentCustomConfigrationModelFixedFields?: CustomConfigrationModelFixedFields
|
|
|
+ configurateMethod: ConfigurationMethodEnum
|
|
|
+ currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields
|
|
|
onCancel: () => void
|
|
|
onSave: () => void
|
|
|
}
|
|
@@ -56,16 +59,20 @@ type ModelModalProps = {
|
|
|
const ModelModal: FC<ModelModalProps> = ({
|
|
|
provider,
|
|
|
configurateMethod,
|
|
|
- currentCustomConfigrationModelFixedFields,
|
|
|
+ currentCustomConfigurationModelFixedFields,
|
|
|
onCancel,
|
|
|
onSave,
|
|
|
}) => {
|
|
|
- const providerFormSchemaPredefined = configurateMethod === ConfigurateMethodEnum.predefinedModel
|
|
|
- const formSchemasValue = useProviderCrenditialsFormSchemasValue(
|
|
|
+ const providerFormSchemaPredefined = configurateMethod === ConfigurationMethodEnum.predefinedModel
|
|
|
+ const {
|
|
|
+ credentials: formSchemasValue,
|
|
|
+ loadBalancing: originalConfig,
|
|
|
+ mutate,
|
|
|
+ } = useProviderCredentialsAndLoadBalancing(
|
|
|
provider.provider,
|
|
|
configurateMethod,
|
|
|
providerFormSchemaPredefined && provider.custom_configuration.status === CustomConfigurationStatusEnum.active,
|
|
|
- currentCustomConfigrationModelFixedFields,
|
|
|
+ currentCustomConfigurationModelFixedFields,
|
|
|
)
|
|
|
const isEditMode = !!formSchemasValue
|
|
|
const { t } = useTranslation()
|
|
@@ -73,13 +80,29 @@ const ModelModal: FC<ModelModalProps> = ({
|
|
|
const language = useLanguage()
|
|
|
const [loading, setLoading] = useState(false)
|
|
|
const [showConfirm, setShowConfirm] = useState(false)
|
|
|
+
|
|
|
+ const [draftConfig, setDraftConfig] = useState<ModelLoadBalancingConfig>()
|
|
|
+ const originalConfigMap = useMemo(() => {
|
|
|
+ if (!originalConfig)
|
|
|
+ return {}
|
|
|
+ return originalConfig?.configs.reduce((prev, config) => {
|
|
|
+ if (config.id)
|
|
|
+ prev[config.id] = config
|
|
|
+ return prev
|
|
|
+ }, {} as Record<string, ModelLoadBalancingConfigEntry>)
|
|
|
+ }, [originalConfig])
|
|
|
+ useEffect(() => {
|
|
|
+ if (originalConfig && !draftConfig)
|
|
|
+ setDraftConfig(originalConfig)
|
|
|
+ }, [draftConfig, originalConfig])
|
|
|
+
|
|
|
const formSchemas = useMemo(() => {
|
|
|
return providerFormSchemaPredefined
|
|
|
? provider.provider_credential_schema.credential_form_schemas
|
|
|
: [
|
|
|
genModelTypeFormSchema(provider.supported_model_types),
|
|
|
genModelNameFormSchema(provider.model_credential_schema?.model),
|
|
|
- ...provider.model_credential_schema.credential_form_schemas,
|
|
|
+ ...(draftConfig?.enabled ? [] : provider.model_credential_schema.credential_form_schemas),
|
|
|
]
|
|
|
}, [
|
|
|
providerFormSchemaPredefined,
|
|
@@ -87,15 +110,14 @@ const ModelModal: FC<ModelModalProps> = ({
|
|
|
provider.supported_model_types,
|
|
|
provider.model_credential_schema?.credential_form_schemas,
|
|
|
provider.model_credential_schema?.model,
|
|
|
+ draftConfig?.enabled,
|
|
|
])
|
|
|
const [
|
|
|
requiredFormSchemas,
|
|
|
- secretFormSchemas,
|
|
|
defaultFormSchemaValue,
|
|
|
showOnVariableMap,
|
|
|
] = useMemo(() => {
|
|
|
const requiredFormSchemas: CredentialFormSchema[] = []
|
|
|
- const secretFormSchemas: CredentialFormSchema[] = []
|
|
|
const defaultFormSchemaValue: Record<string, string | number> = {}
|
|
|
const showOnVariableMap: Record<string, string[]> = {}
|
|
|
|
|
@@ -103,9 +125,6 @@ const ModelModal: FC<ModelModalProps> = ({
|
|
|
if (formSchema.required)
|
|
|
requiredFormSchemas.push(formSchema)
|
|
|
|
|
|
- if (formSchema.type === FormTypeEnum.secretInput)
|
|
|
- secretFormSchemas.push(formSchema)
|
|
|
-
|
|
|
if (formSchema.default)
|
|
|
defaultFormSchemaValue[formSchema.variable] = formSchema.default
|
|
|
|
|
@@ -136,22 +155,21 @@ const ModelModal: FC<ModelModalProps> = ({
|
|
|
|
|
|
return [
|
|
|
requiredFormSchemas,
|
|
|
- secretFormSchemas,
|
|
|
defaultFormSchemaValue,
|
|
|
showOnVariableMap,
|
|
|
]
|
|
|
}, [formSchemas])
|
|
|
- const initialFormSchemasValue = useMemo(() => {
|
|
|
+ const initialFormSchemasValue: Record<string, string | number> = useMemo(() => {
|
|
|
return {
|
|
|
...defaultFormSchemaValue,
|
|
|
...formSchemasValue,
|
|
|
- }
|
|
|
+ } as unknown as Record<string, string | number>
|
|
|
}, [formSchemasValue, defaultFormSchemaValue])
|
|
|
const [value, setValue] = useState(initialFormSchemasValue)
|
|
|
useEffect(() => {
|
|
|
setValue(initialFormSchemasValue)
|
|
|
}, [initialFormSchemasValue])
|
|
|
- const [validate, validating, validatedStatusState] = useValidate(value)
|
|
|
+ const [_, validating, validatedStatusState] = useValidate(value)
|
|
|
const filteredRequiredFormSchemas = requiredFormSchemas.filter((requiredFormSchema) => {
|
|
|
if (requiredFormSchema.show_on.length && requiredFormSchema.show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value))
|
|
|
return true
|
|
@@ -161,32 +179,63 @@ const ModelModal: FC<ModelModalProps> = ({
|
|
|
|
|
|
return false
|
|
|
})
|
|
|
- const getSecretValues = useCallback((v: FormValue) => {
|
|
|
- return secretFormSchemas.reduce((prev, next) => {
|
|
|
- if (v[next.variable] === initialFormSchemasValue[next.variable])
|
|
|
- prev[next.variable] = '[__HIDDEN__]'
|
|
|
-
|
|
|
- return prev
|
|
|
- }, {} as Record<string, string>)
|
|
|
- }, [initialFormSchemasValue, secretFormSchemas])
|
|
|
|
|
|
const handleValueChange = (v: FormValue) => {
|
|
|
setValue(v)
|
|
|
}
|
|
|
+
|
|
|
+ const extendedSecretFormSchemas = useMemo(
|
|
|
+ () =>
|
|
|
+ (providerFormSchemaPredefined
|
|
|
+ ? provider.provider_credential_schema.credential_form_schemas
|
|
|
+ : [
|
|
|
+ genModelTypeFormSchema(provider.supported_model_types),
|
|
|
+ genModelNameFormSchema(provider.model_credential_schema?.model),
|
|
|
+ ...provider.model_credential_schema.credential_form_schemas,
|
|
|
+ ]).filter(({ type }) => type === FormTypeEnum.secretInput),
|
|
|
+ [
|
|
|
+ provider.model_credential_schema?.credential_form_schemas,
|
|
|
+ provider.model_credential_schema?.model,
|
|
|
+ provider.provider_credential_schema?.credential_form_schemas,
|
|
|
+ provider.supported_model_types,
|
|
|
+ providerFormSchemaPredefined,
|
|
|
+ ],
|
|
|
+ )
|
|
|
+
|
|
|
+ const encodeSecretValues = useCallback((v: FormValue) => {
|
|
|
+ const result = { ...v }
|
|
|
+ extendedSecretFormSchemas.forEach(({ variable }) => {
|
|
|
+ if (result[variable] === formSchemasValue?.[variable])
|
|
|
+ result[variable] = '[__HIDDEN__]'
|
|
|
+ })
|
|
|
+ return result
|
|
|
+ }, [extendedSecretFormSchemas, formSchemasValue])
|
|
|
+
|
|
|
+ const encodeConfigEntrySecretValues = useCallback((entry: ModelLoadBalancingConfigEntry) => {
|
|
|
+ const result = { ...entry }
|
|
|
+ extendedSecretFormSchemas.forEach(({ variable }) => {
|
|
|
+ if (entry.id && result.credentials[variable] === originalConfigMap[entry.id]?.credentials?.[variable])
|
|
|
+ result.credentials[variable] = '[__HIDDEN__]'
|
|
|
+ })
|
|
|
+ return result
|
|
|
+ }, [extendedSecretFormSchemas, originalConfigMap])
|
|
|
+
|
|
|
const handleSave = async () => {
|
|
|
try {
|
|
|
setLoading(true)
|
|
|
-
|
|
|
const res = await saveCredentials(
|
|
|
providerFormSchemaPredefined,
|
|
|
provider.provider,
|
|
|
+ encodeSecretValues(value),
|
|
|
{
|
|
|
- ...value,
|
|
|
- ...getSecretValues(value),
|
|
|
+ ...draftConfig,
|
|
|
+ enabled: Boolean(draftConfig?.enabled),
|
|
|
+ configs: draftConfig?.configs.map(encodeConfigEntrySecretValues) || [],
|
|
|
},
|
|
|
)
|
|
|
if (res.result === 'success') {
|
|
|
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
|
|
|
+ mutate()
|
|
|
onSave()
|
|
|
onCancel()
|
|
|
}
|
|
@@ -207,6 +256,7 @@ const ModelModal: FC<ModelModalProps> = ({
|
|
|
)
|
|
|
if (res.result === 'success') {
|
|
|
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
|
|
|
+ mutate()
|
|
|
onSave()
|
|
|
onCancel()
|
|
|
}
|
|
@@ -217,7 +267,7 @@ const ModelModal: FC<ModelModalProps> = ({
|
|
|
}
|
|
|
|
|
|
const renderTitlePrefix = () => {
|
|
|
- const prefix = configurateMethod === ConfigurateMethodEnum.customizableModel ? t('common.operation.add') : t('common.operation.setup')
|
|
|
+ const prefix = configurateMethod === ConfigurationMethodEnum.customizableModel ? t('common.operation.add') : t('common.operation.setup')
|
|
|
|
|
|
return `${prefix} ${provider.label[language] || provider.label.en_US}`
|
|
|
}
|
|
@@ -232,6 +282,7 @@ const ModelModal: FC<ModelModalProps> = ({
|
|
|
<div className='text-xl font-semibold text-gray-900'>{renderTitlePrefix()}</div>
|
|
|
<ProviderIcon provider={provider} />
|
|
|
</div>
|
|
|
+
|
|
|
<Form
|
|
|
value={value}
|
|
|
onChange={handleValueChange}
|
|
@@ -241,7 +292,17 @@ const ModelModal: FC<ModelModalProps> = ({
|
|
|
showOnVariableMap={showOnVariableMap}
|
|
|
isEditMode={isEditMode}
|
|
|
/>
|
|
|
- <div className='sticky bottom-0 flex justify-between items-center py-6 flex-wrap gap-y-2 bg-white'>
|
|
|
+
|
|
|
+ <div className='mt-1 mb-4 border-t-[0.5px] border-t-gray-100' />
|
|
|
+ <ModelLoadBalancingConfigs withSwitch {...{
|
|
|
+ draftConfig,
|
|
|
+ setDraftConfig,
|
|
|
+ provider,
|
|
|
+ currentCustomConfigurationModelFixedFields,
|
|
|
+ configurationMethod: configurateMethod,
|
|
|
+ }} />
|
|
|
+
|
|
|
+ <div className='sticky bottom-0 flex justify-between items-center mt-2 -mx-2 pt-4 px-2 pb-6 flex-wrap gap-y-2 bg-white z-10'>
|
|
|
{
|
|
|
(provider.help && (provider.help.title || provider.help.url))
|
|
|
? (
|
|
@@ -278,7 +339,11 @@ const ModelModal: FC<ModelModalProps> = ({
|
|
|
className='h-9 text-sm font-medium'
|
|
|
type='primary'
|
|
|
onClick={handleSave}
|
|
|
- disabled={loading || filteredRequiredFormSchemas.some(item => value[item.variable] === undefined)}
|
|
|
+ disabled={
|
|
|
+ loading
|
|
|
+ || filteredRequiredFormSchemas.some(item => value[item.variable] === undefined)
|
|
|
+ || (draftConfig?.enabled && (draftConfig?.configs.filter(config => config.enabled).length ?? 0) < 2)
|
|
|
+ }
|
|
|
>
|
|
|
{t('common.operation.save')}
|
|
|
</Button>
|