dify
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import { useModelList } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector'
|
||||
import Indicator from '@/app/components/header/indicator'
|
||||
import { type FC, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export type ModelBarProps = {
|
||||
provider: string
|
||||
model: string
|
||||
} | {}
|
||||
|
||||
const useAllModel = () => {
|
||||
const { data: textGeneration } = useModelList(ModelTypeEnum.textGeneration)
|
||||
const { data: moderation } = useModelList(ModelTypeEnum.moderation)
|
||||
const { data: rerank } = useModelList(ModelTypeEnum.rerank)
|
||||
const { data: speech2text } = useModelList(ModelTypeEnum.speech2text)
|
||||
const { data: textEmbedding } = useModelList(ModelTypeEnum.textEmbedding)
|
||||
const { data: tts } = useModelList(ModelTypeEnum.tts)
|
||||
const models = useMemo(() => {
|
||||
return textGeneration
|
||||
.concat(moderation)
|
||||
.concat(rerank)
|
||||
.concat(speech2text)
|
||||
.concat(textEmbedding)
|
||||
.concat(tts)
|
||||
}, [textGeneration, moderation, rerank, speech2text, textEmbedding, tts])
|
||||
if (!textGeneration || !moderation || !rerank || !speech2text || !textEmbedding || !tts)
|
||||
return undefined
|
||||
return models
|
||||
}
|
||||
|
||||
export const ModelBar: FC<ModelBarProps> = (props) => {
|
||||
const { t } = useTranslation()
|
||||
const modelList = useAllModel()
|
||||
if (!('provider' in props)) {
|
||||
return <Tooltip
|
||||
popupContent={t('workflow.nodes.agent.modelNotSelected')}
|
||||
triggerMethod='hover'
|
||||
>
|
||||
<div className='relative'>
|
||||
<ModelSelector
|
||||
modelList={[]}
|
||||
triggerClassName='bg-workflow-block-parma-bg !h-6 !rounded-md'
|
||||
defaultModel={undefined}
|
||||
showDeprecatedWarnIcon={false}
|
||||
readonly
|
||||
deprecatedClassName='opacity-50'
|
||||
/>
|
||||
<Indicator color={'red'} className='absolute -right-0.5 -top-0.5' />
|
||||
</div>
|
||||
</Tooltip>
|
||||
}
|
||||
const modelInstalled = modelList?.some(
|
||||
provider => provider.provider === props.provider && provider.models.some(model => model.model === props.model))
|
||||
const showWarn = modelList && !modelInstalled
|
||||
return modelList && <Tooltip
|
||||
popupContent={t('workflow.nodes.agent.modelNotInstallTooltip')}
|
||||
triggerMethod='hover'
|
||||
disabled={!modelList || modelInstalled}
|
||||
>
|
||||
<div className='relative'>
|
||||
<ModelSelector
|
||||
modelList={modelList}
|
||||
triggerClassName='bg-workflow-block-parma-bg !h-6 !rounded-md'
|
||||
defaultModel={props}
|
||||
showDeprecatedWarnIcon={false}
|
||||
readonly
|
||||
deprecatedClassName='opacity-50'
|
||||
/>
|
||||
{showWarn && <Indicator color={'red'} className='absolute -right-0.5 -top-0.5' />}
|
||||
</div>
|
||||
</Tooltip>
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import Indicator from '@/app/components/header/indicator'
|
||||
import classNames from '@/utils/classnames'
|
||||
import { memo, useMemo, useRef, useState } from 'react'
|
||||
import { useAllBuiltInTools, useAllCustomTools, useAllMCPTools, useAllWorkflowTools } from '@/service/use-tools'
|
||||
import { getIconFromMarketPlace } from '@/utils/get-icon'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Group } from '@/app/components/base/icons/src/vender/other'
|
||||
import AppIcon from '@/app/components/base/app-icon'
|
||||
|
||||
type Status = 'not-installed' | 'not-authorized' | undefined
|
||||
|
||||
export type ToolIconProps = {
|
||||
id: string
|
||||
providerName: string
|
||||
}
|
||||
|
||||
export const ToolIcon = memo(({ providerName }: ToolIconProps) => {
|
||||
const containerRef = useRef<HTMLDivElement>(null)
|
||||
const { data: buildInTools } = useAllBuiltInTools()
|
||||
const { data: customTools } = useAllCustomTools()
|
||||
const { data: workflowTools } = useAllWorkflowTools()
|
||||
const { data: mcpTools } = useAllMCPTools()
|
||||
const isDataReady = !!buildInTools && !!customTools && !!workflowTools && !!mcpTools
|
||||
const currentProvider = useMemo(() => {
|
||||
const mergedTools = [...(buildInTools || []), ...(customTools || []), ...(workflowTools || []), ...(mcpTools || [])]
|
||||
return mergedTools.find((toolWithProvider) => {
|
||||
return toolWithProvider.name === providerName || toolWithProvider.id === providerName
|
||||
})
|
||||
}, [buildInTools, customTools, providerName, workflowTools, mcpTools])
|
||||
|
||||
const providerNameParts = providerName.split('/')
|
||||
const author = providerNameParts[0]
|
||||
const name = providerNameParts[1]
|
||||
const icon = useMemo(() => {
|
||||
if (!isDataReady) return ''
|
||||
if (currentProvider) return currentProvider.icon
|
||||
const iconFromMarketPlace = getIconFromMarketPlace(`${author}/${name}`)
|
||||
return iconFromMarketPlace
|
||||
}, [author, currentProvider, name, isDataReady])
|
||||
const status: Status = useMemo(() => {
|
||||
if (!isDataReady) return undefined
|
||||
if (!currentProvider) return 'not-installed'
|
||||
if (currentProvider.is_team_authorization === false) return 'not-authorized'
|
||||
return undefined
|
||||
}, [currentProvider, isDataReady])
|
||||
const indicator = status === 'not-installed' ? 'red' : status === 'not-authorized' ? 'yellow' : undefined
|
||||
const notSuccess = (['not-installed', 'not-authorized'] as Array<Status>).includes(status)
|
||||
const { t } = useTranslation()
|
||||
const tooltip = useMemo(() => {
|
||||
if (!notSuccess) return undefined
|
||||
if (status === 'not-installed') return t('workflow.nodes.agent.toolNotInstallTooltip', { tool: name })
|
||||
if (status === 'not-authorized') return t('workflow.nodes.agent.toolNotAuthorizedTooltip', { tool: name })
|
||||
throw new Error('Unknown status')
|
||||
}, [name, notSuccess, status, t])
|
||||
const [iconFetchError, setIconFetchError] = useState(false)
|
||||
return <Tooltip
|
||||
triggerMethod='hover'
|
||||
popupContent={tooltip}
|
||||
disabled={!notSuccess}
|
||||
>
|
||||
<div
|
||||
className={classNames(
|
||||
'relative',
|
||||
)}
|
||||
ref={containerRef}
|
||||
>
|
||||
<div className="flex size-5 items-center justify-center overflow-hidden rounded-[6px] border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge">
|
||||
{(() => {
|
||||
if (iconFetchError || !icon)
|
||||
return <Group className="h-3 w-3 opacity-35" />
|
||||
if (typeof icon === 'string') {
|
||||
return <img
|
||||
src={icon}
|
||||
alt='tool icon'
|
||||
className={classNames(
|
||||
'size-3.5 h-full w-full object-cover',
|
||||
notSuccess && 'opacity-50',
|
||||
)}
|
||||
onError={() => setIconFetchError(true)}
|
||||
/>
|
||||
}
|
||||
if (typeof icon === 'object') {
|
||||
return <AppIcon
|
||||
className={classNames(
|
||||
'size-3.5 h-full w-full object-cover',
|
||||
notSuccess && 'opacity-50',
|
||||
)}
|
||||
icon={icon?.content}
|
||||
background={icon?.background}
|
||||
/>
|
||||
}
|
||||
return <Group className="h-3 w-3 opacity-35" />
|
||||
})()}
|
||||
</div>
|
||||
{indicator && <Indicator color={indicator} className="absolute -right-[1px] -top-[1px]" />}
|
||||
</div>
|
||||
</Tooltip>
|
||||
})
|
||||
|
||||
ToolIcon.displayName = 'ToolIcon'
|
||||
Reference in New Issue
Block a user