diff --git a/web/app/components/rag-pipeline/hooks/use-available-nodes-meta-data.ts b/web/app/components/rag-pipeline/hooks/use-available-nodes-meta-data.ts
index 3dad34f441..6ce4524c8e 100644
--- a/web/app/components/rag-pipeline/hooks/use-available-nodes-meta-data.ts
+++ b/web/app/components/rag-pipeline/hooks/use-available-nodes-meta-data.ts
@@ -19,26 +19,9 @@ export const useAvailableNodesMetaData = () => {
...dataSourceDefault.defaultValue,
_dataSourceStartToAdd: true,
},
- metaData: {
- ...dataSourceDefault.metaData,
- isStart: true,
- isRequired: true,
- },
- },
- {
- ...knowledgeBaseDefault,
- metaData: {
- ...knowledgeBaseDefault.metaData,
- isRequired: true,
- },
- },
- {
- ...dataSourceEmptyDefault,
- metaData: {
- ...dataSourceEmptyDefault.metaData,
- isUndeletable: true,
- },
},
+ knowledgeBaseDefault,
+ dataSourceEmptyDefault,
], [])
const prefixLink = useMemo(() => {
diff --git a/web/app/components/workflow-app/hooks/use-available-nodes-meta-data.ts b/web/app/components/workflow-app/hooks/use-available-nodes-meta-data.ts
index 983d598573..f590c1a8ce 100644
--- a/web/app/components/workflow-app/hooks/use-available-nodes-meta-data.ts
+++ b/web/app/components/workflow-app/hooks/use-available-nodes-meta-data.ts
@@ -15,35 +15,11 @@ export const useAvailableNodesMetaData = () => {
const mergedNodesMetaData = useMemo(() => [
...WORKFLOW_COMMON_NODES,
- {
- ...StartDefault,
- metaData: {
- ...StartDefault.metaData,
- isStart: true,
- isRequired: true,
- isUndeletable: true,
- },
- },
+ StartDefault,
...(
isChatMode
- ? [
- {
- ...AnswerDefault,
- metaData: {
- ...AnswerDefault.metaData,
- isRequired: true,
- },
- },
- ]
- : [
- {
- ...EndDefault,
- metaData: {
- ...EndDefault.metaData,
- isRequired: true,
- },
- },
- ]
+ ? [AnswerDefault]
+ : [EndDefault]
),
], [isChatMode])
diff --git a/web/app/components/workflow/hooks/use-nodes-interactions.ts b/web/app/components/workflow/hooks/use-nodes-interactions.ts
index 3f1fd56df1..023f3a7470 100644
--- a/web/app/components/workflow/hooks/use-nodes-interactions.ts
+++ b/web/app/components/workflow/hooks/use-nodes-interactions.ts
@@ -1256,15 +1256,26 @@ export const useNodesInteractions = () => {
}
else {
// If no nodeId is provided, fall back to the current behavior
- const bundledNodes = nodes.filter(node => node.data._isBundled && node.data.type !== BlockEnum.Start && node.data.type !== BlockEnum.DataSource && node.data.type !== BlockEnum.KnowledgeBase && node.data.type !== BlockEnum.DataSourceEmpty
- && !node.data.isInIteration && !node.data.isInLoop)
+ const bundledNodes = nodes.filter((node) => {
+ if (!node.data._isBundled)
+ return false
+ const { metaData } = nodesMetaDataMap![node.data.type as BlockEnum]
+ if (metaData.isSingleton)
+ return false
+ return !node.data.isInIteration && !node.data.isInLoop
+ })
if (bundledNodes.length) {
setClipboardElements(bundledNodes)
return
}
- const selectedNode = nodes.find(node => node.data.selected && node.data.type !== BlockEnum.Start && node.data.type !== BlockEnum.LoopEnd && node.data.type !== BlockEnum.DataSource)
+ const selectedNode = nodes.find((node) => {
+ if (!node.data.selected)
+ return false
+ const { metaData } = nodesMetaDataMap![node.data.type as BlockEnum]
+ return !metaData.isSingleton
+ })
if (selectedNode)
setClipboardElements([selectedNode])
diff --git a/web/app/components/workflow/nodes/_base/components/panel-operator/panel-operator-popup.tsx b/web/app/components/workflow/nodes/_base/components/panel-operator/panel-operator-popup.tsx
index 75abdd6d12..a871e60e3a 100644
--- a/web/app/components/workflow/nodes/_base/components/panel-operator/panel-operator-popup.tsx
+++ b/web/app/components/workflow/nodes/_base/components/panel-operator/panel-operator-popup.tsx
@@ -16,7 +16,6 @@ import {
} from '@/app/components/workflow/hooks'
import ShortcutsName from '@/app/components/workflow/shortcuts-name'
import type { Node } from '@/app/components/workflow/types'
-import { BlockEnum } from '@/app/components/workflow/types'
type PanelOperatorPopupProps = {
id: string
@@ -43,7 +42,7 @@ const PanelOperatorPopup = ({
const { nodesReadOnly } = useNodesReadOnly()
const edge = edges.find(edge => edge.target === id)
const nodeMetaData = useNodeMetaData({ id, data } as Node)
- const showChangeBlock = data.type !== BlockEnum.Start && !nodesReadOnly && data.type !== BlockEnum.Iteration && data.type !== BlockEnum.Loop
+ const showChangeBlock = !nodeMetaData.isTypeFixed && !nodesReadOnly
const isChildNode = !!(data.isInIteration || data.isInLoop)
return (
@@ -85,31 +84,37 @@ const PanelOperatorPopup = ({
)
}
{
- data.type !== BlockEnum.Start && !nodesReadOnly && (
+ !nodesReadOnly && (
<>
-
-
{
- onClosePopup()
- handleNodesCopy(id)
- }}
- >
- {t('workflow.common.copy')}
-
-
-
{
- onClosePopup()
- handleNodesDuplicate(id)
- }}
- >
- {t('workflow.common.duplicate')}
-
-
-
-
+ {
+ !nodeMetaData.isSingleton && (
+ <>
+
+
{
+ onClosePopup()
+ handleNodesCopy(id)
+ }}
+ >
+ {t('workflow.common.copy')}
+
+
+
{
+ onClosePopup()
+ handleNodesDuplicate(id)
+ }}
+ >
+ {t('workflow.common.duplicate')}
+
+
+
+
+ >
+ )
+ }
{
!nodeMetaData.isUndeletable && (
<>
@@ -117,7 +122,7 @@ const PanelOperatorPopup = ({
handleNodeDelete(id)}
>
diff --git a/web/app/components/workflow/nodes/answer/default.ts b/web/app/components/workflow/nodes/answer/default.ts
index d3cb2c6741..f115274900 100644
--- a/web/app/components/workflow/nodes/answer/default.ts
+++ b/web/app/components/workflow/nodes/answer/default.ts
@@ -6,6 +6,7 @@ import { BlockEnum } from '@/app/components/workflow/types'
const metaData = genNodeMetaData({
sort: 2.1,
type: BlockEnum.Answer,
+ isRequired: true,
})
const nodeDefault: NodeDefault
= {
metaData,
diff --git a/web/app/components/workflow/nodes/data-source-empty/default.ts b/web/app/components/workflow/nodes/data-source-empty/default.ts
index df7c5e853e..69d9904217 100644
--- a/web/app/components/workflow/nodes/data-source-empty/default.ts
+++ b/web/app/components/workflow/nodes/data-source-empty/default.ts
@@ -6,6 +6,8 @@ import { BlockEnum } from '@/app/components/workflow/types'
const metaData = genNodeMetaData({
sort: -1,
type: BlockEnum.DataSourceEmpty,
+ isUndeletable: true,
+ isSingleton: true,
})
const nodeDefault: NodeDefault = {
metaData,
diff --git a/web/app/components/workflow/nodes/data-source/default.ts b/web/app/components/workflow/nodes/data-source/default.ts
index f5ebb27655..82e69679a2 100644
--- a/web/app/components/workflow/nodes/data-source/default.ts
+++ b/web/app/components/workflow/nodes/data-source/default.ts
@@ -15,6 +15,8 @@ const i18nPrefix = 'workflow.errorMsg'
const metaData = genNodeMetaData({
sort: -1,
type: BlockEnum.DataSource,
+ isStart: true,
+ isRequired: true,
})
const nodeDefault: NodeDefault = {
metaData,
diff --git a/web/app/components/workflow/nodes/end/default.ts b/web/app/components/workflow/nodes/end/default.ts
index 32e4f1051d..cadb580c34 100644
--- a/web/app/components/workflow/nodes/end/default.ts
+++ b/web/app/components/workflow/nodes/end/default.ts
@@ -6,6 +6,7 @@ import { BlockEnum } from '@/app/components/workflow/types'
const metaData = genNodeMetaData({
sort: 2.1,
type: BlockEnum.End,
+ isRequired: true,
})
const nodeDefault: NodeDefault = {
metaData,
diff --git a/web/app/components/workflow/nodes/iteration/default.ts b/web/app/components/workflow/nodes/iteration/default.ts
index 3c348a4fe0..450379ec6b 100644
--- a/web/app/components/workflow/nodes/iteration/default.ts
+++ b/web/app/components/workflow/nodes/iteration/default.ts
@@ -9,6 +9,7 @@ const metaData = genNodeMetaData({
classification: BlockClassificationEnum.Logic,
sort: 2,
type: BlockEnum.Iteration,
+ isTypeFixed: true,
})
const nodeDefault: NodeDefault = {
metaData,
diff --git a/web/app/components/workflow/nodes/knowledge-base/default.ts b/web/app/components/workflow/nodes/knowledge-base/default.ts
index e43c08778f..8175e2ac9e 100644
--- a/web/app/components/workflow/nodes/knowledge-base/default.ts
+++ b/web/app/components/workflow/nodes/knowledge-base/default.ts
@@ -6,6 +6,10 @@ import { BlockEnum } from '@/app/components/workflow/types'
const metaData = genNodeMetaData({
sort: 3.1,
type: BlockEnum.KnowledgeBase,
+ isRequired: true,
+ isUndeletable: true,
+ isSingleton: true,
+ isTypeFixed: true,
})
const nodeDefault: NodeDefault = {
metaData,
diff --git a/web/app/components/workflow/nodes/loop-end/default.ts b/web/app/components/workflow/nodes/loop-end/default.ts
index c02d007cde..bb46ff1166 100644
--- a/web/app/components/workflow/nodes/loop-end/default.ts
+++ b/web/app/components/workflow/nodes/loop-end/default.ts
@@ -10,6 +10,7 @@ const metaData = genNodeMetaData({
classification: BlockClassificationEnum.Logic,
sort: 2,
type: BlockEnum.LoopEnd,
+ isSingleton: true,
})
const nodeDefault: NodeDefault = {
metaData,
diff --git a/web/app/components/workflow/nodes/loop/default.ts b/web/app/components/workflow/nodes/loop/default.ts
index 0a80763001..390545d0e2 100644
--- a/web/app/components/workflow/nodes/loop/default.ts
+++ b/web/app/components/workflow/nodes/loop/default.ts
@@ -14,6 +14,7 @@ const metaData = genNodeMetaData({
sort: 3,
type: BlockEnum.Loop,
author: 'AICT-Team',
+ isTypeFixed: true,
})
const nodeDefault: NodeDefault = {
metaData,
diff --git a/web/app/components/workflow/nodes/start/default.ts b/web/app/components/workflow/nodes/start/default.ts
index 8337c2275f..3b98b57a73 100644
--- a/web/app/components/workflow/nodes/start/default.ts
+++ b/web/app/components/workflow/nodes/start/default.ts
@@ -6,6 +6,11 @@ import { BlockEnum } from '@/app/components/workflow/types'
const metaData = genNodeMetaData({
sort: 0.1,
type: BlockEnum.Start,
+ isStart: true,
+ isRequired: true,
+ isUndeletable: true,
+ isSingleton: true,
+ isTypeFixed: true,
})
const nodeDefault: NodeDefault = {
metaData,
diff --git a/web/app/components/workflow/types.ts b/web/app/components/workflow/types.ts
index bfae195a0e..f5ff7d5ce8 100644
--- a/web/app/components/workflow/types.ts
+++ b/web/app/components/workflow/types.ts
@@ -329,6 +329,8 @@ export type NodeDefault = {
isRequired?: boolean
isUndeletable?: boolean
isStart?: boolean
+ isSingleton?: boolean
+ isTypeFixed?: boolean
}
defaultValue: Partial
defaultRunInputData?: Record
diff --git a/web/app/components/workflow/utils/gen-node-meta-data.ts b/web/app/components/workflow/utils/gen-node-meta-data.ts
index e7271cfcc4..9c4e9cabca 100644
--- a/web/app/components/workflow/utils/gen-node-meta-data.ts
+++ b/web/app/components/workflow/utils/gen-node-meta-data.ts
@@ -8,6 +8,11 @@ export type GenNodeMetaDataParams = {
title?: string
author?: string
helpLinkUri?: string
+ isRequired?: boolean
+ isUndeletable?: boolean
+ isStart?: boolean
+ isSingleton?: boolean
+ isTypeFixed?: boolean
}
export const genNodeMetaData = ({
classification = BlockClassificationEnum.Default,
@@ -16,6 +21,11 @@ export const genNodeMetaData = ({
title = '',
author = 'Dify',
helpLinkUri,
+ isRequired = false,
+ isUndeletable = false,
+ isStart = false,
+ isSingleton = false,
+ isTypeFixed = false,
}: GenNodeMetaDataParams) => {
return {
classification,
@@ -24,5 +34,10 @@ export const genNodeMetaData = ({
title,
author,
helpLinkUri: helpLinkUri || type,
+ isRequired,
+ isUndeletable,
+ isStart,
+ isSingleton,
+ isTypeFixed,
}
}