refactor: strategy status

This commit is contained in:
AkaraChen 2025-01-03 15:25:10 +08:00
parent 2296bb162b
commit fbf9984d85
5 changed files with 78 additions and 52 deletions

View File

@ -1,4 +1,5 @@
import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '@/app/components/base/portal-to-follow-elem'
import type { ReactNode } from 'react'
import { memo, useMemo, useState } from 'react'
import type { Strategy } from './agent-strategy'
import classNames from '@/utils/classnames'
@ -16,30 +17,31 @@ import type { StrategyPluginDetail } from '@/app/components/plugins/types'
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
const NotFoundWarn = (props: {
title: ReactNode,
description: ReactNode
}) => {
// strategyStatus can be 'plugin-not-found-and-not-in-marketplace' | 'strategy-not-found'
const { strategyStatus } = props
const { title, description } = props
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>
<p>
<Link href={'/plugins'} className='text-text-accent tracking-tight'>
{t('workflow.nodes.agent.linkToPlugin')}
</Link>
</p>
</div>}
popupContent={
<div className='space-y-1 text-xs'>
<h3 className='text-text-primary font-semibold'>
{title}
</h3>
<p className='text-text-secondary tracking-tight'>
{description}
</p>
<p>
<Link href={'/plugins'} className='text-text-accent tracking-tight'>
{t('workflow.nodes.agent.linkToPlugin')}
</Link>
</p>
</div>
}
needsDelay
>
<div>
@ -98,8 +100,18 @@ export const AgentStrategySelector = memo((props: AgentStrategySelectorProps) =>
value?.agent_strategy_provider_name,
value?.agent_strategy_name,
)
const showError = ['strategy-not-found', 'plugin-not-found-and-not-in-marketplace']
.includes(strategyStatus)
const showPluginNotInstalledWarn = strategyStatus?.plugin?.source === 'external'
&& !strategyStatus.plugin.installed
const showUnsupportedStrategy = strategyStatus?.plugin.source === 'external'
&& strategyStatus.strategy === 'not-found'
const showSwitchVersion = strategyStatus?.strategy === 'not-found'
&& strategyStatus.plugin.source === 'marketplace' && strategyStatus.plugin.installed
const showInstallButton = strategyStatus?.strategy === 'not-found'
&& strategyStatus.plugin.source === 'marketplace' && !strategyStatus.plugin.installed
const icon = list?.find(
coll => coll.tools?.find(tool => tool.name === value?.agent_strategy_name),
)?.icon as string | undefined
@ -125,16 +137,23 @@ 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
{showInstallButton && <InstallPluginButton
onClick={e => e.stopPropagation()}
size={'small'}
uniqueIdentifier={value.plugin_unique_identifier}
/>}
{showError
? <NotInstallWarn
strategyStatus={strategyStatus}
{showPluginNotInstalledWarn
? <NotFoundWarn
title={t('workflow.nodes.agent.pluginNotInstalled')}
description={t('workflow.nodes.agent.pluginNotInstalledDesc')}
/>
: <RiArrowDownSLine className='size-4 text-text-tertiary' />}
: showUnsupportedStrategy
? <NotFoundWarn
title={t('workflow.nodes.agent.unsupportedStrategy')}
description={t('workflow.nodes.agent.strategyNotFoundDesc')}
/>
: <RiArrowDownSLine className='size-4 text-text-tertiary' />
}
</div>}
</div>
</PortalToFollowElemTrigger>

View File

@ -89,20 +89,14 @@ const AgentNode: FC<NodeProps<AgentNodeType>> = (props) => {
{inputs.agent_strategy_name
? <SettingItem
label={t('workflow.nodes.agent.strategy.shortLabel')}
status={
['plugin-not-found', 'strategy-not-found', 'plugin-not-found-and-not-in-marketplace'].includes(currentStrategyStatus)
? 'error'
: undefined
}
status={currentStrategyStatus?.strategy === 'not-found' ? 'error' : 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
currentStrategyStatus?.strategy === 'not-found' ? t('workflow.nodes.agent.strategyNotInstallTooltip', {
plugin: pluginDetail?.declaration.label
? renderI18nObject(pluginDetail?.declaration.label)
: undefined,
strategy: inputs.agent_strategy_label,
}) : undefined
}
>
{inputs.agent_strategy_label}

View File

@ -13,7 +13,13 @@ import type { Var } from '../../types'
import { VarType as VarKindType } from '../../types'
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 type StrategyStatus = {
plugin: {
source: 'external' | 'marketplace'
installed: boolean
}
strategy: 'not-found' | 'normal'
}
export const useStrategyInfo = (
strategyProviderName?: string,
@ -29,16 +35,19 @@ export const useStrategyInfo = (
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'
const strategyStatus: StrategyStatus | undefined = useMemo(() => {
if (strategyProvider.isLoading || marketplace.isLoading)
return undefined
const strategyExist = !!strategy
const isPluginInstalled = !strategyProvider.isError
const isInMarketplace = !!marketplace.data?.data.plugins.at(0)
return {
plugin: {
source: isInMarketplace ? 'marketplace' : 'external',
installed: isPluginInstalled,
},
strategy: strategyExist ? 'normal' : 'not-found',
}
if (!strategy) return 'strategy-not-found'
return 'success'
}, [strategy, marketplace, strategyProvider.isError, strategyProvider.isLoading])
return {
strategyProvider,

View File

@ -733,8 +733,10 @@ const translation = {
toolNotInstallTooltip: '{{tool}} is not installed',
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',
unsupportedStrategy: 'Unsupported strategy',
pluginNotFoundDesc: 'This plugin is installed from GitHub. Please go to Plugins to reinstall',
strategyNotFoundDesc: 'The installed plugin version does not provide this strategy.',
strategyNotFoundDescAndSwitchVersion: 'The installed plugin version does not provide this strategy. Click to switch version.',
modelSelectorTooltips: {
deprecated: 'This model is deprecated',
},

View File

@ -733,8 +733,10 @@ const translation = {
toolNotInstallTooltip: '{{tool}} 未安装',
toolNotAuthorizedTooltip: '{{tool}} 未授权',
strategyNotInstallTooltip: '{{strategy}} 未安装',
strategyNotInstallAndNotInMarketplace: '{{strategy}} 未安装且未在市场中找到',
strategyNotFoundInPlugin: '在 {{plugin}} 中未找到 {{strategy}}',
unsupportedStrategy: '不支持的策略',
strategyNotFoundDesc: '安装的插件版本不提供此策略。',
pluginNotFoundDesc: '此插件安装自 GitHub。请转到插件重新安装。',
strategyNotFoundDescAndSwitchVersion: '安装的插件版本不提供此策略。点击切换版本。',
modelSelectorTooltips: {
deprecated: '此模型已弃用',
},