diff --git a/web/app/components/workflow/hooks/use-node-plugin-installation.ts b/web/app/components/workflow/hooks/use-node-plugin-installation.ts index d275759cc0..6a88105d58 100644 --- a/web/app/components/workflow/hooks/use-node-plugin-installation.ts +++ b/web/app/components/workflow/hooks/use-node-plugin-installation.ts @@ -16,11 +16,11 @@ import { useAllTriggerPlugins, useInvalidateAllTriggerPlugins, } from '@/service/use-triggers' -import { canFindTool } from '@/utils' import { useStore } from '../store' import { BlockEnum } from '../types' +import { matchDataSource, matchToolInCollection, matchTriggerProvider } from '../utils/plugin-install-check' -type InstallationState = { +export type InstallationState = { isChecking: boolean isMissing: boolean uniqueIdentifier?: string @@ -29,14 +29,25 @@ type InstallationState = { shouldDim: boolean } -const useToolInstallation = (data: ToolNodeType): InstallationState => { - const builtInQuery = useAllBuiltInTools() - const customQuery = useAllCustomTools() - const workflowQuery = useAllWorkflowTools() - const mcpQuery = useAllMCPTools() - const invalidateTools = useInvalidToolsByType(data.provider_type) +const NOOP_INSTALLATION: InstallationState = { + isChecking: false, + isMissing: false, + uniqueIdentifier: undefined, + canInstall: false, + onInstallSuccess: () => undefined, + shouldDim: false, +} + +const useToolInstallation = (data: ToolNodeType, enabled: boolean): InstallationState => { + const builtInQuery = useAllBuiltInTools(enabled) + const customQuery = useAllCustomTools(enabled) + const workflowQuery = useAllWorkflowTools(enabled) + const mcpQuery = useAllMCPTools(enabled) + const invalidateTools = useInvalidToolsByType(enabled ? data.provider_type : undefined) const collectionInfo = useMemo(() => { + if (!enabled) + return undefined switch (data.provider_type) { case CollectionType.builtIn: return { @@ -62,6 +73,7 @@ const useToolInstallation = (data: ToolNodeType): InstallationState => { return undefined } }, [ + enabled, builtInQuery.data, builtInQuery.isLoading, customQuery.data, @@ -80,17 +92,8 @@ const useToolInstallation = (data: ToolNodeType): InstallationState => { const matchedCollection = useMemo(() => { if (!collection || !collection.length) return undefined - - return collection.find((toolWithProvider) => { - if (data.plugin_id && toolWithProvider.plugin_id === data.plugin_id) - return true - if (canFindTool(toolWithProvider.id, data.provider_id)) - return true - if (toolWithProvider.name === data.provider_name) - return true - return false - }) - }, [collection, data.plugin_id, data.provider_id, data.provider_name]) + return matchToolInCollection(collection, data) + }, [collection, data]) const uniqueIdentifier = data.plugin_unique_identifier || data.plugin_id || data.provider_id const canInstall = Boolean(data.plugin_unique_identifier) @@ -112,8 +115,8 @@ const useToolInstallation = (data: ToolNodeType): InstallationState => { } } -const useTriggerInstallation = (data: PluginTriggerNodeType): InstallationState => { - const triggerPluginsQuery = useAllTriggerPlugins() +const useTriggerInstallation = (data: PluginTriggerNodeType, enabled: boolean): InstallationState => { + const triggerPluginsQuery = useAllTriggerPlugins(enabled) const invalidateTriggers = useInvalidateAllTriggerPlugins() const triggerProviders = triggerPluginsQuery.data @@ -122,18 +125,8 @@ const useTriggerInstallation = (data: PluginTriggerNodeType): InstallationState const matchedProvider = useMemo(() => { if (!triggerProviders || !triggerProviders.length) return undefined - - return triggerProviders.find(provider => - provider.name === data.provider_name - || provider.id === data.provider_id - || (data.plugin_id && provider.plugin_id === data.plugin_id), - ) - }, [ - data.plugin_id, - data.provider_id, - data.provider_name, - triggerProviders, - ]) + return matchTriggerProvider(triggerProviders, data) + }, [data, triggerProviders]) const uniqueIdentifier = data.plugin_unique_identifier || data.plugin_id || data.provider_id const canInstall = Boolean(data.plugin_unique_identifier) @@ -154,24 +147,15 @@ const useTriggerInstallation = (data: PluginTriggerNodeType): InstallationState } } -const useDataSourceInstallation = (data: DataSourceNodeType): InstallationState => { +const useDataSourceInstallation = (data: DataSourceNodeType, _enabled: boolean): InstallationState => { const dataSourceList = useStore(s => s.dataSourceList) const invalidateDataSourceList = useInvalidDataSourceList() const matchedPlugin = useMemo(() => { if (!dataSourceList || !dataSourceList.length) return undefined - - return dataSourceList.find((item) => { - if (data.plugin_unique_identifier && item.plugin_unique_identifier === data.plugin_unique_identifier) - return true - if (data.plugin_id && item.plugin_id === data.plugin_id) - return true - if (data.provider_name && item.provider === data.provider_name) - return true - return false - }) - }, [data.plugin_id, data.plugin_unique_identifier, data.provider_name, dataSourceList]) + return matchDataSource(dataSourceList, data) + }, [data, dataSourceList]) const uniqueIdentifier = data.plugin_unique_identifier || data.plugin_id const canInstall = Boolean(data.plugin_unique_identifier) @@ -195,25 +179,19 @@ const useDataSourceInstallation = (data: DataSourceNodeType): InstallationState } export const useNodePluginInstallation = (data: CommonNodeType): InstallationState => { - const toolInstallation = useToolInstallation(data as ToolNodeType) - const triggerInstallation = useTriggerInstallation(data as PluginTriggerNodeType) - const dataSourceInstallation = useDataSourceInstallation(data as DataSourceNodeType) + const isTool = data.type === BlockEnum.Tool + const isTrigger = data.type === BlockEnum.TriggerPlugin + const isDataSource = data.type === BlockEnum.DataSource - switch (data.type as BlockEnum) { - case BlockEnum.Tool: - return toolInstallation - case BlockEnum.TriggerPlugin: - return triggerInstallation - case BlockEnum.DataSource: - return dataSourceInstallation - default: - return { - isChecking: false, - isMissing: false, - uniqueIdentifier: undefined, - canInstall: false, - onInstallSuccess: () => undefined, - shouldDim: false, - } - } + const toolInstallation = useToolInstallation(data as ToolNodeType, isTool) + const triggerInstallation = useTriggerInstallation(data as PluginTriggerNodeType, isTrigger) + const dataSourceInstallation = useDataSourceInstallation(data as DataSourceNodeType, isDataSource) + + if (isTool) + return toolInstallation + if (isTrigger) + return triggerInstallation + if (isDataSource) + return dataSourceInstallation + return NOOP_INSTALLATION } diff --git a/web/app/components/workflow/utils/plugin-install-check.ts b/web/app/components/workflow/utils/plugin-install-check.ts index 66eb41d69f..60998def55 100644 --- a/web/app/components/workflow/utils/plugin-install-check.ts +++ b/web/app/components/workflow/utils/plugin-install-check.ts @@ -7,6 +7,49 @@ import { CollectionType } from '@/app/components/tools/types' import { canFindTool } from '@/utils' import { BlockEnum } from '../types' +export const PLUGIN_DEPENDENT_TYPES: BlockEnum[] = [ + BlockEnum.Tool, + BlockEnum.DataSource, + BlockEnum.TriggerPlugin, +] + +export function isPluginDependentNode(type: string): boolean { + return PLUGIN_DEPENDENT_TYPES.includes(type as BlockEnum) +} + +export function matchToolInCollection( + collection: ToolWithProvider[], + data: { plugin_id?: string, provider_id?: string, provider_name?: string }, +): ToolWithProvider | undefined { + return collection.find(t => + (data.plugin_id && t.plugin_id === data.plugin_id) + || canFindTool(t.id, data.provider_id) + || t.name === data.provider_name, + ) +} + +export function matchTriggerProvider( + providers: TriggerWithProvider[], + data: { provider_name?: string, provider_id?: string, plugin_id?: string }, +): TriggerWithProvider | undefined { + return providers.find(p => + p.name === data.provider_name + || p.id === data.provider_id + || (data.plugin_id && p.plugin_id === data.plugin_id), + ) +} + +export function matchDataSource( + list: ToolWithProvider[], + data: { plugin_unique_identifier?: string, plugin_id?: string, provider_name?: string }, +): ToolWithProvider | undefined { + return list.find(item => + (data.plugin_unique_identifier && item.plugin_unique_identifier === data.plugin_unique_identifier) + || (data.plugin_id && item.plugin_id === data.plugin_id) + || (data.provider_name && item.provider === data.provider_name), + ) +} + export type PluginInstallCheckContext = { builtInTools?: ToolWithProvider[] customTools?: ToolWithProvider[] @@ -32,34 +75,19 @@ export function isNodePluginMissing( const collection = collectionMap[toolData.provider_type] if (!collection) return false - const matched = collection.find(t => - (toolData.plugin_id && t.plugin_id === toolData.plugin_id) - || canFindTool(t.id, toolData.provider_id) - || t.name === toolData.provider_name, - ) - return !matched && Boolean(toolData.plugin_unique_identifier) + return !matchToolInCollection(collection, toolData) && Boolean(toolData.plugin_unique_identifier) } case BlockEnum.TriggerPlugin: { const triggerData = data as PluginTriggerNodeType if (!context.triggerPlugins) return false - const matched = context.triggerPlugins.find(p => - p.name === triggerData.provider_name - || p.id === triggerData.provider_id - || (triggerData.plugin_id && p.plugin_id === triggerData.plugin_id), - ) - return !matched && Boolean(triggerData.plugin_unique_identifier) + return !matchTriggerProvider(context.triggerPlugins, triggerData) && Boolean(triggerData.plugin_unique_identifier) } case BlockEnum.DataSource: { const dsData = data as DataSourceNodeType if (!context.dataSourceList) return false - const matched = context.dataSourceList.find(item => - (dsData.plugin_unique_identifier && item.plugin_unique_identifier === dsData.plugin_unique_identifier) - || (dsData.plugin_id && item.plugin_id === dsData.plugin_id) - || (dsData.provider_name && item.provider === dsData.provider_name), - ) - return !matched && Boolean(dsData.plugin_unique_identifier) + return !matchDataSource(context.dataSourceList, dsData) && Boolean(dsData.plugin_unique_identifier) } default: return false diff --git a/web/service/use-tools.ts b/web/service/use-tools.ts index 49a28eba3c..f0b2c63090 100644 --- a/web/service/use-tools.ts +++ b/web/service/use-tools.ts @@ -31,10 +31,11 @@ export const useInvalidateAllToolProviders = () => { } const useAllBuiltInToolsKey = [NAME_SPACE, 'builtIn'] -export const useAllBuiltInTools = () => { +export const useAllBuiltInTools = (enabled = true) => { return useQuery({ queryKey: useAllBuiltInToolsKey, queryFn: () => get('/workspaces/current/tools/builtin'), + enabled, }) } @@ -43,10 +44,11 @@ export const useInvalidateAllBuiltInTools = () => { } const useAllCustomToolsKey = [NAME_SPACE, 'customTools'] -export const useAllCustomTools = () => { +export const useAllCustomTools = (enabled = true) => { return useQuery({ queryKey: useAllCustomToolsKey, queryFn: () => get('/workspaces/current/tools/api'), + enabled, }) } @@ -55,10 +57,11 @@ export const useInvalidateAllCustomTools = () => { } const useAllWorkflowToolsKey = [NAME_SPACE, 'workflowTools'] -export const useAllWorkflowTools = () => { +export const useAllWorkflowTools = (enabled = true) => { return useQuery({ queryKey: useAllWorkflowToolsKey, queryFn: () => get('/workspaces/current/tools/workflow'), + enabled, }) } @@ -67,10 +70,11 @@ export const useInvalidateAllWorkflowTools = () => { } const useAllMCPToolsKey = [NAME_SPACE, 'MCPTools'] -export const useAllMCPTools = () => { +export const useAllMCPTools = (enabled = true) => { return useQuery({ queryKey: useAllMCPToolsKey, queryFn: () => get('/workspaces/current/tools/mcp'), + enabled, }) }