Merge branch 'feat/plugins' of https://github.com/langgenius/dify into feat/plugins

pull/12560/head
AkaraChen 1 year ago
commit d65c1218ae

@ -83,7 +83,7 @@ const AgentModelTrigger: FC<AgentModelTriggerProps> = ({
// pass // pass
} }
} }
if (providerName && !modelProvider) { if (providerName) {
const parts = providerName.split('/') const parts = providerName.split('/')
const org = parts[0] const org = parts[0]
const name = parts[1] const name = parts[1]
@ -101,7 +101,7 @@ const AgentModelTrigger: FC<AgentModelTriggerProps> = ({
setIsPluginChecked(true) setIsPluginChecked(true)
} }
})() })()
}, [providerName, modelProvider, modelId, currentProvider]) }, [providerName, modelId, currentProvider])
if (modelId && !isPluginChecked) if (modelId && !isPluginChecked)
return null return null

@ -1,5 +1,7 @@
import Tooltip from '@/app/components/base/tooltip' import Tooltip from '@/app/components/base/tooltip'
import Link from 'next/link' import Link from 'next/link'
import { SwitchPluginVersion } from '@/app/components/workflow/nodes/_base/components/switch-plugin-version'
import { useInstalledPluginList } from '@/service/use-plugins'
import { RiErrorWarningFill } from '@remixicon/react' import { RiErrorWarningFill } from '@remixicon/react'
type StatusIndicatorsProps = { type StatusIndicatorsProps = {
@ -12,9 +14,10 @@ type StatusIndicatorsProps = {
} }
const StatusIndicators = ({ needsConfiguration, modelProvider, inModelList, disabled, pluginInfo, t }: StatusIndicatorsProps) => { const StatusIndicators = ({ needsConfiguration, modelProvider, inModelList, disabled, pluginInfo, t }: StatusIndicatorsProps) => {
const { data: pluginList } = useInstalledPluginList()
const renderTooltipContent = (title: string, description?: string, linkText?: string, linkHref?: string) => { const renderTooltipContent = (title: string, description?: string, linkText?: string, linkHref?: string) => {
return ( return (
<div className='flex w-[240px] max-w-[240px] gap-1 flex-col px-1 py-1.5'> <div className='flex w-[240px] max-w-[240px] gap-1 flex-col px-1 py-1.5' onClick={e => e.stopPropagation()}>
<div className='text-text-primary title-xs-semi-bold'>{title}</div> <div className='text-text-primary title-xs-semi-bold'>{title}</div>
{description && ( {description && (
<div className='min-w-[200px] text-text-secondary body-xs-regular'> <div className='min-w-[200px] text-text-secondary body-xs-regular'>
@ -36,25 +39,44 @@ const StatusIndicators = ({ needsConfiguration, modelProvider, inModelList, disa
</div> </div>
) )
} }
// const installedPluginUniqueIdentifier = pluginList?.plugins.find(plugin => plugin.name === pluginInfo.name)?.plugin_unique_identifier
return ( return (
<> <>
{/* plugin installed and model is in model list but disabled */} {/* plugin installed and model is in model list but disabled */}
{/* plugin installed from github/local and model is not in model list */} {/* plugin installed from github/local and model is not in model list */}
{!needsConfiguration && modelProvider && disabled && ( {!needsConfiguration && modelProvider && disabled && (
<Tooltip <>
popupContent={inModelList ? t('workflow.nodes.agent.modelSelectorTooltips.deprecated') {inModelList ? (
: renderTooltipContent( <Tooltip
t('workflow.nodes.agent.modelNotSupport.title'), popupContent={t('workflow.nodes.agent.modelSelectorTooltips.deprecated')}
t('workflow.nodes.agent.modelNotSupport.desc'), asChild={false}
!pluginInfo ? t('workflow.nodes.agent.linkToPlugin') : '', needsDelay={false}
!pluginInfo ? '/plugins' : '', >
) <RiErrorWarningFill className='w-4 h-4 text-text-destructive' />
} </Tooltip>
asChild={false} ) : !pluginInfo ? (
needsDelay={!inModelList} <Tooltip
> popupContent={renderTooltipContent(
<RiErrorWarningFill className='w-4 h-4 text-text-destructive' /> t('workflow.nodes.agent.modelNotSupport.title'),
</Tooltip> t('workflow.nodes.agent.modelNotSupport.desc'),
t('workflow.nodes.agent.linkToPlugin'),
'/plugins',
)}
asChild={false}
needsDelay={true}
>
<RiErrorWarningFill className='w-4 h-4 text-text-destructive' />
</Tooltip>
) : (
<SwitchPluginVersion
tooltip={renderTooltipContent(
t('workflow.nodes.agent.modelNotSupport.title'),
t('workflow.nodes.agent.modelNotSupport.descForVersionSwitch'),
)}
uniqueIdentifier={pluginList?.plugins.find(plugin => plugin.name === pluginInfo.name)?.plugin_unique_identifier ?? ''}
/>
)}
</>
)} )}
{!modelProvider && !pluginInfo && ( {!modelProvider && !pluginInfo && (
<Tooltip <Tooltip

@ -1,4 +1,5 @@
export const tagKeys = [ export const tagKeys = [
'agent',
'search', 'search',
'image', 'image',
'videos', 'videos',

@ -61,7 +61,7 @@ export const SwitchPluginVersion: FC<SwitchPluginVersionProps> = (props) => {
} }
const { t } = useTranslation() const { t } = useTranslation()
return <Tooltip popupContent={!isShow && !isShowUpdateModal && tooltip} triggerMethod='hover'> return <Tooltip popupContent={!isShow && !isShowUpdateModal && tooltip} triggerMethod='hover'>
<div className={cn('w-fit', className)}> <div className={cn('w-fit flex items-center justify-center', className)} onClick={e => e.stopPropagation()}>
{isShowUpdateModal && pluginDetail && <PluginMutationModel {isShowUpdateModal && pluginDetail && <PluginMutationModel
onCancel={hideUpdateModal} onCancel={hideUpdateModal}
plugin={pluginManifestToCardPluginProps({ plugin={pluginManifestToCardPluginProps({

@ -27,7 +27,7 @@ const AgentLogItem = ({
const [expanded, setExpanded] = useState(false) const [expanded, setExpanded] = useState(false)
return ( return (
<div className='border-[0.5px] border-components-panel-border rounded-[10px]'> <div className='bg-background-default border-[0.5px] border-components-panel-border rounded-[10px]'>
<div <div
className={cn( className={cn(
'flex items-center pl-1.5 pt-2 pr-3 pb-2 cursor-pointer', 'flex items-center pl-1.5 pt-2 pr-3 pb-2 cursor-pointer',

@ -1,4 +1,5 @@
import { RiArrowLeftLine } from '@remixicon/react' import { RiArrowLeftLine } from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import AgentLogNavMore from './agent-log-nav-more' import AgentLogNavMore from './agent-log-nav-more'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import type { AgentLogItemWithChildren } from '@/types/workflow' import type { AgentLogItemWithChildren } from '@/types/workflow'
@ -11,10 +12,14 @@ const AgentLogNav = ({
agentOrToolLogItemStack, agentOrToolLogItemStack,
onShowAgentOrToolLog, onShowAgentOrToolLog,
}: AgentLogNavProps) => { }: AgentLogNavProps) => {
const options = agentOrToolLogItemStack.slice(2) const { t } = useTranslation()
const agentOrToolLogItemStackLength = agentOrToolLogItemStack.length
const first = agentOrToolLogItemStack[0]
const mid = agentOrToolLogItemStack.slice(1, -1)
const end = agentOrToolLogItemStack.at(-1)
return ( return (
<div className='flex items-center p-1 pr-3 h-8'> <div className='flex items-center p-1 pr-3 h-8 bg-components-panel-bg'>
<Button <Button
className='shrink-0 px-[5px]' className='shrink-0 px-[5px]'
size='small' size='small'
@ -24,32 +29,48 @@ const AgentLogNav = ({
}} }}
> >
<RiArrowLeftLine className='mr-1 w-3.5 h-3.5' /> <RiArrowLeftLine className='mr-1 w-3.5 h-3.5' />
Agent AGENT
</Button> </Button>
<div className='shrink-0 mx-0.5 system-xs-regular text-divider-deep'>/</div> <div className='shrink-0 mx-0.5 system-xs-regular text-divider-deep'>/</div>
<Button
className='shrink-0 px-[5px]'
size='small'
variant='ghost-accent'
onClick={() => {}}
>
Agent strategy
</Button>
{ {
!!options.length && ( agentOrToolLogItemStackLength > 1
? (
<Button
className='shrink-0 px-[5px]'
size='small'
variant='ghost-accent'
onClick={() => onShowAgentOrToolLog(first)}
>
{t('workflow.nodes.agent.strategy.label')}
</Button>
)
: (
<div className='flex items-center px-[5px] system-xs-medium-uppercase text-text-tertiary'>
{t('workflow.nodes.agent.strategy.label')}
</div>
)
}
{
!!mid.length && (
<> <>
<div className='shrink-0 mx-0.5 system-xs-regular text-divider-deep'>/</div> <div className='shrink-0 mx-0.5 system-xs-regular text-divider-deep'>/</div>
<AgentLogNavMore <AgentLogNavMore
options={options} options={mid}
onShowAgentOrToolLog={onShowAgentOrToolLog} onShowAgentOrToolLog={onShowAgentOrToolLog}
/> />
</> </>
) )
} }
<div className='shrink-0 mx-0.5 system-xs-regular text-divider-deep'>/</div> {
<div className='flex items-center px-[5px] system-xs-medium-uppercase text-text-tertiary'> !!end && agentOrToolLogItemStackLength > 2 && (
Run Actions <>
</div> <div className='shrink-0 mx-0.5 system-xs-regular text-divider-deep'>/</div>
<div className='flex items-center px-[5px] system-xs-medium-uppercase text-text-tertiary'>
{end.label}
</div>
</>
)
}
</div> </div>
) )
} }

@ -1,4 +1,5 @@
import { RiArrowRightLine } from '@remixicon/react' import { RiArrowRightLine } from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import type { import type {
AgentLogItemWithChildren, AgentLogItemWithChildren,
NodeTracing, NodeTracing,
@ -12,12 +13,13 @@ const AgentLogTrigger = ({
nodeInfo, nodeInfo,
onShowAgentOrToolLog, onShowAgentOrToolLog,
}: AgentLogTriggerProps) => { }: AgentLogTriggerProps) => {
const { t } = useTranslation()
const { agentLog } = nodeInfo const { agentLog } = nodeInfo
return ( return (
<div className='bg-components-button-tertiary-bg rounded-[10px]'> <div className='bg-components-button-tertiary-bg rounded-[10px]'>
<div className='flex items-center px-3 pt-2 system-2xs-medium-uppercase text-text-tertiary'> <div className='flex items-center px-3 pt-2 system-2xs-medium-uppercase text-text-tertiary'>
Agent strategy {t('workflow.nodes.agent.strategy.label')}
</div> </div>
<div className='flex items-center pl-3 pt-1 pr-2 pb-1.5'> <div className='flex items-center pl-3 pt-1 pr-2 pb-1.5'>
<div className='shrink-0 w-5 h-5'></div> <div className='shrink-0 w-5 h-5'></div>
@ -28,7 +30,7 @@ const AgentLogTrigger = ({
onShowAgentOrToolLog({ id: nodeInfo.id, children: agentLog || [] } as AgentLogItemWithChildren) onShowAgentOrToolLog({ id: nodeInfo.id, children: agentLog || [] } as AgentLogItemWithChildren)
}} }}
> >
Detail {t('runLog.detail')}
<RiArrowRightLine className='ml-0.5 w-3.5 h-3.5' /> <RiArrowRightLine className='ml-0.5 w-3.5 h-3.5' />
</div> </div>
</div> </div>

@ -1,4 +1,5 @@
import { RiAlertFill } from '@remixicon/react' import { RiAlertFill } from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import AgentLogItem from './agent-log-item' import AgentLogItem from './agent-log-item'
import AgentLogNav from './agent-log-nav' import AgentLogNav from './agent-log-nav'
import type { AgentLogItemWithChildren } from '@/types/workflow' import type { AgentLogItemWithChildren } from '@/types/workflow'
@ -13,17 +14,18 @@ const AgentResultPanel = ({
agentOrToolLogListMap, agentOrToolLogListMap,
onShowAgentOrToolLog, onShowAgentOrToolLog,
}: AgentResultPanelProps) => { }: AgentResultPanelProps) => {
const { t } = useTranslation()
const top = agentOrToolLogItemStack[agentOrToolLogItemStack.length - 1] const top = agentOrToolLogItemStack[agentOrToolLogItemStack.length - 1]
const list = agentOrToolLogListMap[top.id] const list = agentOrToolLogListMap[top.id]
return ( return (
<div className='overflow-y-auto'> <div className='bg-background-section overflow-y-auto'>
<AgentLogNav <AgentLogNav
agentOrToolLogItemStack={agentOrToolLogItemStack} agentOrToolLogItemStack={agentOrToolLogItemStack}
onShowAgentOrToolLog={onShowAgentOrToolLog} onShowAgentOrToolLog={onShowAgentOrToolLog}
/> />
{ {
<div className='p-2'> <div className='p-2 space-y-1'>
{ {
list.map(item => ( list.map(item => (
<AgentLogItem <AgentLogItem
@ -37,7 +39,7 @@ const AgentResultPanel = ({
} }
{ {
top.hasCircle && ( top.hasCircle && (
<div className='flex items-center rounded-xl px-3 pr-2 border border-components-panel-border bg-components-panel-bg-blur shadow-md'> <div className='flex items-center mt-1 rounded-xl px-3 pr-2 border border-components-panel-border bg-components-panel-bg-blur shadow-md'>
<div <div
className='absolute inset-0 opacity-[0.4] rounded-xl' className='absolute inset-0 opacity-[0.4] rounded-xl'
style={{ style={{
@ -46,7 +48,7 @@ const AgentResultPanel = ({
></div> ></div>
<RiAlertFill className='mr-1.5 w-4 h-4 text-text-warning-secondary' /> <RiAlertFill className='mr-1.5 w-4 h-4 text-text-warning-secondary' />
<div className='system-xs-medium text-text-primary'> <div className='system-xs-medium text-text-primary'>
There is circular invocation of tools/nodes in the current workflow. {t('runLog.circularInvocationTip')}
</div> </div>
</div> </div>
) )

@ -2,6 +2,7 @@ const translation = {
allTags: 'All Tags', allTags: 'All Tags',
searchTags: 'Search Tags', searchTags: 'Search Tags',
tags: { tags: {
agent: 'Agent',
search: 'Search', search: 'Search',
image: 'Image', image: 'Image',
videos: 'Videos', videos: 'Videos',

@ -24,6 +24,8 @@ const translation = {
link: 'detail panel', link: 'detail panel',
tipRight: ' view it.', tipRight: ' view it.',
}, },
actionLogs: 'Action Logs',
circularInvocationTip: 'There is circular invocation of tools/nodes in the current workflow.',
} }
export default translation export default translation

@ -725,6 +725,7 @@ const translation = {
modelNotSupport: { modelNotSupport: {
title: 'Unsupported Model', title: 'Unsupported Model',
desc: 'The installed plugin version does not provide this model.', desc: 'The installed plugin version does not provide this model.',
descForVersionSwitch: 'The installed plugin version does not provide this model. Click to switch version.',
}, },
configureModel: 'Configure Model', configureModel: 'Configure Model',
notAuthorized: 'Not Authorized', notAuthorized: 'Not Authorized',

@ -2,6 +2,7 @@ const translation = {
allTags: '所有标签', allTags: '所有标签',
searchTags: '搜索标签', searchTags: '搜索标签',
tags: { tags: {
agent: 'Agent',
search: '搜索', search: '搜索',
image: '图片', image: '图片',
videos: '视频', videos: '视频',

@ -24,6 +24,8 @@ const translation = {
link: '详细信息面板', link: '详细信息面板',
tipRight: '查看它。', tipRight: '查看它。',
}, },
actionLogs: 'Action 日志',
circularInvocationTip: '当前工作流中存在工具/节点的循环调用。',
} }
export default translation export default translation

@ -725,6 +725,7 @@ const translation = {
modelNotSupport: { modelNotSupport: {
title: '不支持的模型', title: '不支持的模型',
desc: '已安装的插件版本不提供此模型。', desc: '已安装的插件版本不提供此模型。',
descForVersionSwitch: '已安装的插件版本不提供此模型。点击切换版本。',
}, },
model: '模型', model: '模型',
toolbox: '工具箱', toolbox: '工具箱',

Loading…
Cancel
Save