mirror of https://github.com/langgenius/dify.git
model auth
This commit is contained in:
parent
3f57e4a643
commit
2e28a64d38
|
|
@ -186,6 +186,22 @@ export type Credential = {
|
|||
credential_name: string
|
||||
}
|
||||
|
||||
export type CustomModel = {
|
||||
model: string
|
||||
model_type: ModelTypeEnum
|
||||
}
|
||||
|
||||
export type CustomModelCredential = CustomModel & {
|
||||
credentials?: Record<string, any>
|
||||
available_model_credentials?: Credential[]
|
||||
current_credential_id?: string
|
||||
}
|
||||
|
||||
export type CredentialWithModel = Credential & {
|
||||
model: string
|
||||
model_type: ModelTypeEnum
|
||||
}
|
||||
|
||||
export type ModelProvider = {
|
||||
provider: string
|
||||
label: TypeWithI18N
|
||||
|
|
@ -215,6 +231,7 @@ export type ModelProvider = {
|
|||
current_credential_id?: string
|
||||
current_credential_name?: string
|
||||
available_credentials?: Credential[]
|
||||
custom_models?: CustomModelCredential[]
|
||||
}
|
||||
system_configuration: {
|
||||
enabled: boolean
|
||||
|
|
@ -280,9 +297,22 @@ export type ModelLoadBalancingConfigEntry = {
|
|||
in_cooldown?: boolean
|
||||
/** cooldown time (in seconds) */
|
||||
ttl?: number
|
||||
credential_id?: string
|
||||
}
|
||||
|
||||
export type ModelLoadBalancingConfig = {
|
||||
enabled: boolean
|
||||
configs: ModelLoadBalancingConfigEntry[]
|
||||
}
|
||||
|
||||
export type ProviderCredential = {
|
||||
credentials: Record<string, any>
|
||||
name: string
|
||||
credential_id: string
|
||||
}
|
||||
|
||||
export type ModelCredential = {
|
||||
credentials: Record<string, any>
|
||||
load_balancing: ModelLoadBalancingConfig
|
||||
available_credentials: Credential[]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { useContext } from 'use-context-selector'
|
|||
import type {
|
||||
Credential,
|
||||
CustomConfigurationModelFixedFields,
|
||||
CustomModel,
|
||||
DefaultModel,
|
||||
DefaultModelResponse,
|
||||
Model,
|
||||
|
|
@ -354,6 +355,7 @@ export const useModelModalHandler = () => {
|
|||
configurationMethod: ConfigurationMethodEnum,
|
||||
CustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields,
|
||||
credential?: Credential,
|
||||
model?: CustomModel,
|
||||
) => {
|
||||
setShowModelModal({
|
||||
payload: {
|
||||
|
|
@ -361,6 +363,7 @@ export const useModelModalHandler = () => {
|
|||
currentConfigurationMethod: configurationMethod,
|
||||
currentCustomConfigurationModelFixedFields: CustomConfigurationModelFixedFields,
|
||||
credential,
|
||||
model,
|
||||
},
|
||||
onSaveCallback: () => {
|
||||
handleRefreshModel(provider, configurationMethod, CustomConfigurationModelFixedFields)
|
||||
|
|
|
|||
|
|
@ -3,13 +3,21 @@ import {
|
|||
useCallback,
|
||||
} from 'react'
|
||||
import { RiAddLine } from '@remixicon/react'
|
||||
import {
|
||||
AuthCategory,
|
||||
Authorized,
|
||||
} from '@/app/components/plugins/plugin-auth'
|
||||
import { Authorized } from '@/app/components/header/account-setting/model-provider-page/model-auth'
|
||||
import cn from '@/utils/classnames'
|
||||
import type {
|
||||
Credential,
|
||||
ModelProvider,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
|
||||
const AddCredentialInLoadBalancing = () => {
|
||||
type AddCredentialInLoadBalancingProps = {
|
||||
provider: ModelProvider
|
||||
onSetup: (credential?: Credential) => void
|
||||
}
|
||||
const AddCredentialInLoadBalancing = ({
|
||||
provider,
|
||||
onSetup,
|
||||
}: AddCredentialInLoadBalancingProps) => {
|
||||
const renderTrigger = useCallback((open?: boolean) => {
|
||||
return (
|
||||
<div className={cn(
|
||||
|
|
@ -25,13 +33,9 @@ const AddCredentialInLoadBalancing = () => {
|
|||
return (
|
||||
<Authorized
|
||||
credentials={[]}
|
||||
pluginPayload={{
|
||||
provider: '',
|
||||
category: AuthCategory.model,
|
||||
}}
|
||||
canApiKey
|
||||
offset={4}
|
||||
provider={provider.provider}
|
||||
renderTrigger={renderTrigger}
|
||||
onSetup={onSetup}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
import {
|
||||
memo,
|
||||
useCallback,
|
||||
useMemo,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
RiAddCircleFill,
|
||||
} from '@remixicon/react'
|
||||
import {
|
||||
Button,
|
||||
} from '@/app/components/base/button'
|
||||
import type {
|
||||
CustomConfigurationModelFixedFields,
|
||||
CustomModelCredential,
|
||||
ModelProvider,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import { ConfigurationMethodEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import Authorized from './authorized'
|
||||
import { useAuth } from './hooks'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type AddCustomModelProps = {
|
||||
provider: ModelProvider,
|
||||
configurationMethod: ConfigurationMethodEnum,
|
||||
currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields,
|
||||
models: CustomModelCredential[]
|
||||
}
|
||||
const AddCustomModel = ({
|
||||
provider,
|
||||
configurationMethod,
|
||||
currentCustomConfigurationModelFixedFields,
|
||||
models,
|
||||
}: AddCustomModelProps) => {
|
||||
const { t } = useTranslation()
|
||||
const noModels = !models.length
|
||||
const {
|
||||
handleOpenModal,
|
||||
} = useAuth(provider, configurationMethod, currentCustomConfigurationModelFixedFields)
|
||||
const handleClick = useCallback(() => {
|
||||
if (noModels)
|
||||
handleOpenModal()
|
||||
}, [handleOpenModal, noModels])
|
||||
const ButtonComponent = useMemo(() => {
|
||||
return (
|
||||
<Button
|
||||
variant='ghost-accent'
|
||||
size='small'
|
||||
onClick={handleClick}
|
||||
className={cn(noModels && 'text-text-accent')}
|
||||
>
|
||||
<RiAddCircleFill className='mr-1 h-3.5 w-3.5' />
|
||||
{t('common.modelProvider.addModel')}
|
||||
</Button>
|
||||
)
|
||||
}, [handleClick, noModels])
|
||||
|
||||
const renderTrigger = useCallback(() => {
|
||||
return ButtonComponent
|
||||
}, [ButtonComponent])
|
||||
|
||||
if (noModels)
|
||||
return ButtonComponent
|
||||
|
||||
return (
|
||||
<Authorized
|
||||
provider={provider}
|
||||
configurationMethod={ConfigurationMethodEnum.customizableModel}
|
||||
items={models.map(model => ({
|
||||
model,
|
||||
credentials: model.available_model_credentials ?? [],
|
||||
}))}
|
||||
renderTrigger={renderTrigger}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(AddCustomModel)
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
import {
|
||||
memo,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
RiAddCircleFill,
|
||||
RiAddLine,
|
||||
} from '@remixicon/react'
|
||||
import {
|
||||
PortalToFollowElem,
|
||||
PortalToFollowElemContent,
|
||||
PortalToFollowElemTrigger,
|
||||
} from '@/app/components/base/portal-to-follow-elem'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
|
||||
const AddModel = () => {
|
||||
const { t } = useTranslation()
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
return (
|
||||
<PortalToFollowElem
|
||||
placement='bottom-end'
|
||||
offset={{
|
||||
mainAxis: 4,
|
||||
crossAxis: -4,
|
||||
}}
|
||||
open={open}
|
||||
onOpenChange={setOpen}
|
||||
>
|
||||
<PortalToFollowElemTrigger>
|
||||
<Button
|
||||
variant='ghost-accent'
|
||||
size='small'
|
||||
>
|
||||
<RiAddCircleFill className='mr-1 h-3.5 w-3.5' />
|
||||
{t('common.modelProvider.addModel')}
|
||||
</Button>
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent>
|
||||
<div className='w-[360px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg'>
|
||||
<div className='p-1'>
|
||||
<div className='flex h-9 items-center'>
|
||||
<div className='h-5 w-5 shrink-0'></div>
|
||||
<div
|
||||
className='system-md-medium mx-1 truncate text-text-primary'
|
||||
title='chat-finetune-01'
|
||||
>
|
||||
chat-finetune-01
|
||||
</div>
|
||||
<Tooltip
|
||||
asChild
|
||||
popupContent='Add model credential'
|
||||
>
|
||||
<Button
|
||||
className='h-6 w-6 rounded-full p-0'
|
||||
size='small'
|
||||
variant='secondary-accent'
|
||||
>
|
||||
<RiAddLine className='h-4 w-4' />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div className='system-xs-medium flex h-10 cursor-pointer items-center border-t border-divider-subtle px-4 text-text-accent-light-mode-only'>
|
||||
<RiAddLine className='mr-1 h-4 w-4' />
|
||||
{t('common.modelProvider.addModel')}
|
||||
</div>
|
||||
</div>
|
||||
</PortalToFollowElemContent>
|
||||
</PortalToFollowElem>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(AddModel)
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
import {
|
||||
memo,
|
||||
useCallback,
|
||||
} from 'react'
|
||||
import { RiAddLine } from '@remixicon/react'
|
||||
import CredentialItem from './credential-item'
|
||||
import type {
|
||||
Credential,
|
||||
CustomModel,
|
||||
} from '../../declarations'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
|
||||
type AuthorizedItemProps = {
|
||||
model?: CustomModel
|
||||
disabled?: boolean
|
||||
onDelete?: (id: string) => void
|
||||
onEdit?: (model?: CustomModel, credential?: Credential) => void
|
||||
onSetDefault?: (id: string) => void
|
||||
onItemClick?: (id: string) => void
|
||||
showItemSelectedIcon?: boolean
|
||||
selectedCredentialId?: string
|
||||
disableSetDefault?: boolean
|
||||
credentials: Credential[]
|
||||
}
|
||||
export const AuthorizedItem = ({
|
||||
model,
|
||||
credentials,
|
||||
disabled,
|
||||
onDelete,
|
||||
onEdit,
|
||||
onSetDefault,
|
||||
onItemClick,
|
||||
showItemSelectedIcon,
|
||||
selectedCredentialId,
|
||||
disableSetDefault,
|
||||
}: AuthorizedItemProps) => {
|
||||
const handleEdit = useCallback((credential?: Credential) => {
|
||||
onEdit?.(model, credential)
|
||||
}, [onEdit, model])
|
||||
return (
|
||||
<div className='p-1'>
|
||||
{
|
||||
model && (
|
||||
<div
|
||||
className='flex h-9 items-center'
|
||||
>
|
||||
<div className='h-5 w-5 shrink-0'></div>
|
||||
<div
|
||||
className='system-md-medium mx-1 truncate text-text-primary'
|
||||
title={model.model}
|
||||
>
|
||||
{model.model}
|
||||
</div>
|
||||
<Tooltip
|
||||
asChild
|
||||
popupContent='Add model credential'
|
||||
>
|
||||
<Button
|
||||
className='h-6 w-6 rounded-full p-0'
|
||||
size='small'
|
||||
variant='secondary-accent'
|
||||
>
|
||||
<RiAddLine className='h-4 w-4' />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
credentials.map(credential => (
|
||||
<CredentialItem
|
||||
key={credential.credential_id}
|
||||
credential={credential}
|
||||
disabled={disabled}
|
||||
onDelete={onDelete}
|
||||
onEdit={handleEdit}
|
||||
onSetDefault={onSetDefault}
|
||||
onItemClick={onItemClick}
|
||||
showSelectedIcon={showItemSelectedIcon}
|
||||
selectedCredentialId={selectedCredentialId}
|
||||
disableSetDefault={disableSetDefault}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(AuthorizedItem)
|
||||
|
|
@ -15,11 +15,11 @@ import cn from '@/utils/classnames'
|
|||
import type { Credential } from '../../declarations'
|
||||
import Button from '@/app/components/base/button'
|
||||
|
||||
type ItemProps = {
|
||||
type CredentialItemProps = {
|
||||
credential: Credential
|
||||
disabled?: boolean
|
||||
onDelete?: (id: string) => void
|
||||
onEdit?: (credential: Credential) => void
|
||||
onEdit?: (credential?: Credential) => void
|
||||
onSetDefault?: (id: string) => void
|
||||
disableRename?: boolean
|
||||
disableEdit?: boolean
|
||||
|
|
@ -29,7 +29,7 @@ type ItemProps = {
|
|||
showSelectedIcon?: boolean
|
||||
selectedCredentialId?: string
|
||||
}
|
||||
const Item = ({
|
||||
const CredentialItem = ({
|
||||
credential,
|
||||
disabled,
|
||||
onDelete,
|
||||
|
|
@ -42,7 +42,7 @@ const Item = ({
|
|||
onItemClick,
|
||||
showSelectedIcon,
|
||||
selectedCredentialId,
|
||||
}: ItemProps) => {
|
||||
}: CredentialItemProps) => {
|
||||
const { t } = useTranslation()
|
||||
const showAction = useMemo(() => {
|
||||
return !(disableRename && disableEdit && disableDelete && disableSetDefault)
|
||||
|
|
@ -131,4 +131,4 @@ const Item = ({
|
|||
)
|
||||
}
|
||||
|
||||
export default memo(Item)
|
||||
export default memo(CredentialItem)
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
import {
|
||||
memo,
|
||||
useCallback,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import {
|
||||
|
|
@ -19,17 +18,25 @@ import type {
|
|||
import Button from '@/app/components/base/button'
|
||||
import cn from '@/utils/classnames'
|
||||
import Confirm from '@/app/components/base/confirm'
|
||||
import Item from './item'
|
||||
import { useToastContext } from '@/app/components/base/toast'
|
||||
import type { Credential } from '../../declarations'
|
||||
import {
|
||||
useDeleteModelCredential,
|
||||
useSetModelCredentialDefault,
|
||||
} from '@/service/use-models'
|
||||
import type {
|
||||
ConfigurationMethodEnum,
|
||||
Credential,
|
||||
CustomConfigurationModelFixedFields,
|
||||
CustomModel,
|
||||
ModelProvider,
|
||||
} from '../../declarations'
|
||||
import { useAuth } from '../hooks'
|
||||
import AuthorizedItem from './authorized-item'
|
||||
|
||||
type AuthorizedProps = {
|
||||
provider: string
|
||||
credentials: Credential[]
|
||||
provider: ModelProvider,
|
||||
configurationMethod: ConfigurationMethodEnum,
|
||||
currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields,
|
||||
items: {
|
||||
model?: CustomModel
|
||||
credentials: Credential[]
|
||||
}[]
|
||||
selectedCredential?: Credential
|
||||
disabled?: boolean
|
||||
renderTrigger?: (open?: boolean) => React.ReactNode
|
||||
isOpen?: boolean
|
||||
|
|
@ -40,13 +47,15 @@ type AuthorizedProps = {
|
|||
popupClassName?: string
|
||||
onItemClick?: (id: string) => void
|
||||
showItemSelectedIcon?: boolean
|
||||
selectedCredentialId?: string
|
||||
onUpdate?: () => void
|
||||
onSetup: (credential?: Credential) => void
|
||||
disableSetDefault?: boolean
|
||||
}
|
||||
const Authorized = ({
|
||||
provider,
|
||||
credentials,
|
||||
configurationMethod,
|
||||
currentCustomConfigurationModelFixedFields,
|
||||
items,
|
||||
selectedCredential,
|
||||
disabled,
|
||||
renderTrigger,
|
||||
isOpen,
|
||||
|
|
@ -57,12 +66,10 @@ const Authorized = ({
|
|||
popupClassName,
|
||||
onItemClick,
|
||||
showItemSelectedIcon,
|
||||
selectedCredentialId,
|
||||
onUpdate,
|
||||
onSetup,
|
||||
disableSetDefault,
|
||||
}: AuthorizedProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { notify } = useToastContext()
|
||||
const [isLocalOpen, setIsLocalOpen] = useState(false)
|
||||
const mergedIsOpen = isOpen ?? isLocalOpen
|
||||
const setMergedIsOpen = useCallback((open: boolean) => {
|
||||
|
|
@ -71,68 +78,20 @@ const Authorized = ({
|
|||
|
||||
setIsLocalOpen(open)
|
||||
}, [onOpenChange])
|
||||
const pendingOperationCredentialId = useRef<string | null>(null)
|
||||
const [deleteCredentialId, setDeleteCredentialId] = useState<string | null>(null)
|
||||
const openConfirm = useCallback((credentialId?: string) => {
|
||||
if (credentialId)
|
||||
pendingOperationCredentialId.current = credentialId
|
||||
const {
|
||||
openConfirmDelete,
|
||||
closeConfirmDelete,
|
||||
doingAction,
|
||||
handleActiveCredential,
|
||||
handleConfirmDelete,
|
||||
deleteCredentialId,
|
||||
handleOpenModal,
|
||||
} = useAuth(provider, configurationMethod, currentCustomConfigurationModelFixedFields, onUpdate)
|
||||
|
||||
setDeleteCredentialId(pendingOperationCredentialId.current)
|
||||
}, [])
|
||||
const closeConfirm = useCallback(() => {
|
||||
setDeleteCredentialId(null)
|
||||
pendingOperationCredentialId.current = null
|
||||
}, [])
|
||||
const [doingAction, setDoingAction] = useState(false)
|
||||
const doingActionRef = useRef(doingAction)
|
||||
const handleSetDoingAction = useCallback((doing: boolean) => {
|
||||
doingActionRef.current = doing
|
||||
setDoingAction(doing)
|
||||
}, [])
|
||||
const { mutateAsync: deleteModelCredential } = useDeleteModelCredential(provider)
|
||||
const { mutateAsync: setModelCredentialDefault } = useSetModelCredentialDefault(provider)
|
||||
const handleSetDefault = useCallback(async (id: string) => {
|
||||
if (doingActionRef.current)
|
||||
return
|
||||
try {
|
||||
handleSetDoingAction(true)
|
||||
await setModelCredentialDefault(id)
|
||||
notify({
|
||||
type: 'success',
|
||||
message: t('common.api.actionSuccess'),
|
||||
})
|
||||
onUpdate?.()
|
||||
}
|
||||
finally {
|
||||
handleSetDoingAction(false)
|
||||
}
|
||||
}, [setModelCredentialDefault, onUpdate, notify, t, handleSetDoingAction])
|
||||
const handleConfirm = useCallback(async () => {
|
||||
if (doingActionRef.current)
|
||||
return
|
||||
if (!pendingOperationCredentialId.current) {
|
||||
setDeleteCredentialId(null)
|
||||
return
|
||||
}
|
||||
try {
|
||||
handleSetDoingAction(true)
|
||||
await deleteModelCredential(pendingOperationCredentialId.current)
|
||||
notify({
|
||||
type: 'success',
|
||||
message: t('common.api.actionSuccess'),
|
||||
})
|
||||
onUpdate?.()
|
||||
setDeleteCredentialId(null)
|
||||
pendingOperationCredentialId.current = null
|
||||
}
|
||||
finally {
|
||||
handleSetDoingAction(false)
|
||||
}
|
||||
}, [onUpdate, notify, t, handleSetDoingAction])
|
||||
const handleOpenSetup = useCallback((credential?: Credential) => {
|
||||
onSetup(credential)
|
||||
const handleEdit = useCallback((model?: CustomModel, credential?: Credential) => {
|
||||
handleOpenModal(model, credential)
|
||||
setMergedIsOpen(false)
|
||||
}, [onSetup, setMergedIsOpen])
|
||||
}, [handleOpenModal, setMergedIsOpen])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -166,39 +125,29 @@ const Authorized = ({
|
|||
'w-[360px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg',
|
||||
popupClassName,
|
||||
)}>
|
||||
<div className='max-h-[304px] overflow-y-auto py-1'>
|
||||
<div className='max-h-[304px] overflow-y-auto'>
|
||||
{
|
||||
!!credentials.length && (
|
||||
<div className='p-1'>
|
||||
<div className={cn(
|
||||
'system-xs-medium px-3 pb-0.5 pt-1 text-text-tertiary',
|
||||
showItemSelectedIcon && 'pl-7',
|
||||
)}>
|
||||
API Keys
|
||||
</div>
|
||||
{
|
||||
credentials.map(credential => (
|
||||
<Item
|
||||
key={credential.credential_id}
|
||||
credential={credential}
|
||||
disabled={disabled}
|
||||
onDelete={openConfirm}
|
||||
onEdit={handleOpenSetup}
|
||||
onSetDefault={handleSetDefault}
|
||||
onItemClick={onItemClick}
|
||||
showSelectedIcon={showItemSelectedIcon}
|
||||
selectedCredentialId={selectedCredentialId}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
)
|
||||
items.map((item, index) => (
|
||||
<AuthorizedItem
|
||||
key={index}
|
||||
model={item.model}
|
||||
credentials={item.credentials}
|
||||
disabled={disabled}
|
||||
onDelete={openConfirmDelete}
|
||||
onEdit={handleEdit}
|
||||
onSetDefault={handleActiveCredential}
|
||||
onItemClick={onItemClick}
|
||||
showItemSelectedIcon={showItemSelectedIcon}
|
||||
selectedCredentialId={selectedCredential?.credential_id}
|
||||
disableSetDefault={disableSetDefault}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<div className='h-[1px] bg-divider-subtle'></div>
|
||||
<div className='p-2'>
|
||||
<Button
|
||||
onClick={() => handleOpenSetup()}
|
||||
onClick={() => handleOpenModal()}
|
||||
className='w-full'
|
||||
>
|
||||
add api key
|
||||
|
|
@ -211,10 +160,10 @@ const Authorized = ({
|
|||
deleteCredentialId && (
|
||||
<Confirm
|
||||
isShow
|
||||
title={t('datasetDocuments.list.delete.title')}
|
||||
title={t('common.modelProvider.confirmDelete')}
|
||||
isDisabled={doingAction}
|
||||
onCancel={closeConfirm}
|
||||
onConfirm={handleConfirm}
|
||||
onCancel={closeConfirmDelete}
|
||||
onConfirm={handleConfirmDelete}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
import {
|
||||
memo,
|
||||
useCallback,
|
||||
useMemo,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
RiEqualizer2Line,
|
||||
} from '@remixicon/react'
|
||||
import {
|
||||
Button,
|
||||
} from '@/app/components/base/button'
|
||||
import type {
|
||||
CustomConfigurationModelFixedFields,
|
||||
ModelProvider,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import { ConfigurationMethodEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import Authorized from './authorized'
|
||||
import { useAuth, useCredentialStatus } from './hooks'
|
||||
|
||||
type ConfigProviderProps = {
|
||||
provider: ModelProvider,
|
||||
configurationMethod: ConfigurationMethodEnum,
|
||||
currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields,
|
||||
}
|
||||
const ConfigProvider = ({
|
||||
provider,
|
||||
configurationMethod,
|
||||
currentCustomConfigurationModelFixedFields,
|
||||
}: ConfigProviderProps) => {
|
||||
const { t } = useTranslation()
|
||||
const {
|
||||
handleOpenModal,
|
||||
} = useAuth(provider, configurationMethod, currentCustomConfigurationModelFixedFields)
|
||||
const {
|
||||
hasCredential,
|
||||
authorized,
|
||||
current_credential_id,
|
||||
current_credential_name,
|
||||
available_credentials,
|
||||
} = useCredentialStatus(provider)
|
||||
const handleClick = useCallback(() => {
|
||||
if (!hasCredential)
|
||||
handleOpenModal()
|
||||
}, [handleOpenModal, hasCredential])
|
||||
|
||||
const ButtonComponent = useMemo(() => {
|
||||
return (
|
||||
<Button
|
||||
className='grow'
|
||||
size='small'
|
||||
onClick={handleClick}
|
||||
variant={!authorized ? 'secondary-accent' : 'secondary'}
|
||||
>
|
||||
<RiEqualizer2Line className='mr-1 h-3.5 w-3.5' />
|
||||
{t('common.operation.setup')}
|
||||
</Button>
|
||||
)
|
||||
}, [handleClick, authorized])
|
||||
|
||||
if (!hasCredential)
|
||||
return ButtonComponent
|
||||
|
||||
return (
|
||||
<Authorized
|
||||
provider={provider}
|
||||
configurationMethod={ConfigurationMethodEnum.predefinedModel}
|
||||
items={[
|
||||
{
|
||||
credentials: available_credentials ?? [],
|
||||
},
|
||||
]}
|
||||
selectedCredential={{
|
||||
credential_id: current_credential_id ?? '',
|
||||
credential_name: current_credential_name ?? '',
|
||||
}}
|
||||
showItemSelectedIcon
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(ConfigProvider)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
export * from './use-model-form-schemas'
|
||||
export * from './use-credential-status'
|
||||
export * from './use-custom-models'
|
||||
export * from './use-auth'
|
||||
export * from './use-auth-service'
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
import { useCallback } from 'react'
|
||||
import {
|
||||
useActiveModelCredential,
|
||||
useActiveProviderCredential,
|
||||
useAddModelCredential,
|
||||
useAddProviderCredential,
|
||||
useDeleteModelCredential,
|
||||
useDeleteProviderCredential,
|
||||
useEditModelCredential,
|
||||
useEditProviderCredential,
|
||||
useGetModelCredential,
|
||||
useGetProviderCredential,
|
||||
} from '@/service/use-models'
|
||||
import type {
|
||||
CustomModel,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
|
||||
export const useGetCredential = (provider: string, credentialId?: string, model?: CustomModel, configFrom?: string) => {
|
||||
const providerData = useGetProviderCredential(!model && !!credentialId, provider, credentialId)
|
||||
const modelData = useGetModelCredential(!!model && !!credentialId, provider, credentialId, model?.model, model?.model_type, configFrom)
|
||||
return model ? modelData : providerData
|
||||
}
|
||||
|
||||
export const useAuthService = (provider: string) => {
|
||||
const { mutateAsync: addProviderCredential } = useAddProviderCredential(provider)
|
||||
const { mutateAsync: editProviderCredential } = useEditProviderCredential(provider)
|
||||
const { mutateAsync: deleteProviderCredential } = useDeleteProviderCredential(provider)
|
||||
const { mutateAsync: activeProviderCredential } = useActiveProviderCredential(provider)
|
||||
|
||||
const { mutateAsync: addModelCredential } = useAddModelCredential(provider)
|
||||
const { mutateAsync: activeModelCredential } = useActiveModelCredential(provider)
|
||||
const { mutateAsync: deleteModelCredential } = useDeleteModelCredential(provider)
|
||||
const { mutateAsync: editModelCredential } = useEditModelCredential(provider)
|
||||
|
||||
const getAddCredentialService = useCallback((isModel: boolean) => {
|
||||
return isModel ? addModelCredential : addProviderCredential
|
||||
}, [addModelCredential, addProviderCredential])
|
||||
|
||||
const getEditCredentialService = useCallback((isModel: boolean) => {
|
||||
return isModel ? editModelCredential : editProviderCredential
|
||||
}, [editModelCredential, editProviderCredential])
|
||||
|
||||
const getDeleteCredentialService = useCallback((isModel: boolean) => {
|
||||
return isModel ? deleteModelCredential : deleteProviderCredential
|
||||
}, [deleteModelCredential, deleteProviderCredential])
|
||||
|
||||
const getActiveCredentialService = useCallback((isModel: boolean) => {
|
||||
return isModel ? activeModelCredential : activeProviderCredential
|
||||
}, [activeModelCredential, activeProviderCredential])
|
||||
|
||||
return {
|
||||
getAddCredentialService,
|
||||
getEditCredentialService,
|
||||
getDeleteCredentialService,
|
||||
getActiveCredentialService,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
import {
|
||||
useCallback,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useToastContext } from '@/app/components/base/toast'
|
||||
import { useAuthService } from './use-auth-service'
|
||||
import type {
|
||||
ConfigurationMethodEnum,
|
||||
Credential,
|
||||
CustomConfigurationModelFixedFields,
|
||||
CustomModel,
|
||||
ModelProvider,
|
||||
} from '../../declarations'
|
||||
import {
|
||||
useModelModalHandler,
|
||||
useRefreshModel,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
|
||||
export const useAuth = (
|
||||
provider: ModelProvider,
|
||||
configurationMethod: ConfigurationMethodEnum,
|
||||
currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields,
|
||||
onUpdate?: () => void,
|
||||
) => {
|
||||
const { t } = useTranslation()
|
||||
const { notify } = useToastContext()
|
||||
const {
|
||||
getDeleteCredentialService,
|
||||
getActiveCredentialService,
|
||||
getEditCredentialService,
|
||||
getAddCredentialService,
|
||||
} = useAuthService(provider.provider)
|
||||
const handleOpenModelModal = useModelModalHandler()
|
||||
const { handleRefreshModel } = useRefreshModel()
|
||||
const pendingOperationCredentialId = useRef<string | null>(null)
|
||||
const pendingOperationModel = useRef<CustomModel | null>(null)
|
||||
const [deleteCredentialId, setDeleteCredentialId] = useState<string | null>(null)
|
||||
const openConfirmDelete = useCallback((credentialId?: string, model?: CustomModel) => {
|
||||
if (credentialId)
|
||||
pendingOperationCredentialId.current = credentialId
|
||||
if (model)
|
||||
pendingOperationModel.current = model
|
||||
|
||||
setDeleteCredentialId(pendingOperationCredentialId.current)
|
||||
}, [])
|
||||
const closeConfirmDelete = useCallback(() => {
|
||||
setDeleteCredentialId(null)
|
||||
pendingOperationCredentialId.current = null
|
||||
}, [])
|
||||
const [doingAction, setDoingAction] = useState(false)
|
||||
const doingActionRef = useRef(doingAction)
|
||||
const handleSetDoingAction = useCallback((doing: boolean) => {
|
||||
doingActionRef.current = doing
|
||||
setDoingAction(doing)
|
||||
}, [])
|
||||
const handleActiveCredential = useCallback(async (id: string, model?: CustomModel) => {
|
||||
if (doingActionRef.current)
|
||||
return
|
||||
try {
|
||||
handleSetDoingAction(true)
|
||||
await getActiveCredentialService(!!model)({
|
||||
credential_id: id,
|
||||
model: model?.model,
|
||||
model_type: model?.model_type,
|
||||
})
|
||||
notify({
|
||||
type: 'success',
|
||||
message: t('common.api.actionSuccess'),
|
||||
})
|
||||
onUpdate?.()
|
||||
}
|
||||
finally {
|
||||
handleSetDoingAction(false)
|
||||
}
|
||||
}, [getActiveCredentialService, onUpdate, notify, t, handleSetDoingAction])
|
||||
const handleConfirmDelete = useCallback(async () => {
|
||||
if (doingActionRef.current)
|
||||
return
|
||||
if (!pendingOperationCredentialId.current) {
|
||||
setDeleteCredentialId(null)
|
||||
return
|
||||
}
|
||||
try {
|
||||
handleSetDoingAction(true)
|
||||
await getDeleteCredentialService(!!pendingOperationModel.current)({
|
||||
credential_id: pendingOperationCredentialId.current,
|
||||
model: pendingOperationModel.current?.model,
|
||||
model_type: pendingOperationModel.current?.model_type,
|
||||
})
|
||||
notify({
|
||||
type: 'success',
|
||||
message: t('common.api.actionSuccess'),
|
||||
})
|
||||
onUpdate?.()
|
||||
handleRefreshModel(provider, configurationMethod, undefined)
|
||||
setDeleteCredentialId(null)
|
||||
pendingOperationCredentialId.current = null
|
||||
}
|
||||
finally {
|
||||
handleSetDoingAction(false)
|
||||
}
|
||||
}, [onUpdate, notify, t, handleSetDoingAction, getDeleteCredentialService])
|
||||
const handleAddCredential = useCallback((model?: CustomModel) => {
|
||||
if (model)
|
||||
pendingOperationModel.current = model
|
||||
}, [])
|
||||
const handleSaveCredential = useCallback(async (payload: Record<string, any>) => {
|
||||
if (doingActionRef.current)
|
||||
return
|
||||
try {
|
||||
handleSetDoingAction(true)
|
||||
|
||||
let res: { result?: string } = {}
|
||||
if (payload.credential_id)
|
||||
res = await getEditCredentialService(!!payload.model)(payload as any)
|
||||
else
|
||||
res = await getAddCredentialService(!!payload.model)(payload as any)
|
||||
|
||||
if (res.result === 'success') {
|
||||
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
|
||||
onUpdate?.()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
handleSetDoingAction(false)
|
||||
}
|
||||
}, [onUpdate, notify, t, handleSetDoingAction, getEditCredentialService, getAddCredentialService])
|
||||
const handleOpenModal = useCallback((model?: CustomModel, credential?: Credential) => {
|
||||
handleOpenModelModal(
|
||||
provider,
|
||||
configurationMethod,
|
||||
currentCustomConfigurationModelFixedFields,
|
||||
credential,
|
||||
model,
|
||||
)
|
||||
}, [handleOpenModelModal, provider, configurationMethod, currentCustomConfigurationModelFixedFields])
|
||||
|
||||
return {
|
||||
pendingOperationCredentialId,
|
||||
pendingOperationModel,
|
||||
openConfirmDelete,
|
||||
closeConfirmDelete,
|
||||
doingAction,
|
||||
handleActiveCredential,
|
||||
handleConfirmDelete,
|
||||
handleAddCredential,
|
||||
deleteCredentialId,
|
||||
handleSaveCredential,
|
||||
handleOpenModal,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import { useMemo } from 'react'
|
||||
import type {
|
||||
ModelProvider,
|
||||
} from '../../declarations'
|
||||
|
||||
export const useCredentialStatus = (provider: ModelProvider) => {
|
||||
const {
|
||||
current_credential_id,
|
||||
current_credential_name,
|
||||
available_credentials,
|
||||
} = provider.custom_configuration
|
||||
const hasCredential = !!available_credentials?.length
|
||||
const authorized = current_credential_id && current_credential_name
|
||||
const authRemoved = hasCredential && !current_credential_id && !current_credential_name
|
||||
|
||||
return useMemo(() => ({
|
||||
hasCredential,
|
||||
authorized,
|
||||
authRemoved,
|
||||
current_credential_id,
|
||||
current_credential_name,
|
||||
available_credentials,
|
||||
}), [hasCredential, authorized, authRemoved, current_credential_id, current_credential_name, available_credentials])
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import type {
|
||||
ModelProvider,
|
||||
} from '../../declarations'
|
||||
|
||||
export const useCustomModels = (provider: ModelProvider) => {
|
||||
const { custom_models } = provider.custom_configuration
|
||||
|
||||
return custom_models || []
|
||||
}
|
||||
|
|
@ -3,11 +3,11 @@ import { useTranslation } from 'react-i18next'
|
|||
import type {
|
||||
ModelLoadBalancingConfig,
|
||||
ModelProvider,
|
||||
} from '../declarations'
|
||||
} from '../../declarations'
|
||||
import {
|
||||
genModelNameFormSchema,
|
||||
genModelTypeFormSchema,
|
||||
} from '../utils'
|
||||
} from '../../utils'
|
||||
import { FormTypeEnum } from '@/app/components/base/form/types'
|
||||
|
||||
export const useModelFormSchemas = (
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
export { default as Authorized } from './authorized'
|
||||
export { default as SwitchCredentialInLoadBalancing } from './switch-credential-in-load-balancing'
|
||||
export { default as AddCredentialInLoadBalancing } from './add-credential-in-load-balancing'
|
||||
export { default as AddCustomModel } from './add-custom-model'
|
||||
export { default as ConfigProvider } from './config-provider'
|
||||
|
|
@ -1,45 +1,107 @@
|
|||
import type { Dispatch, SetStateAction } from 'react'
|
||||
import {
|
||||
memo,
|
||||
useCallback,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiArrowDownSLine } from '@remixicon/react'
|
||||
import Button from '@/app/components/base/button'
|
||||
import {
|
||||
AuthCategory,
|
||||
Authorized,
|
||||
} from '@/app/components/plugins/plugin-auth'
|
||||
import Indicator from '@/app/components/header/indicator'
|
||||
import Badge from '@/app/components/base/badge'
|
||||
import Authorized from './authorized'
|
||||
import type {
|
||||
Credential,
|
||||
ModelLoadBalancingConfig,
|
||||
ModelProvider,
|
||||
} from '../declarations'
|
||||
import { ConfigurationMethodEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import { useCredentialStatus } from './hooks'
|
||||
import { useModelModalHandler } from '../hooks'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type SwitchCredentialInLoadBalancingProps = {
|
||||
provider: ModelProvider
|
||||
draftConfig?: ModelLoadBalancingConfig
|
||||
setDraftConfig: Dispatch<SetStateAction<ModelLoadBalancingConfig | undefined>>
|
||||
}
|
||||
const SwitchCredentialInLoadBalancing = ({
|
||||
provider,
|
||||
draftConfig,
|
||||
setDraftConfig,
|
||||
}: SwitchCredentialInLoadBalancingProps) => {
|
||||
const { t } = useTranslation()
|
||||
const {
|
||||
available_credentials,
|
||||
current_credential_name,
|
||||
} = useCredentialStatus(provider)
|
||||
const handleOpenModal = useModelModalHandler()
|
||||
console.log(draftConfig, 'draftConfig')
|
||||
|
||||
const handleSetup = useCallback((credential?: Credential) => {
|
||||
handleOpenModal(provider, ConfigurationMethodEnum.predefinedModel, undefined, credential)
|
||||
}, [handleOpenModal, provider])
|
||||
|
||||
const handleItemClick = useCallback((id: string) => {
|
||||
setDraftConfig((prev) => {
|
||||
if (!prev)
|
||||
return prev
|
||||
const newConfigs = [...prev.configs]
|
||||
const index = newConfigs.findIndex(config => config.name === '__inherit__')
|
||||
const inheritConfig = newConfigs[index]
|
||||
const modifiedConfig = inheritConfig ? {
|
||||
...inheritConfig,
|
||||
credential_id: id,
|
||||
} : {
|
||||
name: '__inherit__',
|
||||
credential_id: id,
|
||||
credentials: {},
|
||||
}
|
||||
newConfigs.splice(index, 1, modifiedConfig)
|
||||
return {
|
||||
...prev,
|
||||
configs: newConfigs,
|
||||
}
|
||||
})
|
||||
}, [setDraftConfig])
|
||||
|
||||
const SwitchCredentialInLoadBalancing = () => {
|
||||
const renderTrigger = useCallback(() => {
|
||||
const selectedCredentialId = draftConfig?.configs.find(config => config.name === '__inherit__')?.credential_id
|
||||
const selectedCredential = available_credentials?.find(credential => credential.credential_id === selectedCredentialId)
|
||||
const name = selectedCredential?.credential_name || current_credential_name
|
||||
const authRemoved = !!selectedCredentialId && !selectedCredential
|
||||
return (
|
||||
<Button
|
||||
variant='secondary'
|
||||
className='space-x-1'
|
||||
className={cn(
|
||||
'shrink-0 space-x-1',
|
||||
authRemoved && 'text-components-button-destructive-secondary-text',
|
||||
)}
|
||||
>
|
||||
<Indicator />
|
||||
chat-enterprise
|
||||
<Badge>enterprise</Badge>
|
||||
<Indicator
|
||||
className='mr-2'
|
||||
color={authRemoved ? 'red' : 'green'}
|
||||
/>
|
||||
{
|
||||
authRemoved ? t('common.model.authRemoved') : name
|
||||
}
|
||||
{
|
||||
!authRemoved && (
|
||||
<Badge>enterprise</Badge>
|
||||
)
|
||||
}
|
||||
<RiArrowDownSLine className='h-4 w-4' />
|
||||
</Button>
|
||||
)
|
||||
}, [])
|
||||
}, [current_credential_name, t, draftConfig, available_credentials])
|
||||
|
||||
return (
|
||||
<Authorized
|
||||
credentials={[]}
|
||||
pluginPayload={{
|
||||
provider: '',
|
||||
category: AuthCategory.model,
|
||||
}}
|
||||
canApiKey
|
||||
placement='bottom-end'
|
||||
offset={{
|
||||
mainAxis: 4,
|
||||
crossAxis: -8,
|
||||
}}
|
||||
provider={provider.provider}
|
||||
credentials={available_credentials || []}
|
||||
onSetup={handleSetup}
|
||||
renderTrigger={renderTrigger}
|
||||
onItemClick={handleItemClick}
|
||||
disableSetDefault
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,34 +2,20 @@ import type { FC } from 'react'
|
|||
import {
|
||||
memo,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type {
|
||||
CustomConfigurationModelFixedFields,
|
||||
ModelLoadBalancingConfig,
|
||||
ModelLoadBalancingConfigEntry,
|
||||
ModelProvider,
|
||||
} from '../declarations'
|
||||
import {
|
||||
ConfigurationMethodEnum,
|
||||
CustomConfigurationStatusEnum,
|
||||
FormTypeEnum,
|
||||
} from '../declarations'
|
||||
import {
|
||||
genModelNameFormSchema,
|
||||
genModelTypeFormSchema,
|
||||
removeCredentials,
|
||||
saveCredentials,
|
||||
} from '../utils'
|
||||
import {
|
||||
useLanguage,
|
||||
useProviderCredentialsAndLoadBalancing,
|
||||
} from '../hooks'
|
||||
import ModelLoadBalancingConfigs from '../provider-added-card/model-load-balancing-configs'
|
||||
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'
|
||||
|
|
@ -37,7 +23,6 @@ import {
|
|||
PortalToFollowElem,
|
||||
PortalToFollowElemContent,
|
||||
} from '@/app/components/base/portal-to-follow-elem'
|
||||
import { useToastContext } from '@/app/components/base/toast'
|
||||
import Confirm from '@/app/components/base/confirm'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import AuthForm from '@/app/components/base/form/form-scenarios/auth'
|
||||
|
|
@ -46,20 +31,29 @@ import type {
|
|||
FormSchema,
|
||||
} from '@/app/components/base/form/types'
|
||||
import { useModelFormSchemas } from '../model-auth/hooks'
|
||||
import type { Credential } from '../declarations'
|
||||
import type {
|
||||
Credential,
|
||||
CustomModel,
|
||||
} from '../declarations'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import {
|
||||
useAuth,
|
||||
useGetCredential,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/model-auth/hooks'
|
||||
|
||||
type ModelModalProps = {
|
||||
provider: ModelProvider
|
||||
model?: CustomModel
|
||||
credential?: Credential
|
||||
configurateMethod: ConfigurationMethodEnum
|
||||
currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields
|
||||
credential?: Credential
|
||||
onCancel: () => void
|
||||
onSave: () => void
|
||||
}
|
||||
|
||||
const ModelModal: FC<ModelModalProps> = ({
|
||||
provider,
|
||||
model,
|
||||
configurateMethod,
|
||||
currentCustomConfigurationModelFixedFields,
|
||||
credential,
|
||||
|
|
@ -68,134 +62,62 @@ const ModelModal: FC<ModelModalProps> = ({
|
|||
}) => {
|
||||
const providerFormSchemaPredefined = configurateMethod === ConfigurationMethodEnum.predefinedModel
|
||||
const {
|
||||
credentials: formSchemasValue,
|
||||
loadBalancing: originalConfig,
|
||||
mutate,
|
||||
isLoading,
|
||||
} = useProviderCredentialsAndLoadBalancing(
|
||||
provider.provider,
|
||||
configurateMethod,
|
||||
providerFormSchemaPredefined && provider.custom_configuration.status === CustomConfigurationStatusEnum.active,
|
||||
currentCustomConfigurationModelFixedFields,
|
||||
credential?.credential_id,
|
||||
)
|
||||
data: credentialData = {},
|
||||
} = useGetCredential(provider.provider, credential?.credential_id, model)
|
||||
const {
|
||||
handleSaveCredential,
|
||||
handleConfirmDelete,
|
||||
deleteCredentialId,
|
||||
closeConfirmDelete,
|
||||
openConfirmDelete,
|
||||
doingAction,
|
||||
} = useAuth(provider, configurateMethod, currentCustomConfigurationModelFixedFields, onSave)
|
||||
const {
|
||||
credentials: formSchemasValue,
|
||||
} = credentialData as any
|
||||
|
||||
const { isCurrentWorkspaceManager } = useAppContext()
|
||||
const isEditMode = !!formSchemasValue && isCurrentWorkspaceManager
|
||||
const { t } = useTranslation()
|
||||
const { notify } = useToastContext()
|
||||
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 } = useModelFormSchemas(provider, providerFormSchemaPredefined, draftConfig)
|
||||
const { formSchemas } = useModelFormSchemas(provider, providerFormSchemaPredefined)
|
||||
const formRef = useRef<FormRefObject>(null)
|
||||
|
||||
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 handleSave = useCallback(async () => {
|
||||
const {
|
||||
isCheckValidated,
|
||||
values,
|
||||
} = formRef.current?.getFormValues({
|
||||
needCheckValidatedValues: true,
|
||||
needTransformWhenSecretFieldIsPristine: true,
|
||||
}) || { isCheckValidated: false, values: {} }
|
||||
if (!isCheckValidated)
|
||||
return
|
||||
|
||||
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 {
|
||||
isCheckValidated,
|
||||
values,
|
||||
} = formRef.current?.getFormValues({
|
||||
needCheckValidatedValues: true,
|
||||
needTransformWhenSecretFieldIsPristine: true,
|
||||
}) || { isCheckValidated: false, values: {} }
|
||||
if (!isCheckValidated)
|
||||
return
|
||||
|
||||
const res = await saveCredentials(
|
||||
providerFormSchemaPredefined,
|
||||
provider.provider,
|
||||
values,
|
||||
{
|
||||
...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()
|
||||
}
|
||||
const {
|
||||
__authorization_name__,
|
||||
__model_name,
|
||||
__model_type,
|
||||
...rest
|
||||
} = values
|
||||
if (__model_name && __model_type) {
|
||||
handleSaveCredential({
|
||||
credential_id: credential?.credential_id,
|
||||
credentials: rest,
|
||||
name: __authorization_name__,
|
||||
model: __model_name,
|
||||
model_type: __model_type,
|
||||
})
|
||||
}
|
||||
finally {
|
||||
setLoading(false)
|
||||
else {
|
||||
handleSaveCredential({
|
||||
credential_id: credential?.credential_id,
|
||||
credentials: rest,
|
||||
name: __authorization_name__,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const handleRemove = async () => {
|
||||
try {
|
||||
setLoading(true)
|
||||
const {
|
||||
isCheckValidated,
|
||||
values,
|
||||
} = formRef.current?.getFormValues({
|
||||
needCheckValidatedValues: true,
|
||||
needTransformWhenSecretFieldIsPristine: true,
|
||||
}) || { isCheckValidated: false, values: {} }
|
||||
if (!isCheckValidated)
|
||||
return
|
||||
const res = await removeCredentials(
|
||||
providerFormSchemaPredefined,
|
||||
provider.provider,
|
||||
values,
|
||||
credential?.credential_id,
|
||||
)
|
||||
if (res.result === 'success') {
|
||||
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
|
||||
// mutate()
|
||||
onSave()
|
||||
onCancel()
|
||||
}
|
||||
}
|
||||
finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
}, [handleSaveCredential, credential?.credential_id, model])
|
||||
|
||||
const renderTitlePrefix = () => {
|
||||
const prefix = isEditMode ? t('common.operation.setup') : t('common.operation.add')
|
||||
|
|
@ -239,20 +161,6 @@ const ModelModal: FC<ModelModalProps> = ({
|
|||
/>
|
||||
)
|
||||
}
|
||||
{
|
||||
!!draftConfig && (
|
||||
<>
|
||||
<div className='mb-4 mt-1 border-t-[0.5px] border-t-divider-regular' />
|
||||
<ModelLoadBalancingConfigs withSwitch {...{
|
||||
draftConfig,
|
||||
setDraftConfig,
|
||||
provider,
|
||||
currentCustomConfigurationModelFixedFields,
|
||||
configurationMethod: configurateMethod,
|
||||
}} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
||||
<div className='sticky bottom-0 -mx-2 mt-2 flex flex-wrap items-center justify-between gap-y-2 bg-components-panel-bg px-2 pb-6 pt-4'>
|
||||
|
|
@ -278,7 +186,7 @@ const ModelModal: FC<ModelModalProps> = ({
|
|||
variant='warning'
|
||||
size='large'
|
||||
className='mr-2'
|
||||
onClick={() => setShowConfirm(true)}
|
||||
onClick={() => openConfirmDelete(credential?.credential_id, model)}
|
||||
>
|
||||
{t('common.operation.remove')}
|
||||
</Button>
|
||||
|
|
@ -295,11 +203,7 @@ const ModelModal: FC<ModelModalProps> = ({
|
|||
size='large'
|
||||
variant='primary'
|
||||
onClick={handleSave}
|
||||
disabled={
|
||||
loading
|
||||
|| (draftConfig?.enabled && (draftConfig?.configs.filter(config => config.enabled).length ?? 0) < 2)
|
||||
}
|
||||
|
||||
disabled={isLoading || doingAction}
|
||||
>
|
||||
{t('common.operation.save')}
|
||||
</Button>
|
||||
|
|
@ -322,12 +226,13 @@ const ModelModal: FC<ModelModalProps> = ({
|
|||
</div>
|
||||
</div>
|
||||
{
|
||||
showConfirm && (
|
||||
deleteCredentialId && (
|
||||
<Confirm
|
||||
isShow
|
||||
title={t('common.modelProvider.confirmDelete')}
|
||||
isShow={showConfirm}
|
||||
onCancel={() => setShowConfirm(false)}
|
||||
onConfirm={handleRemove}
|
||||
isDisabled={doingAction}
|
||||
onCancel={closeConfirmDelete}
|
||||
onConfirm={handleConfirmDelete}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiEqualizer2Line } from '@remixicon/react'
|
||||
import type {
|
||||
Credential,
|
||||
ModelProvider,
|
||||
} from '../declarations'
|
||||
import {
|
||||
|
|
@ -18,22 +16,18 @@ import PrioritySelector from './priority-selector'
|
|||
import PriorityUseTip from './priority-use-tip'
|
||||
import { UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST } from './index'
|
||||
import Indicator from '@/app/components/header/indicator'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { changeModelProviderPriority } from '@/service/common'
|
||||
import { useToastContext } from '@/app/components/base/toast'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import Authorized from '../model-auth/authorized'
|
||||
import cn from '@/utils/classnames'
|
||||
import { useCredentialStatus } from '@/app/components/header/account-setting/model-provider-page/model-auth/hooks'
|
||||
import { ConfigProvider } from '@/app/components/header/account-setting/model-provider-page/model-auth'
|
||||
|
||||
type CredentialPanelProps = {
|
||||
provider: ModelProvider
|
||||
onSetup: (credential?: Credential) => void
|
||||
onUpdate: () => void
|
||||
}
|
||||
const CredentialPanel = ({
|
||||
provider,
|
||||
onSetup,
|
||||
onUpdate,
|
||||
}: CredentialPanelProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { notify } = useToastContext()
|
||||
|
|
@ -46,13 +40,11 @@ const CredentialPanel = ({
|
|||
const isCustomConfigured = customConfig.status === CustomConfigurationStatusEnum.active
|
||||
const configurateMethods = provider.configurate_methods
|
||||
const {
|
||||
current_credential_id,
|
||||
hasCredential,
|
||||
authorized,
|
||||
authRemoved,
|
||||
current_credential_name,
|
||||
available_credentials,
|
||||
} = provider.custom_configuration
|
||||
const hasCredential = !!available_credentials?.length
|
||||
const authorized = current_credential_id && current_credential_name
|
||||
const authRemoved = hasCredential && !current_credential_id && !current_credential_name
|
||||
} = useCredentialStatus(provider)
|
||||
|
||||
const handleChangePriority = async (key: PreferredProviderTypeEnum) => {
|
||||
const res = await changeModelProviderPriority({
|
||||
|
|
@ -108,31 +100,10 @@ const CredentialPanel = ({
|
|||
<Indicator className='shrink-0' color={authorized ? 'green' : 'red'} />
|
||||
</div>
|
||||
<div className='flex items-center gap-0.5'>
|
||||
{
|
||||
!hasCredential && (
|
||||
<Button
|
||||
className='grow'
|
||||
size='small'
|
||||
onClick={() => onSetup()}
|
||||
variant={!authorized ? 'secondary-accent' : 'secondary'}
|
||||
>
|
||||
<RiEqualizer2Line className='mr-1 h-3.5 w-3.5' />
|
||||
{t('common.operation.setup')}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
{
|
||||
(hasCredential || authRemoved) && (
|
||||
<Authorized
|
||||
provider={provider.provider}
|
||||
onSetup={onSetup}
|
||||
credentials={available_credentials ?? []}
|
||||
selectedCredentialId={current_credential_id}
|
||||
showItemSelectedIcon
|
||||
onUpdate={onUpdate}
|
||||
/>
|
||||
)
|
||||
}
|
||||
<ConfigProvider
|
||||
provider={provider}
|
||||
configurationMethod={ConfigurationMethodEnum.predefinedModel}
|
||||
/>
|
||||
{
|
||||
systemConfig.enabled && isCustomConfigured && (
|
||||
<PrioritySelector
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ import { useEventEmitterContextContext } from '@/context/event-emitter'
|
|||
import { IS_CE_EDITION } from '@/config'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import cn from '@/utils/classnames'
|
||||
import { useRefreshModel } from '../hooks'
|
||||
|
||||
export const UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST = 'UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST'
|
||||
type ProviderAddedCardProps = {
|
||||
|
|
@ -82,8 +81,6 @@ const ProviderAddedCard: FC<ProviderAddedCardProps> = ({
|
|||
getModelList(v.payload)
|
||||
})
|
||||
|
||||
const { handleRefreshModel } = useRefreshModel()
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
|
|
@ -118,8 +115,6 @@ const ProviderAddedCard: FC<ProviderAddedCardProps> = ({
|
|||
{
|
||||
showCredential && (
|
||||
<CredentialPanel
|
||||
onSetup={(credential?: Credential) => onOpenModal(ConfigurationMethodEnum.predefinedModel, undefined, credential)}
|
||||
onUpdate={() => handleRefreshModel(provider, ConfigurationMethodEnum.predefinedModel, undefined)}
|
||||
provider={provider}
|
||||
/>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import {
|
|||
RiArrowRightSLine,
|
||||
} from '@remixicon/react'
|
||||
import type {
|
||||
Credential,
|
||||
CustomConfigurationModelFixedFields,
|
||||
ModelItem,
|
||||
ModelProvider,
|
||||
|
|
@ -13,10 +14,11 @@ import {
|
|||
ConfigurationMethodEnum,
|
||||
} from '../declarations'
|
||||
// import Tab from './tab'
|
||||
import AddModelButton from './add-model-button'
|
||||
import ModelListItem from './model-list-item'
|
||||
import { useModalContextSelector } from '@/context/modal-context'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useCustomModels } from '@/app/components/header/account-setting/model-provider-page/model-auth/hooks'
|
||||
import { AddCustomModel } from '@/app/components/header/account-setting/model-provider-page/model-auth'
|
||||
|
||||
type ModelListProps = {
|
||||
provider: ModelProvider
|
||||
|
|
@ -36,11 +38,12 @@ const ModelList: FC<ModelListProps> = ({
|
|||
const configurativeMethods = provider.configurate_methods.filter(method => method !== ConfigurationMethodEnum.fetchFromRemote)
|
||||
const { isCurrentWorkspaceManager } = useAppContext()
|
||||
const isConfigurable = configurativeMethods.includes(ConfigurationMethodEnum.customizableModel)
|
||||
|
||||
const customModels = useCustomModels(provider)
|
||||
const setShowModelLoadBalancingModal = useModalContextSelector(state => state.setShowModelLoadBalancingModal)
|
||||
const onModifyLoadBalancing = useCallback((model: ModelItem) => {
|
||||
const onModifyLoadBalancing = useCallback((model: ModelItem, credential?: Credential) => {
|
||||
setShowModelLoadBalancingModal({
|
||||
provider,
|
||||
credential,
|
||||
model: model!,
|
||||
open: !!model,
|
||||
onClose: () => setShowModelLoadBalancingModal(null),
|
||||
|
|
@ -65,17 +68,15 @@ const ModelList: FC<ModelListProps> = ({
|
|||
<RiArrowRightSLine className='mr-0.5 h-4 w-4 rotate-90' />
|
||||
</span>
|
||||
</span>
|
||||
{/* {
|
||||
isConfigurable && canSystemConfig && (
|
||||
<span className='flex items-center'>
|
||||
<Tab active='all' onSelect={() => {}} />
|
||||
</span>
|
||||
)
|
||||
} */}
|
||||
{
|
||||
isConfigurable && isCurrentWorkspaceManager && (
|
||||
<div className='flex grow justify-end'>
|
||||
<AddModelButton onClick={() => onConfig()} />
|
||||
<AddCustomModel
|
||||
provider={provider}
|
||||
configurationMethod={ConfigurationMethodEnum.customizableModel}
|
||||
currentCustomConfigurationModelFixedFields={undefined}
|
||||
models={customModels}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import classNames from '@/utils/classnames'
|
|||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import Switch from '@/app/components/base/switch'
|
||||
import { Balance } from '@/app/components/base/icons/src/vender/line/financeAndECommerce'
|
||||
import { Edit02, Plus02 } from '@/app/components/base/icons/src/vender/line/general'
|
||||
import { Edit02 } from '@/app/components/base/icons/src/vender/line/general'
|
||||
import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback'
|
||||
import { useModalContextSelector } from '@/context/modal-context'
|
||||
import UpgradeBtn from '@/app/components/billing/upgrade-btn'
|
||||
|
|
@ -19,6 +19,7 @@ import s from '@/app/components/custom/style.module.css'
|
|||
import GridMask from '@/app/components/base/grid-mask'
|
||||
import { useProviderContextSelector } from '@/context/provider-context'
|
||||
import { IS_CE_EDITION } from '@/config'
|
||||
import { AddCredentialInLoadBalancing } from '@/app/components/header/account-setting/model-provider-page/model-auth'
|
||||
|
||||
export type ModelLoadBalancingConfigsProps = {
|
||||
draftConfig?: ModelLoadBalancingConfig
|
||||
|
|
@ -234,15 +235,10 @@ const ModelLoadBalancingConfigs = ({
|
|||
</div>
|
||||
)
|
||||
})}
|
||||
|
||||
<div
|
||||
className='mt-1 flex h-8 items-center px-3 text-[13px] font-medium text-primary-600'
|
||||
onClick={() => toggleEntryModal()}
|
||||
>
|
||||
<div className='flex cursor-pointer items-center'>
|
||||
<Plus02 className='mr-2 h-3 w-3' />{t('common.modelProvider.addConfig')}
|
||||
</div>
|
||||
</div>
|
||||
<AddCredentialInLoadBalancing
|
||||
provider={provider}
|
||||
onSetup={() => toggleEntryModal()}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
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 type {
|
||||
Credential,
|
||||
ModelItem,
|
||||
ModelLoadBalancingConfig,
|
||||
ModelLoadBalancingConfigEntry,
|
||||
ModelProvider,
|
||||
} from '../declarations'
|
||||
import { FormTypeEnum } from '../declarations'
|
||||
import ModelIcon from '../model-icon'
|
||||
import ModelName from '../model-name'
|
||||
|
|
@ -13,17 +19,26 @@ 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'
|
||||
import { SwitchCredentialInLoadBalancing } from '@/app/components/header/account-setting/model-provider-page/model-auth'
|
||||
|
||||
export type ModelLoadBalancingModalProps = {
|
||||
provider: ModelProvider
|
||||
model: ModelItem
|
||||
credential?: Credential
|
||||
open?: boolean
|
||||
onClose?: () => void
|
||||
onSave?: (provider: string) => void
|
||||
}
|
||||
|
||||
// model balancing config modal
|
||||
const ModelLoadBalancingModal = ({ provider, model, open = false, onClose, onSave }: ModelLoadBalancingModalProps) => {
|
||||
const ModelLoadBalancingModal = ({
|
||||
provider,
|
||||
model,
|
||||
credential,
|
||||
open = false,
|
||||
onClose,
|
||||
onSave,
|
||||
}: ModelLoadBalancingModalProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { notify } = useToastContext()
|
||||
|
||||
|
|
@ -152,6 +167,11 @@ const ModelLoadBalancingModal = ({ provider, model, open = false, onClose, onSav
|
|||
<div className='text-sm text-text-secondary'>{t('common.modelProvider.providerManaged')}</div>
|
||||
<div className='text-xs text-text-tertiary'>{t('common.modelProvider.providerManagedDescription')}</div>
|
||||
</div>
|
||||
<SwitchCredentialInLoadBalancing
|
||||
draftConfig={draftConfig}
|
||||
setDraftConfig={setDraftConfig}
|
||||
provider={provider}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { ValidatedStatus } from '../key-validator/declarations'
|
||||
import type {
|
||||
CredentialFormSchemaRadio,
|
||||
CredentialFormSchemaTextInput,
|
||||
FormValue,
|
||||
ModelLoadBalancingConfig,
|
||||
|
|
@ -181,7 +180,7 @@ export const genModelTypeFormSchema = (modelTypes: ModelTypeEnum[]) => {
|
|||
show_on: [],
|
||||
}
|
||||
}),
|
||||
} as CredentialFormSchemaRadio
|
||||
} as any
|
||||
}
|
||||
|
||||
export const genModelNameFormSchema = (model?: Pick<CredentialFormSchemaTextInput, 'label' | 'placeholder'>) => {
|
||||
|
|
@ -198,5 +197,5 @@ export const genModelNameFormSchema = (model?: Pick<CredentialFormSchemaTextInpu
|
|||
zh_Hans: '请输入模型名称',
|
||||
en_US: 'Please enter model name',
|
||||
},
|
||||
} as CredentialFormSchemaTextInput
|
||||
} as any
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import type {
|
|||
ConfigurationMethodEnum,
|
||||
Credential,
|
||||
CustomConfigurationModelFixedFields,
|
||||
CustomModel,
|
||||
ModelLoadBalancingConfigEntry,
|
||||
ModelProvider,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
|
|
@ -81,6 +82,7 @@ export type ModelModalType = {
|
|||
currentConfigurationMethod: ConfigurationMethodEnum
|
||||
currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields
|
||||
credential?: Credential
|
||||
model?: CustomModel
|
||||
}
|
||||
export type LoadBalancingEntryModalType = ModelModalType & {
|
||||
entry?: ModelLoadBalancingConfigEntry
|
||||
|
|
@ -338,6 +340,7 @@ export const ModalContextProvider = ({
|
|||
<ModelModal
|
||||
provider={showModelModal.payload.currentProvider}
|
||||
configurateMethod={showModelModal.payload.currentConfigurationMethod}
|
||||
model={showModelModal.payload.model}
|
||||
currentCustomConfigurationModelFixedFields={showModelModal.payload.currentCustomConfigurationModelFixedFields}
|
||||
credential={showModelModal.payload.credential}
|
||||
onCancel={handleCancelModelModal}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,13 @@ import {
|
|||
del,
|
||||
get,
|
||||
post,
|
||||
put,
|
||||
} from './base'
|
||||
import type {
|
||||
ModelCredential,
|
||||
ModelItem,
|
||||
ModelTypeEnum,
|
||||
ProviderCredential,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import {
|
||||
useMutation,
|
||||
|
|
@ -21,35 +25,114 @@ export const useModelProviderModelList = (provider: string) => {
|
|||
})
|
||||
}
|
||||
|
||||
export const useAddModelCredential = (providerName: string) => {
|
||||
return useMutation({
|
||||
mutationFn: (data: any) => post<{ result: string }>(`/workspaces/current/model-providers/${providerName}/credentials`, data),
|
||||
})
|
||||
}
|
||||
|
||||
export const useGetModelCredential = (providerName: string, credentialId: string) => {
|
||||
export const useGetProviderCredential = (enabled: boolean, provider: string, credentialId?: string) => {
|
||||
return useQuery({
|
||||
queryKey: [NAME_SPACE, 'model-credential', providerName, credentialId],
|
||||
queryFn: () => get<{ data: Credential[] }>(`/workspaces/current/model-providers/${providerName}/credentials?credential_id=${credentialId}`),
|
||||
enabled,
|
||||
queryKey: [NAME_SPACE, 'model-list', provider, credentialId],
|
||||
queryFn: () => get<{ data: ProviderCredential }>(`/workspaces/current/model-providers/${provider}/credentials${credentialId ? `?credential_id=${credentialId}` : ''}`),
|
||||
})
|
||||
}
|
||||
|
||||
export const useDeleteModelCredential = (providerName: string) => {
|
||||
export const useAddProviderCredential = (provider: string) => {
|
||||
return useMutation({
|
||||
mutationFn: (credentialId: string) => del<{ result: string }>(`/workspaces/current/model-providers/${providerName}/credentials`, {
|
||||
body: {
|
||||
credential_id: credentialId,
|
||||
},
|
||||
mutationFn: (data: ProviderCredential) => post<{ result: string }>(`/workspaces/current/model-providers/${provider}/credentials`, {
|
||||
body: data,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
export const useSetModelCredentialDefault = (providerName: string) => {
|
||||
export const useEditProviderCredential = (provider: string) => {
|
||||
return useMutation({
|
||||
mutationFn: (credentialId: string) => post<{ result: string }>(`/workspaces/current/model-providers/${providerName}/credentials/switch`, {
|
||||
body: {
|
||||
credential_id: credentialId,
|
||||
},
|
||||
mutationFn: (data: ProviderCredential) => put<{ result: string }>(`/workspaces/current/model-providers/${provider}/credentials`, {
|
||||
body: data,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
export const useDeleteProviderCredential = (provider: string) => {
|
||||
return useMutation({
|
||||
mutationFn: (data: {
|
||||
credential_id: string
|
||||
}) => del<{ result: string }>(`/workspaces/current/model-providers/${provider}/credentials`, {
|
||||
body: data,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
export const useActiveProviderCredential = (provider: string) => {
|
||||
return useMutation({
|
||||
mutationFn: (data: {
|
||||
credential_id: string
|
||||
model?: string
|
||||
model_type?: ModelTypeEnum
|
||||
}) => post<{ result: string }>(`/workspaces/current/model-providers/${provider}/credentials/switch`, {
|
||||
body: data,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
export const useGetModelCredential = (
|
||||
enabled: boolean,
|
||||
provider: string,
|
||||
credentialId?: string,
|
||||
model?: string,
|
||||
modelType?: string,
|
||||
configFrom?: string,
|
||||
) => {
|
||||
return useQuery({
|
||||
enabled,
|
||||
queryKey: [NAME_SPACE, 'model-list', provider, model, modelType, credentialId],
|
||||
queryFn: () => get<{ data: ModelCredential }>(`/workspaces/current/model-providers/${provider}/models/credentials?model=${model}&model_type=${modelType}$credential_id=${credentialId}$config_from=${configFrom}`),
|
||||
})
|
||||
}
|
||||
|
||||
export const useAddModelCredential = (provider: string) => {
|
||||
return useMutation({
|
||||
mutationFn: (data: ModelCredential) => post<{ result: string }>(`/workspaces/current/model-providers/${provider}/models/credentials`, {
|
||||
body: data,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
export const useEditModelCredential = (provider: string) => {
|
||||
return useMutation({
|
||||
mutationFn: (data: ModelCredential) => put<{ result: string }>(`/workspaces/current/model-providers/${provider}/models/credentials`, {
|
||||
body: data,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
export const useDeleteModelCredential = (provider: string) => {
|
||||
return useMutation({
|
||||
mutationFn: (data: {
|
||||
credential_id: string
|
||||
model?: string
|
||||
model_type?: ModelTypeEnum
|
||||
}) => del<{ result: string }>(`/workspaces/current/model-providers/${provider}/models/credentials`, {
|
||||
body: data,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
export const useDeleteModel = (provider: string) => {
|
||||
return useMutation({
|
||||
mutationFn: (data: {
|
||||
model: string
|
||||
model_type: ModelTypeEnum
|
||||
}) => del<{ result: string }>(`/workspaces/current/model-providers/${provider}/models/credentials`, {
|
||||
body: data,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
export const useActiveModelCredential = (provider: string) => {
|
||||
return useMutation({
|
||||
mutationFn: (data: {
|
||||
credential_id: string
|
||||
model?: string
|
||||
model_type?: ModelTypeEnum
|
||||
}) => post<{ result: string }>(`/workspaces/current/model-providers/${provider}/models/credentials/switch`, {
|
||||
body: data,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue