mirror of
https://github.com/langgenius/dify.git
synced 2026-01-06 06:26:00 +00:00
refactor: strategy status
This commit is contained in:
@@ -17,15 +17,27 @@ import type { ToolWithProvider } from '../../../types'
|
||||
import { CollectionType } from '@/app/components/tools/types'
|
||||
import useGetIcon from '@/app/components/plugins/install-plugin/base/use-get-icon'
|
||||
import type { StrategyStatus } from '../../agent/use-config'
|
||||
import { useStrategyInfo } from '../../agent/use-config'
|
||||
|
||||
const NotInstallWarn = (props: {
|
||||
strategyStatus: StrategyStatus
|
||||
}) => {
|
||||
// strategyStatus can be 'plugin-not-found-and-not-in-marketplace' | 'strategy-not-found'
|
||||
const { strategyStatus } = props
|
||||
|
||||
const ExternalNotInstallWarn = () => {
|
||||
const { t } = useTranslation()
|
||||
return <Tooltip
|
||||
popupContent={<div className='space-y-1 text-xs'>
|
||||
<h3 className='text-text-primary font-semibold'>{t('workflow.nodes.agent.pluginNotInstalled')}</h3>
|
||||
<p className='text-text-secondary tracking-tight'>{t('workflow.nodes.agent.pluginNotInstalledDesc')}</p>
|
||||
<h3 className='text-text-primary font-semibold'>
|
||||
{t('workflow.nodes.agent.pluginNotInstalled')}
|
||||
</h3>
|
||||
<p className='text-text-secondary tracking-tight'>
|
||||
{t('workflow.nodes.agent.pluginNotInstalledDesc')}
|
||||
</p>
|
||||
<p>
|
||||
<Link href={'/plugins'} className='text-text-accent tracking-tight'>{t('workflow.nodes.agent.linkToPlugin')}</Link>
|
||||
<Link href={'/plugins'} className='text-text-accent tracking-tight'>
|
||||
{t('workflow.nodes.agent.linkToPlugin')}
|
||||
</Link>
|
||||
</p>
|
||||
</div>}
|
||||
needsDelay
|
||||
@@ -68,11 +80,10 @@ function formatStrategy(input: StrategyPluginDetail[], getIcon: (i: string) => s
|
||||
export type AgentStrategySelectorProps = {
|
||||
value?: Strategy,
|
||||
onChange: (value?: Strategy) => void,
|
||||
strategyStatus?: StrategyStatus
|
||||
}
|
||||
|
||||
export const AgentStrategySelector = memo((props: AgentStrategySelectorProps) => {
|
||||
const { value, onChange, strategyStatus } = props
|
||||
const { value, onChange } = props
|
||||
const [open, setOpen] = useState(false)
|
||||
const [viewType, setViewType] = useState<ViewType>(ViewType.flat)
|
||||
const [query, setQuery] = useState('')
|
||||
@@ -83,14 +94,23 @@ export const AgentStrategySelector = memo((props: AgentStrategySelectorProps) =>
|
||||
if (!list) return []
|
||||
return list.filter(tool => tool.name.toLowerCase().includes(query.toLowerCase()))
|
||||
}, [query, list])
|
||||
const showError = (['plugin-not-found', 'strategy-not-found'] as Array<undefined | StrategyStatus>).includes(strategyStatus)
|
||||
const { strategyStatus } = useStrategyInfo(
|
||||
value?.agent_strategy_provider_name,
|
||||
value?.agent_strategy_name,
|
||||
)
|
||||
const showError = ['strategy-not-found', 'plugin-not-found-and-not-in-marketplace']
|
||||
.includes(strategyStatus)
|
||||
const icon = list?.find(
|
||||
coll => coll.tools?.find(tool => tool.name === value?.agent_strategy_name),
|
||||
)?.icon as string | undefined
|
||||
const { t } = useTranslation()
|
||||
|
||||
return <PortalToFollowElem open={open} onOpenChange={setOpen} placement='bottom'>
|
||||
<PortalToFollowElemTrigger className='w-full'>
|
||||
<div className='h-8 p-1 gap-0.5 flex items-center rounded-lg bg-components-input-bg-normal w-full hover:bg-state-base-hover-alt select-none' onClick={() => setOpen(o => !o)}>
|
||||
<div
|
||||
className='h-8 p-1 gap-0.5 flex items-center rounded-lg bg-components-input-bg-normal w-full hover:bg-state-base-hover-alt select-none'
|
||||
onClick={() => setOpen(o => !o)}
|
||||
>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
{icon && <div className='flex items-center justify-center w-6 h-6'><img
|
||||
src={icon}
|
||||
@@ -105,8 +125,16 @@ export const AgentStrategySelector = memo((props: AgentStrategySelectorProps) =>
|
||||
{value?.agent_strategy_label || t('workflow.nodes.agent.strategy.selectTip')}
|
||||
</p>
|
||||
{value && <div className='ml-auto flex items-center gap-1'>
|
||||
{strategyStatus === 'plugin-not-found' && <InstallPluginButton onClick={e => e.stopPropagation()} size={'small'} uniqueIdentifier={value.plugin_unique_identifier} />}
|
||||
{showError ? <ExternalNotInstallWarn /> : <RiArrowDownSLine className='size-4 text-text-tertiary' />}
|
||||
{strategyStatus === 'plugin-not-found' && <InstallPluginButton
|
||||
onClick={e => e.stopPropagation()}
|
||||
size={'small'}
|
||||
uniqueIdentifier={value.plugin_unique_identifier}
|
||||
/>}
|
||||
{showError
|
||||
? <NotInstallWarn
|
||||
strategyStatus={strategyStatus}
|
||||
/>
|
||||
: <RiArrowDownSLine className='size-4 text-text-tertiary' />}
|
||||
</div>}
|
||||
</div>
|
||||
</PortalToFollowElemTrigger>
|
||||
|
||||
@@ -19,7 +19,6 @@ import { useWorkflowStore } from '../../../store'
|
||||
import { useRenderI18nObject } from '@/hooks/use-i18n'
|
||||
import type { NodeOutPutVar } from '../../../types'
|
||||
import type { Node } from 'reactflow'
|
||||
import type { StrategyStatus } from '../../agent/use-config'
|
||||
|
||||
export type Strategy = {
|
||||
agent_strategy_provider_name: string
|
||||
@@ -37,7 +36,6 @@ export type AgentStrategyProps = {
|
||||
onFormValueChange: (value: ToolVarInputs) => void
|
||||
nodeOutputVars?: NodeOutPutVar[],
|
||||
availableNodes?: Node[],
|
||||
strategyStatus: StrategyStatus
|
||||
}
|
||||
|
||||
type CustomSchema<Type, Field = {}> = Omit<CredentialFormSchema, 'type'> & { type: Type } & Field
|
||||
@@ -56,7 +54,7 @@ type StringSchema = CustomSchema<'string', {
|
||||
type CustomField = ToolSelectorSchema | MultipleToolSelectorSchema | StringSchema
|
||||
|
||||
export const AgentStrategy = memo((props: AgentStrategyProps) => {
|
||||
const { strategy, onStrategyChange, formSchema, formValue, onFormValueChange, nodeOutputVars, availableNodes, strategyStatus } = props
|
||||
const { strategy, onStrategyChange, formSchema, formValue, onFormValueChange, nodeOutputVars, availableNodes } = props
|
||||
const { t } = useTranslation()
|
||||
const defaultModel = useDefaultModel(ModelTypeEnum.textGeneration)
|
||||
const renderI18nObject = useRenderI18nObject()
|
||||
@@ -178,7 +176,7 @@ export const AgentStrategy = memo((props: AgentStrategyProps) => {
|
||||
}
|
||||
}
|
||||
return <div className='space-y-2'>
|
||||
<AgentStrategySelector value={strategy} onChange={onStrategyChange} strategyStatus={strategyStatus} />
|
||||
<AgentStrategySelector value={strategy} onChange={onStrategyChange} />
|
||||
{
|
||||
strategy
|
||||
? <div>
|
||||
|
||||
@@ -90,16 +90,20 @@ const AgentNode: FC<NodeProps<AgentNodeType>> = (props) => {
|
||||
? <SettingItem
|
||||
label={t('workflow.nodes.agent.strategy.shortLabel')}
|
||||
status={
|
||||
['plugin-not-found', 'strategy-not-found'].includes(currentStrategyStatus)
|
||||
['plugin-not-found', 'strategy-not-found', 'plugin-not-found-and-not-in-marketplace'].includes(currentStrategyStatus)
|
||||
? 'error'
|
||||
: undefined
|
||||
}
|
||||
tooltip={t(`workflow.nodes.agent.${currentStrategyStatus === 'plugin-not-found' ? 'strategyNotInstallTooltip' : 'strategyNotFoundInPlugin'}`, {
|
||||
strategy: inputs.agent_strategy_label,
|
||||
plugin: pluginDetail?.declaration.label
|
||||
? renderI18nObject(pluginDetail?.declaration.label)
|
||||
: undefined,
|
||||
})}
|
||||
tooltip={
|
||||
['plugin-not-found', 'strategy-not-found', 'plugin-not-found-and-not-in-marketplace'].includes(currentStrategyStatus)
|
||||
? t('workflow.nodes.agent.strategyNotInstallTooltip', {
|
||||
plugin: pluginDetail?.declaration.label
|
||||
? renderI18nObject(pluginDetail?.declaration.label)
|
||||
: undefined,
|
||||
strategy: inputs.agent_strategy_label,
|
||||
})
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{inputs.agent_strategy_label}
|
||||
</SettingItem>
|
||||
|
||||
@@ -30,7 +30,6 @@ const AgentPanel: FC<NodePanelProps<AgentNodeType>> = (props) => {
|
||||
inputs,
|
||||
setInputs,
|
||||
currentStrategy,
|
||||
currentStrategyStatus,
|
||||
formData,
|
||||
onFormChange,
|
||||
|
||||
@@ -96,7 +95,6 @@ const AgentPanel: FC<NodePanelProps<AgentNodeType>> = (props) => {
|
||||
onFormValueChange={onFormChange}
|
||||
nodeOutputVars={availableVars}
|
||||
availableNodes={availableNodesWithParent}
|
||||
strategyStatus={currentStrategyStatus}
|
||||
/>
|
||||
</Field>
|
||||
<div>
|
||||
|
||||
@@ -15,6 +15,38 @@ import useAvailableVarList from '../_base/hooks/use-available-var-list'
|
||||
|
||||
export type StrategyStatus = 'loading' | 'plugin-not-found' | 'plugin-not-found-and-not-in-marketplace' | 'strategy-not-found' | 'success'
|
||||
|
||||
export const useStrategyInfo = (
|
||||
strategyProviderName?: string,
|
||||
strategyName?: string,
|
||||
) => {
|
||||
const strategyProvider = useStrategyProviderDetail(
|
||||
strategyProviderName || '',
|
||||
{ retry: false },
|
||||
)
|
||||
const strategy = strategyProvider.data?.declaration.strategies.find(
|
||||
str => str.identity.name === strategyName,
|
||||
)
|
||||
const marketplace = useFetchPluginsInMarketPlaceByIds([strategyProviderName!], {
|
||||
retry: false,
|
||||
})
|
||||
const strategyStatus: StrategyStatus = useMemo(() => {
|
||||
if (strategyProvider.isLoading || marketplace.isLoading) return 'loading'
|
||||
if (strategyProvider.isError) {
|
||||
if (marketplace.data && marketplace.data.data.plugins.length === 0)
|
||||
return 'plugin-not-found-and-not-in-marketplace'
|
||||
|
||||
return 'plugin-not-found'
|
||||
}
|
||||
if (!strategy) return 'strategy-not-found'
|
||||
return 'success'
|
||||
}, [strategy, marketplace, strategyProvider.isError, strategyProvider.isLoading])
|
||||
return {
|
||||
strategyProvider,
|
||||
strategy,
|
||||
strategyStatus,
|
||||
}
|
||||
}
|
||||
|
||||
const useConfig = (id: string, payload: AgentNodeType) => {
|
||||
const { nodesReadOnly: readOnly } = useNodesReadOnly()
|
||||
const { inputs, setInputs } = useNodeCrud<AgentNodeType>(id, payload)
|
||||
@@ -23,27 +55,14 @@ const useConfig = (id: string, payload: AgentNodeType) => {
|
||||
inputs,
|
||||
setInputs,
|
||||
})
|
||||
const strategyProvider = useStrategyProviderDetail(
|
||||
inputs.agent_strategy_provider_name || '',
|
||||
{ retry: false },
|
||||
const {
|
||||
strategyStatus: currentStrategyStatus,
|
||||
strategy: currentStrategy,
|
||||
strategyProvider,
|
||||
} = useStrategyInfo(
|
||||
inputs.agent_strategy_provider_name,
|
||||
inputs.agent_strategy_name,
|
||||
)
|
||||
const currentStrategy = strategyProvider.data?.declaration.strategies.find(
|
||||
str => str.identity.name === inputs.agent_strategy_name,
|
||||
)
|
||||
const marketplace = useFetchPluginsInMarketPlaceByIds([inputs.agent_strategy_provider_name!], {
|
||||
retry: false,
|
||||
})
|
||||
const currentStrategyStatus: StrategyStatus = useMemo(() => {
|
||||
if (strategyProvider.isLoading || marketplace.isLoading) return 'loading'
|
||||
if (strategyProvider.isError) {
|
||||
if (marketplace.data && marketplace.data.data.plugins.length === 0)
|
||||
return 'plugin-not-found-and-not-in-marketplace'
|
||||
|
||||
return 'plugin-not-found'
|
||||
}
|
||||
if (!currentStrategy) return 'strategy-not-found'
|
||||
return 'success'
|
||||
}, [currentStrategy, marketplace, strategyProvider.isError, strategyProvider.isLoading])
|
||||
console.log('currentStrategyStatus', currentStrategyStatus)
|
||||
const pluginId = inputs.agent_strategy_provider_name?.split('/').splice(0, 2).join('/')
|
||||
const pluginDetail = useCheckInstalled({
|
||||
|
||||
@@ -734,6 +734,7 @@ const translation = {
|
||||
toolNotAuthorizedTooltip: '{{tool}} Not Authorized',
|
||||
strategyNotInstallTooltip: '{{strategy}} is not installed',
|
||||
strategyNotFoundInPlugin: '{{strategy}} is not found in {{plugin}}',
|
||||
strategyNotInstallAndNotInMarketplace: '{{strategy}} is not installed and not found in Marketplace',
|
||||
modelSelectorTooltips: {
|
||||
deprecated: 'This model is deprecated',
|
||||
},
|
||||
|
||||
@@ -733,6 +733,7 @@ const translation = {
|
||||
toolNotInstallTooltip: '{{tool}} 未安装',
|
||||
toolNotAuthorizedTooltip: '{{tool}} 未授权',
|
||||
strategyNotInstallTooltip: '{{strategy}} 未安装',
|
||||
strategyNotInstallAndNotInMarketplace: '{{strategy}} 未安装且未在市场中找到',
|
||||
strategyNotFoundInPlugin: '在 {{plugin}} 中未找到 {{strategy}}',
|
||||
modelSelectorTooltips: {
|
||||
deprecated: '此模型已弃用',
|
||||
|
||||
Reference in New Issue
Block a user