mirror of
https://github.com/langgenius/dify.git
synced 2026-05-05 18:08:07 +08:00
refactor(web): enhance model selector functionality and improve UI consistency
- Removed unnecessary ESLint suppressions for better code quality. - Updated the ModelParameterModal and ModelSelector components to ensure consistent class ordering. - Added onHide prop to ModelSelector for better control over dropdown visibility. - Introduced useChangeProviderPriority hook to manage provider priority changes more effectively. - Integrated CreditsExhaustedAlert in the Popup component to handle API key status more gracefully.
This commit is contained in:
@ -174,13 +174,14 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({
|
||||
<div className={cn(popupClassName, 'w-[389px] rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-lg')}>
|
||||
<div className={cn('max-h-[420px] overflow-y-auto p-4 pt-3')}>
|
||||
<div className="relative">
|
||||
<div className={cn('system-sm-semibold mb-1 flex h-6 items-center text-text-secondary')}>
|
||||
<div className={cn('mb-1 flex h-6 items-center text-text-secondary system-sm-semibold')}>
|
||||
{t('modelProvider.model', { ns: 'common' }).toLocaleUpperCase()}
|
||||
</div>
|
||||
<ModelSelector
|
||||
defaultModel={(provider || modelId) ? { provider, model: modelId } : undefined}
|
||||
modelList={activeTextGenerationModelList}
|
||||
onSelect={handleChangeModel}
|
||||
onHide={() => setOpen(false)}
|
||||
/>
|
||||
</div>
|
||||
{
|
||||
@ -196,7 +197,7 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({
|
||||
{
|
||||
!isLoading && !!parameterRules.length && (
|
||||
<div className="mb-2 flex items-center justify-between">
|
||||
<div className={cn('system-sm-semibold flex h-6 items-center text-text-secondary')}>{t('modelProvider.parameters', { ns: 'common' })}</div>
|
||||
<div className={cn('flex h-6 items-center text-text-secondary system-sm-semibold')}>{t('modelProvider.parameters', { ns: 'common' })}</div>
|
||||
{
|
||||
PROVIDER_WITH_PRESET_TONE.includes(provider) && (
|
||||
<PresetsParameter onSelect={handleSelectPresetParameter} />
|
||||
@ -225,7 +226,7 @@ const ModelParameterModal: FC<ModelParameterModalProps> = ({
|
||||
</div>
|
||||
{!hideDebugWithMultipleModel && (
|
||||
<div
|
||||
className="bg-components-section-burn system-sm-regular flex h-[50px] cursor-pointer items-center justify-between rounded-b-xl border-t border-t-divider-subtle px-4 text-text-accent"
|
||||
className="bg-components-section-burn flex h-[50px] cursor-pointer items-center justify-between rounded-b-xl border-t border-t-divider-subtle px-4 text-text-accent system-sm-regular"
|
||||
onClick={() => onDebugWithMultipleModelChange?.()}
|
||||
>
|
||||
{
|
||||
|
||||
@ -24,6 +24,7 @@ type ModelSelectorProps = {
|
||||
triggerClassName?: string
|
||||
popupClassName?: string
|
||||
onSelect?: (model: DefaultModel) => void
|
||||
onHide?: () => void
|
||||
readonly?: boolean
|
||||
scopeFeatures?: ModelFeatureEnum[]
|
||||
deprecatedClassName?: string
|
||||
@ -35,6 +36,7 @@ const ModelSelector: FC<ModelSelectorProps> = ({
|
||||
triggerClassName,
|
||||
popupClassName,
|
||||
onSelect,
|
||||
onHide,
|
||||
readonly,
|
||||
scopeFeatures = [],
|
||||
deprecatedClassName,
|
||||
@ -113,7 +115,10 @@ const ModelSelector: FC<ModelSelectorProps> = ({
|
||||
modelList={modelList}
|
||||
onSelect={handleSelect}
|
||||
scopeFeatures={scopeFeatures}
|
||||
onHide={() => setOpen(false)}
|
||||
onHide={() => {
|
||||
setOpen(false)
|
||||
onHide?.()
|
||||
}}
|
||||
triggerRef={triggerRef}
|
||||
/>
|
||||
</PortalToFollowElemContent>
|
||||
|
||||
@ -104,7 +104,7 @@ describe('PopupItem', () => {
|
||||
|
||||
it('should call onSelect when clicking an active model', () => {
|
||||
const onSelect = vi.fn()
|
||||
render(<PopupItem model={makeModel()} onSelect={onSelect} />)
|
||||
render(<PopupItem model={makeModel()} onSelect={onSelect} onHide={vi.fn()} />)
|
||||
|
||||
fireEvent.click(screen.getByText('GPT-4'))
|
||||
|
||||
@ -117,6 +117,7 @@ describe('PopupItem', () => {
|
||||
<PopupItem
|
||||
model={makeModel({ models: [makeModelItem({ status: ModelStatusEnum.disabled })] })}
|
||||
onSelect={onSelect}
|
||||
onHide={vi.fn()}
|
||||
/>,
|
||||
)
|
||||
|
||||
@ -130,6 +131,7 @@ describe('PopupItem', () => {
|
||||
<PopupItem
|
||||
model={makeModel({ models: [makeModelItem({ status: ModelStatusEnum.noConfigure })] })}
|
||||
onSelect={vi.fn()}
|
||||
onHide={vi.fn()}
|
||||
/>,
|
||||
)
|
||||
|
||||
@ -149,6 +151,7 @@ describe('PopupItem', () => {
|
||||
models: [makeModelItem({ status: ModelStatusEnum.noConfigure, model_type: undefined as unknown as ModelTypeEnum })],
|
||||
})}
|
||||
onSelect={vi.fn()}
|
||||
onHide={vi.fn()}
|
||||
/>,
|
||||
)
|
||||
|
||||
@ -167,6 +170,7 @@ describe('PopupItem', () => {
|
||||
defaultModel={defaultModel}
|
||||
model={makeModel()}
|
||||
onSelect={vi.fn()}
|
||||
onHide={vi.fn()}
|
||||
/>,
|
||||
)
|
||||
|
||||
@ -174,7 +178,7 @@ describe('PopupItem', () => {
|
||||
})
|
||||
|
||||
it('should toggle collapsed state when clicking provider header', () => {
|
||||
render(<PopupItem model={makeModel()} onSelect={vi.fn()} />)
|
||||
render(<PopupItem model={makeModel()} onSelect={vi.fn()} onHide={vi.fn()} />)
|
||||
|
||||
expect(screen.getByText('GPT-4')).toBeInTheDocument()
|
||||
|
||||
@ -188,7 +192,7 @@ describe('PopupItem', () => {
|
||||
})
|
||||
|
||||
it('should show credential name when using custom provider', () => {
|
||||
render(<PopupItem model={makeModel()} onSelect={vi.fn()} />)
|
||||
render(<PopupItem model={makeModel()} onSelect={vi.fn()} onHide={vi.fn()} />)
|
||||
|
||||
expect(screen.getByText('my-api-key')).toBeInTheDocument()
|
||||
})
|
||||
@ -203,7 +207,7 @@ describe('PopupItem', () => {
|
||||
})],
|
||||
})
|
||||
|
||||
render(<PopupItem model={makeModel()} onSelect={vi.fn()} />)
|
||||
render(<PopupItem model={makeModel()} onSelect={vi.fn()} onHide={vi.fn()} />)
|
||||
|
||||
expect(screen.getByText(/modelProvider\.selector\.configureRequired/)).toBeInTheDocument()
|
||||
})
|
||||
@ -215,7 +219,7 @@ describe('PopupItem', () => {
|
||||
})],
|
||||
})
|
||||
|
||||
render(<PopupItem model={makeModel()} onSelect={vi.fn()} />)
|
||||
render(<PopupItem model={makeModel()} onSelect={vi.fn()} onHide={vi.fn()} />)
|
||||
|
||||
expect(screen.getByText(/modelProvider\.selector\.aiCredits/)).toBeInTheDocument()
|
||||
})
|
||||
@ -230,7 +234,7 @@ describe('PopupItem', () => {
|
||||
currentWorkspace: { trial_credits: 100, trial_credits_used: 100 },
|
||||
})
|
||||
|
||||
render(<PopupItem model={makeModel()} onSelect={vi.fn()} />)
|
||||
render(<PopupItem model={makeModel()} onSelect={vi.fn()} onHide={vi.fn()} />)
|
||||
|
||||
expect(screen.getByText(/modelProvider\.selector\.creditsExhausted/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
@ -4,10 +4,14 @@ import type {
|
||||
Model,
|
||||
ModelItem,
|
||||
} from '../declarations'
|
||||
import { useState } from 'react'
|
||||
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from '@/app/components/base/ui/popover'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import { useModalContext } from '@/context/modal-context'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
@ -28,6 +32,9 @@ import {
|
||||
import ModelBadge from '../model-badge'
|
||||
import ModelIcon from '../model-icon'
|
||||
import ModelName from '../model-name'
|
||||
import DropdownContent from '../provider-added-card/model-auth-dropdown/dropdown-content'
|
||||
import { useChangeProviderPriority } from '../provider-added-card/use-change-provider-priority'
|
||||
import { useCredentialPanelState } from '../provider-added-card/use-credential-panel-state'
|
||||
import {
|
||||
modelTypeFormat,
|
||||
sizeFormat,
|
||||
@ -38,13 +45,16 @@ type PopupItemProps = {
|
||||
defaultModel?: DefaultModel
|
||||
model: Model
|
||||
onSelect: (provider: string, model: ModelItem) => void
|
||||
onHide: () => void
|
||||
}
|
||||
const PopupItem: FC<PopupItemProps> = ({
|
||||
defaultModel,
|
||||
model,
|
||||
onSelect,
|
||||
onHide,
|
||||
}) => {
|
||||
const [collapsed, setCollapsed] = useState(false)
|
||||
const [dropdownOpen, setDropdownOpen] = useState(false)
|
||||
const { t } = useTranslation()
|
||||
const language = useLanguage()
|
||||
const { currentWorkspace } = useAppContext()
|
||||
@ -82,6 +92,14 @@ const PopupItem: FC<PopupItemProps> = ({
|
||||
const isApiKeyActive = currentProvider?.custom_configuration.status === CustomConfigurationStatusEnum.active
|
||||
const credentialName = currentProvider?.custom_configuration.current_credential_name
|
||||
|
||||
const state = useCredentialPanelState(currentProvider)
|
||||
const { isChangingPriority, handleChangePriority } = useChangeProviderPriority(currentProvider)
|
||||
|
||||
const handleCloseDropdown = useCallback(() => {
|
||||
setDropdownOpen(false)
|
||||
onHide()
|
||||
}, [onHide])
|
||||
|
||||
return (
|
||||
<div className="mb-1">
|
||||
<div className="flex h-[22px] items-center justify-between px-3 text-xs font-medium text-text-tertiary">
|
||||
@ -92,39 +110,53 @@ const PopupItem: FC<PopupItemProps> = ({
|
||||
{model.label[language] || model.label.en_US}
|
||||
<span className={cn('i-custom-vender-solid-general-arrow-down-round-fill h-4 w-4 text-text-quaternary', collapsed && '-rotate-90')} />
|
||||
</div>
|
||||
<div className="flex items-center text-text-tertiary system-xs-medium">
|
||||
{isUsingCredits
|
||||
? (
|
||||
hasCredits
|
||||
<Popover open={dropdownOpen} onOpenChange={setDropdownOpen}>
|
||||
<PopoverTrigger
|
||||
render={(
|
||||
<div className="flex cursor-pointer items-center text-text-tertiary system-xs-medium">
|
||||
{isUsingCredits
|
||||
? (
|
||||
<>
|
||||
<span className="i-ri-globe-line h-3 w-3" />
|
||||
<span className="ml-1">{t('modelProvider.selector.aiCredits', { ns: 'common' })}</span>
|
||||
</>
|
||||
hasCredits
|
||||
? (
|
||||
<>
|
||||
<span className="i-custom-vender-line-financeandecommerce-credits-coin h-3 w-3" />
|
||||
<span className="ml-1">{t('modelProvider.selector.aiCredits', { ns: 'common' })}</span>
|
||||
</>
|
||||
)
|
||||
: (
|
||||
<>
|
||||
<span className="i-ri-alert-fill h-3 w-3 text-text-warning-secondary" />
|
||||
<span className="ml-1 text-text-warning">{t('modelProvider.selector.creditsExhausted', { ns: 'common' })}</span>
|
||||
</>
|
||||
)
|
||||
)
|
||||
: (
|
||||
<>
|
||||
<span className="i-ri-alert-fill h-3 w-3 text-text-warning-secondary" />
|
||||
<span className="ml-1 text-text-warning">{t('modelProvider.selector.creditsExhausted', { ns: 'common' })}</span>
|
||||
</>
|
||||
)
|
||||
)
|
||||
: credentialName
|
||||
? (
|
||||
<>
|
||||
<span className={cn('h-1.5 w-1.5 shrink-0 rounded-[2px] border', isApiKeyActive ? 'border-components-badge-status-light-success-border-inner bg-components-badge-status-light-success-bg' : 'border-components-badge-status-light-error-border-inner bg-components-badge-status-light-error-bg')} />
|
||||
<span className="ml-1 text-text-tertiary">{credentialName}</span>
|
||||
</>
|
||||
)
|
||||
: (
|
||||
<>
|
||||
<span className="h-1.5 w-1.5 shrink-0 rounded-[2px] border border-components-badge-status-light-disabled-border-inner bg-components-badge-status-light-disabled-bg" />
|
||||
<span className="ml-1 text-text-tertiary">{t('modelProvider.selector.configureRequired', { ns: 'common' })}</span>
|
||||
</>
|
||||
)}
|
||||
<span className={cn('i-ri-arrow-down-s-line !h-[14px] !w-[14px] translate-y-px text-text-tertiary', collapsed && '-rotate-90')} />
|
||||
|
||||
</div>
|
||||
: credentialName
|
||||
? (
|
||||
<>
|
||||
<span className={cn('h-1.5 w-1.5 shrink-0 rounded-[2px] border', isApiKeyActive ? 'border-components-badge-status-light-success-border-inner bg-components-badge-status-light-success-bg' : 'border-components-badge-status-light-error-border-inner bg-components-badge-status-light-error-bg')} />
|
||||
<span className="ml-1 text-text-tertiary">{credentialName}</span>
|
||||
</>
|
||||
)
|
||||
: (
|
||||
<>
|
||||
<span className="h-1.5 w-1.5 shrink-0 rounded-[2px] border border-components-badge-status-light-disabled-border-inner bg-components-badge-status-light-disabled-bg" />
|
||||
<span className="ml-1 text-text-tertiary">{t('modelProvider.selector.configureRequired', { ns: 'common' })}</span>
|
||||
</>
|
||||
)}
|
||||
<span className={cn('i-ri-arrow-down-s-line !h-[14px] !w-[14px] translate-y-px text-text-tertiary', collapsed && '-rotate-90')} />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<PopoverContent placement="bottom-end" className="z-[1003]">
|
||||
<DropdownContent
|
||||
provider={currentProvider}
|
||||
state={state}
|
||||
isChangingPriority={isChangingPriority}
|
||||
onChangePriority={handleChangePriority}
|
||||
onClose={handleCloseDropdown}
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
{!collapsed && model.models.map(modelItem => (
|
||||
<Tooltip
|
||||
|
||||
@ -19,8 +19,9 @@ import { useInstallPackageFromMarketPlace } from '@/service/use-plugins'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { supportFunctionCall } from '@/utils/tool-call'
|
||||
import { getMarketplaceUrl } from '@/utils/var'
|
||||
import { ModelFeatureEnum } from '../declarations'
|
||||
import { CustomConfigurationStatusEnum, ModelFeatureEnum } from '../declarations'
|
||||
import { useLanguage, useMarketplaceAllPlugins } from '../hooks'
|
||||
import CreditsExhaustedAlert from '../provider-added-card/model-auth-dropdown/credits-exhausted-alert'
|
||||
import { MODEL_PROVIDER_QUOTA_GET_PAID, modelNameMap, providerIconMap, providerKeyToPluginId } from '../utils'
|
||||
import PopupItem from './popup-item'
|
||||
|
||||
@ -56,6 +57,9 @@ const Popup: FC<PopupProps> = ({
|
||||
const { mutateAsync: installPackageFromMarketPlace } = useInstallPackageFromMarketPlace()
|
||||
const { refreshPluginList } = useRefreshPluginList()
|
||||
const [installingProvider, setInstallingProvider] = useState<ModelProviderQuotaGetPaid | null>(null)
|
||||
const hasApiKeyFallback = useMemo(() => {
|
||||
return modelProviders.some(p => p.custom_configuration?.status === CustomConfigurationStatusEnum.active)
|
||||
}, [modelProviders])
|
||||
|
||||
const handleInstallPlugin = useCallback(async (key: ModelProviderQuotaGetPaid) => {
|
||||
if (!allPlugins || installingProvider)
|
||||
@ -101,7 +105,7 @@ const Popup: FC<PopupProps> = ({
|
||||
}, [])
|
||||
|
||||
const filteredModelList = useMemo(() => {
|
||||
return modelList.map((model) => {
|
||||
const filtered = modelList.map((model) => {
|
||||
const filteredModels = model.models
|
||||
.filter((modelItem) => {
|
||||
if (modelItem.label[language] !== undefined)
|
||||
@ -121,7 +125,17 @@ const Popup: FC<PopupProps> = ({
|
||||
})
|
||||
return { ...model, models: filteredModels }
|
||||
}).filter(model => model.models.length > 0)
|
||||
}, [language, modelList, scopeFeatures, searchText])
|
||||
|
||||
if (defaultModel?.provider) {
|
||||
const selectedIndex = filtered.findIndex(m => m.provider === defaultModel.provider)
|
||||
if (selectedIndex > 0) {
|
||||
const [selected] = filtered.splice(selectedIndex, 1)
|
||||
filtered.unshift(selected)
|
||||
}
|
||||
}
|
||||
|
||||
return filtered
|
||||
}, [defaultModel?.provider, language, modelList, scopeFeatures, searchText])
|
||||
|
||||
const marketplaceProviders = useMemo(() => {
|
||||
const installedProviders = new Set(modelList.map(m => m.provider))
|
||||
@ -158,6 +172,7 @@ const Popup: FC<PopupProps> = ({
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<CreditsExhaustedAlert hasApiKeyFallback={hasApiKeyFallback} />
|
||||
<div className="p-1">
|
||||
{
|
||||
filteredModelList.map(model => (
|
||||
@ -166,6 +181,7 @@ const Popup: FC<PopupProps> = ({
|
||||
defaultModel={defaultModel}
|
||||
model={model}
|
||||
onSelect={onSelect}
|
||||
onHide={onHide}
|
||||
/>
|
||||
))
|
||||
}
|
||||
|
||||
@ -1,24 +1,12 @@
|
||||
import type {
|
||||
ModelProvider,
|
||||
PreferredProviderTypeEnum,
|
||||
} from '../declarations'
|
||||
import type { ModelProvider } from '../declarations'
|
||||
import type { CardVariant } from './use-credential-panel-state'
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { memo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Warning from '@/app/components/base/icons/src/vender/line/alertsAndFeedback/Warning'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import Indicator from '@/app/components/header/indicator'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import {
|
||||
ConfigurationMethodEnum,
|
||||
} from '../declarations'
|
||||
import {
|
||||
useUpdateModelList,
|
||||
useUpdateModelProviders,
|
||||
} from '../hooks'
|
||||
import ModelAuthDropdown from './model-auth-dropdown'
|
||||
import SystemQuotaCard from './system-quota-card'
|
||||
import { useChangeProviderPriority } from './use-change-provider-priority'
|
||||
import { isDestructiveVariant, useCredentialPanelState } from './use-credential-panel-state'
|
||||
|
||||
type CredentialPanelProps = {
|
||||
@ -37,47 +25,8 @@ const TEXT_LABEL_VARIANTS = new Set<CardVariant>([
|
||||
const CredentialPanel = ({
|
||||
provider,
|
||||
}: CredentialPanelProps) => {
|
||||
const { t } = useTranslation()
|
||||
const queryClient = useQueryClient()
|
||||
const updateModelList = useUpdateModelList()
|
||||
const updateModelProviders = useUpdateModelProviders()
|
||||
const state = useCredentialPanelState(provider)
|
||||
const providerName = provider.provider
|
||||
const modelProviderModelListQueryKey = consoleQuery.modelProviders.models.queryKey({
|
||||
input: {
|
||||
params: {
|
||||
provider: providerName,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const { mutate: changePriority, isPending: isChangingPriority } = useMutation(
|
||||
consoleQuery.modelProviders.changePreferredProviderType.mutationOptions({
|
||||
onSuccess: () => {
|
||||
Toast.notify({ type: 'success', message: t('actionMsg.modifiedSuccessfully', { ns: 'common' }) })
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: modelProviderModelListQueryKey,
|
||||
exact: true,
|
||||
refetchType: 'none',
|
||||
})
|
||||
updateModelProviders()
|
||||
provider.configurate_methods.forEach((method) => {
|
||||
if (method === ConfigurationMethodEnum.predefinedModel)
|
||||
provider.supported_model_types.forEach(modelType => updateModelList(modelType))
|
||||
})
|
||||
},
|
||||
onError: () => {
|
||||
Toast.notify({ type: 'error', message: t('actionMsg.modifiedUnsuccessfully', { ns: 'common' }) })
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
const handleChangePriority = (key: PreferredProviderTypeEnum) => {
|
||||
changePriority({
|
||||
params: { provider: providerName },
|
||||
body: { preferred_provider_type: key },
|
||||
})
|
||||
}
|
||||
const { isChangingPriority, handleChangePriority } = useChangeProviderPriority(provider)
|
||||
|
||||
const { variant, credentialName } = state
|
||||
const isDestructive = isDestructiveVariant(variant)
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
import type { ModelProvider, PreferredProviderTypeEnum } from '../declarations'
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import { ConfigurationMethodEnum } from '../declarations'
|
||||
import { useUpdateModelList, useUpdateModelProviders } from '../hooks'
|
||||
|
||||
export function useChangeProviderPriority(provider: ModelProvider) {
|
||||
const { t } = useTranslation()
|
||||
const queryClient = useQueryClient()
|
||||
const updateModelList = useUpdateModelList()
|
||||
const updateModelProviders = useUpdateModelProviders()
|
||||
const providerName = provider.provider
|
||||
|
||||
const modelProviderModelListQueryKey = consoleQuery.modelProviders.models.queryKey({
|
||||
input: {
|
||||
params: {
|
||||
provider: providerName,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const { mutate: changePriority, isPending: isChangingPriority } = useMutation(
|
||||
consoleQuery.modelProviders.changePreferredProviderType.mutationOptions({
|
||||
onSuccess: () => {
|
||||
Toast.notify({ type: 'success', message: t('actionMsg.modifiedSuccessfully', { ns: 'common' }) })
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: modelProviderModelListQueryKey,
|
||||
exact: true,
|
||||
refetchType: 'none',
|
||||
})
|
||||
updateModelProviders()
|
||||
provider.configurate_methods.forEach((method) => {
|
||||
if (method === ConfigurationMethodEnum.predefinedModel)
|
||||
provider.supported_model_types.forEach(modelType => updateModelList(modelType))
|
||||
})
|
||||
},
|
||||
onError: () => {
|
||||
Toast.notify({ type: 'error', message: t('actionMsg.modifiedUnsuccessfully', { ns: 'common' }) })
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
const handleChangePriority = (key: PreferredProviderTypeEnum) => {
|
||||
changePriority({
|
||||
params: { provider: providerName },
|
||||
body: { preferred_provider_type: key },
|
||||
})
|
||||
}
|
||||
|
||||
return { isChangingPriority, handleChangePriority }
|
||||
}
|
||||
Reference in New Issue
Block a user