| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 | 
							- import { memo, useCallback, useEffect, useMemo, useState } from 'react'
 
- import { useTranslation } from 'react-i18next'
 
- import useSWR from 'swr'
 
- import type { ModelItem, ModelLoadBalancingConfig, ModelLoadBalancingConfigEntry, ModelProvider } from '../declarations'
 
- import { FormTypeEnum } from '../declarations'
 
- import ModelIcon from '../model-icon'
 
- import ModelName from '../model-name'
 
- import { savePredefinedLoadBalancingConfig } from '../utils'
 
- import ModelLoadBalancingConfigs from './model-load-balancing-configs'
 
- import classNames from '@/utils/classnames'
 
- import Modal from '@/app/components/base/modal'
 
- import Button from '@/app/components/base/button'
 
- import { fetchModelLoadBalancingConfig } from '@/service/common'
 
- import Loading from '@/app/components/base/loading'
 
- import { useToastContext } from '@/app/components/base/toast'
 
- export type ModelLoadBalancingModalProps = {
 
-   provider: ModelProvider
 
-   model: ModelItem
 
-   open?: boolean
 
-   onClose?: () => void
 
-   onSave?: (provider: string) => void
 
- }
 
- // model balancing config modal
 
- const ModelLoadBalancingModal = ({ provider, model, open = false, onClose, onSave }: ModelLoadBalancingModalProps) => {
 
-   const { t } = useTranslation()
 
-   const { notify } = useToastContext()
 
-   const [loading, setLoading] = useState(false)
 
-   const { data, mutate } = useSWR(
 
-     `/workspaces/current/model-providers/${provider.provider}/models/credentials?model=${model.model}&model_type=${model.model_type}`,
 
-     fetchModelLoadBalancingConfig,
 
-   )
 
-   const originalConfig = data?.load_balancing
 
-   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)
 
-       setDraftConfig(originalConfig)
 
-   }, [originalConfig])
 
-   const toggleModalBalancing = useCallback((enabled: boolean) => {
 
-     if (draftConfig) {
 
-       setDraftConfig({
 
-         ...draftConfig,
 
-         enabled,
 
-       })
 
-     }
 
-   }, [draftConfig])
 
-   const extendedSecretFormSchemas = useMemo(
 
-     () => provider.provider_credential_schema.credential_form_schemas.filter(
 
-       ({ type }) => type === FormTypeEnum.secretInput,
 
-     ),
 
-     [provider.provider_credential_schema.credential_form_schemas],
 
-   )
 
-   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 savePredefinedLoadBalancingConfig(
 
-         provider.provider,
 
-         ({
 
-           ...(data?.credentials ?? {}),
 
-           __model_type: model.model_type,
 
-           __model_name: model.model,
 
-         }),
 
-         {
 
-           ...draftConfig,
 
-           enabled: Boolean(draftConfig?.enabled),
 
-           configs: draftConfig!.configs.map(encodeConfigEntrySecretValues),
 
-         },
 
-       )
 
-       if (res.result === 'success') {
 
-         notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
 
-         mutate()
 
-         onSave?.(provider.provider)
 
-         onClose?.()
 
-       }
 
-     }
 
-     finally {
 
-       setLoading(false)
 
-     }
 
-   }
 
-   return (
 
-     <Modal
 
-       isShow={Boolean(model) && open}
 
-       onClose={onClose}
 
-       className='max-w-none pt-8 px-8 w-[640px]'
 
-       title={
 
-         <div className='pb-3 font-semibold'>
 
-           <div className='h-[30px]'>{t('common.modelProvider.configLoadBalancing')}</div>
 
-           {Boolean(model) && (
 
-             <div className='flex items-center h-5'>
 
-               <ModelIcon
 
-                 className='shrink-0 mr-2'
 
-                 provider={provider}
 
-                 modelName={model!.model}
 
-               />
 
-               <ModelName
 
-                 className='grow text-sm font-normal text-gray-900'
 
-                 modelItem={model!}
 
-                 showModelType
 
-                 showMode
 
-                 showContextSize
 
-               />
 
-             </div>
 
-           )}
 
-         </div>
 
-       }
 
-     >
 
-       {!draftConfig
 
-         ? <Loading type='area' />
 
-         : (
 
-           <>
 
-             <div className='py-2'>
 
-               <div
 
-                 className={classNames(
 
-                   'min-h-16 bg-gray-50 border rounded-xl transition-colors',
 
-                   draftConfig.enabled ? 'border-gray-200 cursor-pointer' : 'border-primary-400 cursor-default',
 
-                 )}
 
-                 onClick={draftConfig.enabled ? () => toggleModalBalancing(false) : undefined}
 
-               >
 
-                 <div className='flex items-center px-[15px] py-3 gap-2 select-none'>
 
-                   <div className='grow-0 shrink-0 flex items-center justify-center w-8 h-8 bg-white border rounded-lg'>
 
-                     {Boolean(model) && (
 
-                       <ModelIcon className='shrink-0' provider={provider} modelName={model!.model} />
 
-                     )}
 
-                   </div>
 
-                   <div className='grow'>
 
-                     <div className='text-sm'>{t('common.modelProvider.providerManaged')}</div>
 
-                     <div className='text-xs text-gray-500'>{t('common.modelProvider.providerManagedDescription')}</div>
 
-                   </div>
 
-                 </div>
 
-               </div>
 
-               <ModelLoadBalancingConfigs {...{
 
-                 draftConfig,
 
-                 setDraftConfig,
 
-                 provider,
 
-                 currentCustomConfigurationModelFixedFields: {
 
-                   __model_name: model.model,
 
-                   __model_type: model.model_type,
 
-                 },
 
-                 configurationMethod: model.fetch_from,
 
-                 className: 'mt-2',
 
-               }} />
 
-             </div>
 
-             <div className='flex items-center justify-end gap-2 mt-6'>
 
-               <Button onClick={onClose}>{t('common.operation.cancel')}</Button>
 
-               <Button
 
-                 variant='primary'
 
-                 onClick={handleSave}
 
-                 disabled={
 
-                   loading
 
-                   || (draftConfig?.enabled && (draftConfig?.configs.filter(config => config.enabled).length ?? 0) < 2)
 
-                 }
 
-               >{t('common.operation.save')}</Button>
 
-             </div>
 
-           </>
 
-         )
 
-       }
 
-     </Modal >
 
-   )
 
- }
 
- export default memo(ModelLoadBalancingModal)
 
 
  |