feat: hide mcp tab agentey not support

pull/22091/head
Joel 12 months ago
parent 3000f87b53
commit 7a76f38d90

@ -26,6 +26,7 @@ type Props = {
nodeOutputVars: NodeOutPutVar[],
availableNodes: Node[],
nodeId?: string
canChooseMCPTool?: boolean
}
const MultipleToolSelector = ({
@ -40,6 +41,7 @@ const MultipleToolSelector = ({
nodeOutputVars,
availableNodes,
nodeId,
canChooseMCPTool,
}: Props) => {
const { t } = useTranslation()
const enabledCount = value.filter(item => item.enabled).length
@ -155,7 +157,7 @@ const MultipleToolSelector = ({
}
panelShowState={panelShowState}
onPanelShowStateChange={setPanelShowState}
canChooseMCPTool={canChooseMCPTool}
/>
{value.length === 0 && (
<div className='system-xs-regular flex justify-center rounded-[10px] bg-background-section p-3 text-text-tertiary'>{t('plugin.detailPanel.toolSelector.empty')}</div>
@ -173,6 +175,7 @@ const MultipleToolSelector = ({
onSelectMultiple={handleAddMultiple}
onDelete={() => handleDelete(index)}
supportEnableSwitch
canChooseMCPTool={canChooseMCPTool}
/>
</div>
))}

@ -68,6 +68,7 @@ type Props = {
nodeOutputVars: NodeOutPutVar[],
availableNodes: Node[],
nodeId?: string,
canChooseMCPTool?: boolean,
}
const ToolSelector: FC<Props> = ({
value,
@ -88,6 +89,7 @@ const ToolSelector: FC<Props> = ({
nodeOutputVars,
availableNodes,
nodeId = '',
canChooseMCPTool,
}) => {
const { t } = useTranslation()
const [isShow, onShowChange] = useState(false)
@ -308,6 +310,7 @@ const ToolSelector: FC<Props> = ({
onSelectMultiple={handleSelectMultipleTool}
scope={scope}
selectedTools={selectedTools}
canChooseMCPTool={canChooseMCPTool}
/>
</div>
<div className='flex flex-col gap-1'>

@ -449,9 +449,14 @@ export type StrategyDeclaration = {
strategies: StrategyDetail[]
}
export type PluginMeta = {
version: string // the version of dify sdk
}
export type StrategyPluginDetail = {
provider: string
plugin_unique_identifier: string
plugin_id: string
declaration: StrategyDeclaration
meta: PluginMeta
}

@ -83,6 +83,7 @@ const Tabs: FC<TabsProps> = ({
customTools={customTools || []}
workflowTools={workflowTools || []}
mcpTools={mcpTools || []}
isHideMCPTools={false}
/>
)
}

@ -39,6 +39,7 @@ type Props = {
supportAddCustomTool?: boolean
scope?: string
selectedTools?: ToolValue[]
canChooseMCPTool?: boolean
}
const ToolPicker: FC<Props> = ({
@ -54,6 +55,7 @@ const ToolPicker: FC<Props> = ({
scope = 'all',
selectedTools,
panelClassName,
canChooseMCPTool,
}) => {
const { t } = useTranslation()
const [searchText, setSearchText] = useState('')
@ -175,8 +177,8 @@ const ToolPicker: FC<Props> = ({
customTools={customToolList || []}
workflowTools={workflowToolList || []}
mcpTools={mcpTools || []}
selectedTools={selectedTools}
isHideMCPTools={!canChooseMCPTool}
/>
</div>
</PortalToFollowElemContent>

@ -69,6 +69,7 @@ const ToolItem: FC<Props> = ({
output_schema: payload.output_schema,
paramSchemas: payload.parameters,
params,
meta: provider.meta,
})
}}
>

@ -1,3 +1,5 @@
import type { PluginMeta } from '../../plugins/types'
export enum TabsEnum {
Blocks = 'blocks',
Tools = 'tools',
@ -31,6 +33,7 @@ export type ToolDefaultValue = {
params: Record<string, any>
paramSchemas: Record<string, any>[]
output_schema: Record<string, any>
meta: PluginMeta
}
export type ToolValue = {

@ -67,6 +67,7 @@ function formatStrategy(input: StrategyPluginDetail[], getIcon: (i: string) => s
icon: getIcon(item.declaration.identity.icon),
label: item.declaration.identity.label as any,
type: CollectionType.all,
meta: item.meta,
tools: item.declaration.strategies.map(strategy => ({
name: strategy.identity.name,
author: strategy.identity.author,
@ -210,6 +211,7 @@ export const AgentStrategySelector = memo((props: AgentStrategySelectorProps) =>
agent_strategy_label: tool!.tool_label,
agent_output_schema: tool!.output_schema,
plugin_unique_identifier: tool!.provider_id,
meta: tool!.meta,
})
setOpen(false)
}}

@ -22,6 +22,8 @@ import type { Node } from 'reactflow'
import { useContext } from 'use-context-selector'
import I18n from '@/context/i18n'
import { LanguagesSupported } from '@/i18n/language'
import type { PluginMeta } from '@/app/components/plugins/types'
import { noop } from 'lodash'
export type Strategy = {
agent_strategy_provider_name: string
@ -29,6 +31,7 @@ export type Strategy = {
agent_strategy_label: string
agent_output_schema: Record<string, any>
plugin_unique_identifier: string
meta?: PluginMeta
}
export type AgentStrategyProps = {
@ -40,6 +43,7 @@ export type AgentStrategyProps = {
nodeOutputVars?: NodeOutPutVar[],
availableNodes?: Node[],
nodeId?: string
canChooseMCPTool?: boolean
}
type CustomSchema<Type, Field = {}> = Omit<CredentialFormSchema, 'type'> & { type: Type } & Field
@ -50,7 +54,7 @@ type MultipleToolSelectorSchema = CustomSchema<'array[tools]'>
type CustomField = ToolSelectorSchema | MultipleToolSelectorSchema
export const AgentStrategy = memo((props: AgentStrategyProps) => {
const { strategy, onStrategyChange, formSchema, formValue, onFormValueChange, nodeOutputVars, availableNodes, nodeId } = props
const { strategy, onStrategyChange, formSchema, formValue, onFormValueChange, nodeOutputVars, availableNodes, nodeId, canChooseMCPTool } = props
const { t } = useTranslation()
const { locale } = useContext(I18n)
const defaultModel = useDefaultModel(ModelTypeEnum.textGeneration)
@ -166,6 +170,8 @@ export const AgentStrategy = memo((props: AgentStrategyProps) => {
value={value}
onSelect={item => onChange(item)}
onDelete={() => onChange(null)}
canChooseMCPTool={canChooseMCPTool}
onSelectMultiple={noop}
/>
</Field>
)
@ -187,6 +193,7 @@ export const AgentStrategy = memo((props: AgentStrategyProps) => {
onChange={onChange}
supportCollapse
required={schema.required}
canChooseMCPTool={canChooseMCPTool}
/>
)
}

@ -53,6 +53,7 @@ const AgentPanel: FC<NodePanelProps<AgentNodeType>> = (props) => {
varInputs,
outputSchema,
handleMemoryChange,
canChooseMCPTool,
} = useConfig(props.id, props.data)
const { t } = useTranslation()
const nodeInfo = useMemo(() => {
@ -79,7 +80,7 @@ const AgentPanel: FC<NodePanelProps<AgentNodeType>> = (props) => {
})()
const resetEditor = useStore(s => s.setControlPromptEditorRerenderKey)
console.log(canChooseMCPTool)
return <div className='my-2'>
<Field
required
@ -93,6 +94,7 @@ const AgentPanel: FC<NodePanelProps<AgentNodeType>> = (props) => {
agent_strategy_label: inputs.agent_strategy_label!,
agent_output_schema: inputs.output_schema,
plugin_unique_identifier: inputs.plugin_unique_identifier!,
meta: inputs.meta,
} : undefined}
onStrategyChange={(strategy) => {
setInputs({
@ -102,6 +104,7 @@ const AgentPanel: FC<NodePanelProps<AgentNodeType>> = (props) => {
agent_strategy_label: strategy?.agent_strategy_label,
output_schema: strategy!.agent_output_schema,
plugin_unique_identifier: strategy!.plugin_unique_identifier,
meta: strategy?.meta,
})
resetEditor(Date.now())
}}

@ -1,11 +1,13 @@
import type { CommonNodeType, Memory } from '@/app/components/workflow/types'
import type { ToolVarInputs } from '../tool/types'
import type { PluginMeta } from '@/app/components/plugins/types'
export type AgentNodeType = CommonNodeType & {
agent_strategy_provider_name?: string
agent_strategy_name?: string
agent_strategy_label?: string
agent_parameters?: ToolVarInputs
meta?: PluginMeta
output_schema: Record<string, any>
plugin_unique_identifier?: string
memory?: Memory

@ -14,6 +14,7 @@ import type { Memory, Var } from '../../types'
import { VarType as VarKindType } from '../../types'
import useAvailableVarList from '../_base/hooks/use-available-var-list'
import produce from 'immer'
import { isSupportMCP } from '@/utils/plugin-version-feature'
export type StrategyStatus = {
plugin: {
@ -214,6 +215,7 @@ const useConfig = (id: string, payload: AgentNodeType) => {
outputSchema,
handleMemoryChange,
isChatMode,
canChooseMCPTool: isSupportMCP(inputs.meta?.version),
}
}

@ -15,6 +15,7 @@ import type {
} from '@/app/components/workflow/nodes/_base/components/error-handle/types'
import type { WorkflowRetryConfig } from '@/app/components/workflow/nodes/_base/components/retry/types'
import type { StructuredOutput } from '@/app/components/workflow/nodes/llm/types'
import type { PluginMeta } from '../plugins/types'
export enum BlockEnum {
Start = 'start',
@ -400,6 +401,7 @@ export type MoreInfo = {
export type ToolWithProvider = Collection & {
tools: Tool[]
meta: PluginMeta
}
export enum SupportUploadFileTypes {

@ -0,0 +1,26 @@
import { isSupportMCP } from './plugin-version-feature'
describe('plugin-version-feature', () => {
beforeEach(() => {
jest.clearAllMocks()
})
describe('isSupportMCP', () => {
it('should call isEqualOrLaterThanVersion with the correct parameters', () => {
expect(isSupportMCP('0.0.3')).toBe(true)
expect(isSupportMCP('1.0.0')).toBe(true)
})
it('should return true when version is equal to the supported MCP version', () => {
const mockVersion = '0.0.2'
const result = isSupportMCP(mockVersion)
expect(result).toBe(true)
})
it('should return false when version is less than the supported MCP version', () => {
const mockVersion = '0.0.1'
const result = isSupportMCP(mockVersion)
expect(result).toBe(false)
})
})
})

@ -0,0 +1,10 @@
import { isEqualOrLaterThanVersion } from './semver'
const SUPPORT_MCP_VERSION = '0.0.2'
export const isSupportMCP = (version?: string): boolean => {
if (!version)
return false
return isEqualOrLaterThanVersion(version, SUPPORT_MCP_VERSION)
}

@ -0,0 +1,75 @@
import { compareVersion, getLatestVersion, isEqualOrLaterThanVersion } from './semver'
describe('semver utilities', () => {
describe('getLatestVersion', () => {
it('should return the latest version from a list of versions', () => {
expect(getLatestVersion(['1.0.0', '1.1.0', '1.0.1'])).toBe('1.1.0')
expect(getLatestVersion(['2.0.0', '1.9.9', '1.10.0'])).toBe('2.0.0')
expect(getLatestVersion(['1.0.0-alpha', '1.0.0-beta', '1.0.0'])).toBe('1.0.0')
})
it('should handle patch versions correctly', () => {
expect(getLatestVersion(['1.0.1', '1.0.2', '1.0.0'])).toBe('1.0.2')
expect(getLatestVersion(['1.0.10', '1.0.9', '1.0.11'])).toBe('1.0.11')
})
it('should handle mixed version formats', () => {
expect(getLatestVersion(['v1.0.0', '1.1.0', 'v1.2.0'])).toBe('v1.2.0')
expect(getLatestVersion(['1.0.0-rc.1', '1.0.0', '1.0.0-beta'])).toBe('1.0.0')
})
it('should return the only version if only one version is provided', () => {
expect(getLatestVersion(['1.0.0'])).toBe('1.0.0')
})
})
describe('compareVersion', () => {
it('should return 1 when first version is greater', () => {
expect(compareVersion('1.1.0', '1.0.0')).toBe(1)
expect(compareVersion('2.0.0', '1.9.9')).toBe(1)
expect(compareVersion('1.0.1', '1.0.0')).toBe(1)
})
it('should return -1 when first version is less', () => {
expect(compareVersion('1.0.0', '1.1.0')).toBe(-1)
expect(compareVersion('1.9.9', '2.0.0')).toBe(-1)
expect(compareVersion('1.0.0', '1.0.1')).toBe(-1)
})
it('should return 0 when versions are equal', () => {
expect(compareVersion('1.0.0', '1.0.0')).toBe(0)
expect(compareVersion('2.1.3', '2.1.3')).toBe(0)
})
it('should handle pre-release versions correctly', () => {
expect(compareVersion('1.0.0-beta', '1.0.0-alpha')).toBe(1)
expect(compareVersion('1.0.0', '1.0.0-beta')).toBe(1)
expect(compareVersion('1.0.0-alpha', '1.0.0-beta')).toBe(-1)
})
})
describe('isEqualOrLaterThanVersion', () => {
it('should return true when baseVersion is greater than targetVersion', () => {
expect(isEqualOrLaterThanVersion('1.1.0', '1.0.0')).toBe(true)
expect(isEqualOrLaterThanVersion('2.0.0', '1.9.9')).toBe(true)
expect(isEqualOrLaterThanVersion('1.0.1', '1.0.0')).toBe(true)
})
it('should return true when baseVersion is equal to targetVersion', () => {
expect(isEqualOrLaterThanVersion('1.0.0', '1.0.0')).toBe(true)
expect(isEqualOrLaterThanVersion('2.1.3', '2.1.3')).toBe(true)
})
it('should return false when baseVersion is less than targetVersion', () => {
expect(isEqualOrLaterThanVersion('1.0.0', '1.1.0')).toBe(false)
expect(isEqualOrLaterThanVersion('1.9.9', '2.0.0')).toBe(false)
expect(isEqualOrLaterThanVersion('1.0.0', '1.0.1')).toBe(false)
})
it('should handle pre-release versions correctly', () => {
expect(isEqualOrLaterThanVersion('1.0.0', '1.0.0-beta')).toBe(true)
expect(isEqualOrLaterThanVersion('1.0.0-beta', '1.0.0-alpha')).toBe(true)
expect(isEqualOrLaterThanVersion('1.0.0-alpha', '1.0.0')).toBe(false)
})
})
})

@ -7,3 +7,7 @@ export const getLatestVersion = (versionList: string[]) => {
export const compareVersion = (v1: string, v2: string) => {
return semver.compare(v1, v2)
}
export const isEqualOrLaterThanVersion = (baseVersion: string, targetVersion: string) => {
return semver.gte(baseVersion, targetVersion)
}

Loading…
Cancel
Save