mirror of
https://github.com/langgenius/dify.git
synced 2026-04-29 04:26:30 +08:00
chore: refactor workflow
This commit is contained in:
parent
5e09ac696c
commit
f7de55364f
@ -7,6 +7,7 @@ import { WorkflowWithInnerContext } from '@/app/components/workflow'
|
|||||||
import type { WorkflowProps } from '@/app/components/workflow'
|
import type { WorkflowProps } from '@/app/components/workflow'
|
||||||
import WorkflowChildren from './workflow-children'
|
import WorkflowChildren from './workflow-children'
|
||||||
import {
|
import {
|
||||||
|
useAvailableNodesMetaData,
|
||||||
useNodesSyncDraft,
|
useNodesSyncDraft,
|
||||||
useWorkflowRun,
|
useWorkflowRun,
|
||||||
useWorkflowStartRun,
|
useWorkflowStartRun,
|
||||||
@ -44,6 +45,7 @@ const WorkflowMain = ({
|
|||||||
handleWorkflowStartRunInChatflow,
|
handleWorkflowStartRunInChatflow,
|
||||||
handleWorkflowStartRunInWorkflow,
|
handleWorkflowStartRunInWorkflow,
|
||||||
} = useWorkflowStartRun()
|
} = useWorkflowStartRun()
|
||||||
|
const availableNodesMetaData = useAvailableNodesMetaData()
|
||||||
|
|
||||||
const hooksStore = useMemo(() => {
|
const hooksStore = useMemo(() => {
|
||||||
return {
|
return {
|
||||||
@ -57,6 +59,7 @@ const WorkflowMain = ({
|
|||||||
handleStartWorkflowRun,
|
handleStartWorkflowRun,
|
||||||
handleWorkflowStartRunInChatflow,
|
handleWorkflowStartRunInChatflow,
|
||||||
handleWorkflowStartRunInWorkflow,
|
handleWorkflowStartRunInWorkflow,
|
||||||
|
availableNodesMetaData,
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
syncWorkflowDraftWhenPageClose,
|
syncWorkflowDraftWhenPageClose,
|
||||||
@ -69,6 +72,7 @@ const WorkflowMain = ({
|
|||||||
handleStartWorkflowRun,
|
handleStartWorkflowRun,
|
||||||
handleWorkflowStartRunInChatflow,
|
handleWorkflowStartRunInChatflow,
|
||||||
handleWorkflowStartRunInWorkflow,
|
handleWorkflowStartRunInWorkflow,
|
||||||
|
availableNodesMetaData,
|
||||||
])
|
])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -77,7 +81,7 @@ const WorkflowMain = ({
|
|||||||
edges={edges}
|
edges={edges}
|
||||||
viewport={viewport}
|
viewport={viewport}
|
||||||
onWorkflowDataUpdate={handleWorkflowDataUpdate}
|
onWorkflowDataUpdate={handleWorkflowDataUpdate}
|
||||||
hooksStore={hooksStore}
|
hooksStore={hooksStore as any}
|
||||||
>
|
>
|
||||||
<WorkflowChildren />
|
<WorkflowChildren />
|
||||||
</WorkflowWithInnerContext>
|
</WorkflowWithInnerContext>
|
||||||
|
|||||||
@ -4,3 +4,4 @@ export * from './use-nodes-sync-draft'
|
|||||||
export * from './use-workflow-run'
|
export * from './use-workflow-run'
|
||||||
export * from './use-workflow-start-run'
|
export * from './use-workflow-start-run'
|
||||||
export * from './use-is-chat-mode'
|
export * from './use-is-chat-mode'
|
||||||
|
export * from './use-available-nodes-meta-data'
|
||||||
|
|||||||
@ -0,0 +1,60 @@
|
|||||||
|
import { useMemo } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { useGetLanguage } from '@/context/i18n'
|
||||||
|
import StartDefault from '@/app/components/workflow/nodes/start/default'
|
||||||
|
import EndDefault from '@/app/components/workflow/nodes/end/default'
|
||||||
|
import AnswerDefault from '@/app/components/workflow/nodes/answer/default'
|
||||||
|
import { WORKFLOW_COMMON_NODES } from '@/app/components/workflow/constants/node'
|
||||||
|
import type { AvailableNodesMetaData } from '@/app/components/workflow/hooks-store/store'
|
||||||
|
import { useIsChatMode } from './use-is-chat-mode'
|
||||||
|
|
||||||
|
export const useAvailableNodesMetaData = () => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const isChatMode = useIsChatMode()
|
||||||
|
const language = useGetLanguage()
|
||||||
|
|
||||||
|
console.log('isChatMode', isChatMode)
|
||||||
|
|
||||||
|
const mergedNodesMetaData = useMemo(() => [
|
||||||
|
...WORKFLOW_COMMON_NODES,
|
||||||
|
StartDefault,
|
||||||
|
...(
|
||||||
|
isChatMode
|
||||||
|
? [AnswerDefault]
|
||||||
|
: [EndDefault]
|
||||||
|
),
|
||||||
|
], [isChatMode])
|
||||||
|
|
||||||
|
const prefixLink = useMemo(() => {
|
||||||
|
if (language === 'zh_Hans')
|
||||||
|
return 'https://docs.dify.ai/zh-hans/guides/workflow/node/'
|
||||||
|
|
||||||
|
return 'https://docs.dify.ai/guides/workflow/node/'
|
||||||
|
}, [language])
|
||||||
|
|
||||||
|
const availableNodesMetaData = useMemo(() => mergedNodesMetaData.map((node) => {
|
||||||
|
return {
|
||||||
|
...node,
|
||||||
|
defaultValue: {
|
||||||
|
...node.defaultValue,
|
||||||
|
type: node.type,
|
||||||
|
},
|
||||||
|
title: t(`workflow.blocks.${node.type}`),
|
||||||
|
description: t(`workflow.blocksAbout.${node.type}`),
|
||||||
|
helpLinkUri: `${prefixLink}${node.helpLinkUri}`,
|
||||||
|
|
||||||
|
}
|
||||||
|
}), [mergedNodesMetaData, t, prefixLink])
|
||||||
|
|
||||||
|
const availableNodesMetaDataMap = useMemo(() => availableNodesMetaData.reduce((acc, node) => {
|
||||||
|
acc![node.type] = node
|
||||||
|
return acc
|
||||||
|
}, {} as AvailableNodesMetaData['nodesMap']), [availableNodesMetaData])
|
||||||
|
|
||||||
|
return useMemo(() => {
|
||||||
|
return {
|
||||||
|
nodes: availableNodesMetaData,
|
||||||
|
nodesMap: availableNodesMetaDataMap,
|
||||||
|
}
|
||||||
|
}, [availableNodesMetaData, availableNodesMetaDataMap])
|
||||||
|
}
|
||||||
@ -3,15 +3,17 @@ import {
|
|||||||
NODE_WIDTH_X_OFFSET,
|
NODE_WIDTH_X_OFFSET,
|
||||||
START_INITIAL_POSITION,
|
START_INITIAL_POSITION,
|
||||||
} from '@/app/components/workflow/constants'
|
} from '@/app/components/workflow/constants'
|
||||||
import { useNodesInitialData } from '@/app/components/workflow/hooks'
|
|
||||||
import { useIsChatMode } from './use-is-chat-mode'
|
import { useIsChatMode } from './use-is-chat-mode'
|
||||||
|
import type { StartNodeType } from '@/app/components/workflow/nodes/start/types'
|
||||||
|
import startDefault from '@/app/components/workflow/nodes/start/default'
|
||||||
|
import llmDefault from '@/app/components/workflow/nodes/llm/default'
|
||||||
|
import answerDefault from '@/app/components/workflow/nodes/answer/default'
|
||||||
|
|
||||||
export const useWorkflowTemplate = () => {
|
export const useWorkflowTemplate = () => {
|
||||||
const isChatMode = useIsChatMode()
|
const isChatMode = useIsChatMode()
|
||||||
const nodesInitialData = useNodesInitialData()
|
|
||||||
|
|
||||||
const { newNode: startNode } = generateNewNode({
|
const { newNode: startNode } = generateNewNode({
|
||||||
data: nodesInitialData.start,
|
data: startDefault.defaultValue as StartNodeType,
|
||||||
position: START_INITIAL_POSITION,
|
position: START_INITIAL_POSITION,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -19,7 +21,7 @@ export const useWorkflowTemplate = () => {
|
|||||||
const { newNode: llmNode } = generateNewNode({
|
const { newNode: llmNode } = generateNewNode({
|
||||||
id: 'llm',
|
id: 'llm',
|
||||||
data: {
|
data: {
|
||||||
...nodesInitialData.llm,
|
...llmDefault.defaultValue,
|
||||||
memory: {
|
memory: {
|
||||||
window: { enabled: false, size: 10 },
|
window: { enabled: false, size: 10 },
|
||||||
query_prompt_template: '{{#sys.query#}}',
|
query_prompt_template: '{{#sys.query#}}',
|
||||||
@ -35,7 +37,7 @@ export const useWorkflowTemplate = () => {
|
|||||||
const { newNode: answerNode } = generateNewNode({
|
const { newNode: answerNode } = generateNewNode({
|
||||||
id: 'answer',
|
id: 'answer',
|
||||||
data: {
|
data: {
|
||||||
...nodesInitialData.answer,
|
...answerDefault.defaultValue,
|
||||||
answer: `{{#${llmNode.id}.text#}}`,
|
answer: `{{#${llmNode.id}.text#}}`,
|
||||||
},
|
},
|
||||||
position: {
|
position: {
|
||||||
|
|||||||
@ -7,12 +7,8 @@ import { useTranslation } from 'react-i18next'
|
|||||||
import { groupBy } from 'lodash-es'
|
import { groupBy } from 'lodash-es'
|
||||||
import BlockIcon from '../block-icon'
|
import BlockIcon from '../block-icon'
|
||||||
import { BlockEnum } from '../types'
|
import { BlockEnum } from '../types'
|
||||||
import {
|
import type { NodeDefault } from '../types'
|
||||||
useIsChatMode,
|
|
||||||
useNodesExtraData,
|
|
||||||
} from '../hooks'
|
|
||||||
import { BLOCK_CLASSIFICATIONS } from './constants'
|
import { BLOCK_CLASSIFICATIONS } from './constants'
|
||||||
import { useBlocks } from './hooks'
|
|
||||||
import type { ToolDefaultValue } from './types'
|
import type { ToolDefaultValue } from './types'
|
||||||
import Tooltip from '@/app/components/base/tooltip'
|
import Tooltip from '@/app/components/base/tooltip'
|
||||||
import Badge from '@/app/components/base/badge'
|
import Badge from '@/app/components/base/badge'
|
||||||
@ -21,23 +17,19 @@ type BlocksProps = {
|
|||||||
searchText: string
|
searchText: string
|
||||||
onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void
|
onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void
|
||||||
availableBlocksTypes?: BlockEnum[]
|
availableBlocksTypes?: BlockEnum[]
|
||||||
|
blocks: NodeDefault[]
|
||||||
}
|
}
|
||||||
const Blocks = ({
|
const Blocks = ({
|
||||||
searchText,
|
searchText,
|
||||||
onSelect,
|
onSelect,
|
||||||
availableBlocksTypes = [],
|
availableBlocksTypes = [],
|
||||||
|
blocks,
|
||||||
}: BlocksProps) => {
|
}: BlocksProps) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const isChatMode = useIsChatMode()
|
|
||||||
const nodesExtraData = useNodesExtraData()
|
|
||||||
const blocks = useBlocks()
|
|
||||||
|
|
||||||
const groups = useMemo(() => {
|
const groups = useMemo(() => {
|
||||||
return BLOCK_CLASSIFICATIONS.reduce((acc, classification) => {
|
return BLOCK_CLASSIFICATIONS.reduce((acc, classification) => {
|
||||||
const list = groupBy(blocks, 'classification')[classification].filter((block) => {
|
const list = groupBy(blocks, 'classification')[classification].filter((block) => {
|
||||||
if (block.type === BlockEnum.Answer && !isChatMode)
|
|
||||||
return false
|
|
||||||
|
|
||||||
return block.title.toLowerCase().includes(searchText.toLowerCase()) && availableBlocksTypes.includes(block.type)
|
return block.title.toLowerCase().includes(searchText.toLowerCase()) && availableBlocksTypes.includes(block.type)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -46,11 +38,11 @@ const Blocks = ({
|
|||||||
[classification]: list,
|
[classification]: list,
|
||||||
}
|
}
|
||||||
}, {} as Record<string, typeof blocks>)
|
}, {} as Record<string, typeof blocks>)
|
||||||
}, [blocks, isChatMode, searchText, availableBlocksTypes])
|
}, [blocks, searchText, availableBlocksTypes])
|
||||||
const isEmpty = Object.values(groups).every(list => !list.length)
|
const isEmpty = Object.values(groups).every(list => !list.length)
|
||||||
|
|
||||||
const renderGroup = useCallback((classification: string) => {
|
const renderGroup = useCallback((classification: string) => {
|
||||||
const list = groups[classification]
|
const list = groups[classification].sort((a, b) => a.sort - b.sort)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -78,7 +70,7 @@ const Blocks = ({
|
|||||||
type={block.type}
|
type={block.type}
|
||||||
/>
|
/>
|
||||||
<div className='system-md-medium mb-1 text-text-primary'>{block.title}</div>
|
<div className='system-md-medium mb-1 text-text-primary'>{block.title}</div>
|
||||||
<div className='system-xs-regular text-text-tertiary'>{nodesExtraData[block.type].about}</div>
|
<div className='system-xs-regular text-text-tertiary'>{block.description}</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@ -106,7 +98,7 @@ const Blocks = ({
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [groups, nodesExtraData, onSelect, t])
|
}, [groups, onSelect, t])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='p-1'>
|
<div className='p-1'>
|
||||||
|
|||||||
@ -1,107 +1,5 @@
|
|||||||
import type { Block } from '../types'
|
|
||||||
import { BlockEnum } from '../types'
|
|
||||||
import { BlockClassificationEnum } from './types'
|
import { BlockClassificationEnum } from './types'
|
||||||
|
|
||||||
export const BLOCKS: Block[] = [
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.Default,
|
|
||||||
type: BlockEnum.Start,
|
|
||||||
title: 'Start',
|
|
||||||
description: '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.Default,
|
|
||||||
type: BlockEnum.LLM,
|
|
||||||
title: 'LLM',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.Default,
|
|
||||||
type: BlockEnum.KnowledgeRetrieval,
|
|
||||||
title: 'Knowledge Retrieval',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.Default,
|
|
||||||
type: BlockEnum.End,
|
|
||||||
title: 'End',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.Default,
|
|
||||||
type: BlockEnum.Answer,
|
|
||||||
title: 'Direct Answer',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.QuestionUnderstand,
|
|
||||||
type: BlockEnum.QuestionClassifier,
|
|
||||||
title: 'Question Classifier',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.Logic,
|
|
||||||
type: BlockEnum.IfElse,
|
|
||||||
title: 'IF/ELSE',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.Logic,
|
|
||||||
type: BlockEnum.LoopEnd,
|
|
||||||
title: 'Exit Loop',
|
|
||||||
description: '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.Logic,
|
|
||||||
type: BlockEnum.Iteration,
|
|
||||||
title: 'Iteration',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.Logic,
|
|
||||||
type: BlockEnum.Loop,
|
|
||||||
title: 'Loop',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.Transform,
|
|
||||||
type: BlockEnum.Code,
|
|
||||||
title: 'Code',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.Transform,
|
|
||||||
type: BlockEnum.TemplateTransform,
|
|
||||||
title: 'Templating Transform',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.Transform,
|
|
||||||
type: BlockEnum.VariableAggregator,
|
|
||||||
title: 'Variable Aggregator',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.Transform,
|
|
||||||
type: BlockEnum.DocExtractor,
|
|
||||||
title: 'Doc Extractor',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.Transform,
|
|
||||||
type: BlockEnum.Assigner,
|
|
||||||
title: 'Variable Assigner',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.Transform,
|
|
||||||
type: BlockEnum.ParameterExtractor,
|
|
||||||
title: 'Parameter Extractor',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.Utilities,
|
|
||||||
type: BlockEnum.HttpRequest,
|
|
||||||
title: 'HTTP Request',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.Utilities,
|
|
||||||
type: BlockEnum.ListFilter,
|
|
||||||
title: 'List Filter',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
classification: BlockClassificationEnum.Default,
|
|
||||||
type: BlockEnum.Agent,
|
|
||||||
title: 'Agent',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
export const BLOCK_CLASSIFICATIONS: string[] = [
|
export const BLOCK_CLASSIFICATIONS: string[] = [
|
||||||
BlockClassificationEnum.Default,
|
BlockClassificationEnum.Default,
|
||||||
BlockClassificationEnum.QuestionUnderstand,
|
BlockClassificationEnum.QuestionUnderstand,
|
||||||
|
|||||||
@ -1,21 +1,9 @@
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { BLOCKS } from './constants'
|
|
||||||
import {
|
import {
|
||||||
TabsEnum,
|
TabsEnum,
|
||||||
ToolTypeEnum,
|
ToolTypeEnum,
|
||||||
} from './types'
|
} from './types'
|
||||||
|
|
||||||
export const useBlocks = () => {
|
|
||||||
const { t } = useTranslation()
|
|
||||||
|
|
||||||
return BLOCKS.map((block) => {
|
|
||||||
return {
|
|
||||||
...block,
|
|
||||||
title: t(`workflow.blocks.${block.type}`),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useTabs = () => {
|
export const useTabs = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
|||||||
@ -1,171 +1,36 @@
|
|||||||
import type {
|
import { useMemo } from 'react'
|
||||||
FC,
|
import type { NodeSelectorProps } from './main'
|
||||||
MouseEventHandler,
|
import NodeSelector from './main'
|
||||||
} from 'react'
|
import { useHooksStore } from '@/app/components/workflow/hooks-store/store'
|
||||||
import {
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
memo,
|
|
||||||
useCallback,
|
|
||||||
useMemo,
|
|
||||||
useState,
|
|
||||||
} from 'react'
|
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
import type {
|
|
||||||
OffsetOptions,
|
|
||||||
Placement,
|
|
||||||
} from '@floating-ui/react'
|
|
||||||
import type { BlockEnum, OnSelectBlock } from '../types'
|
|
||||||
import Tabs from './tabs'
|
|
||||||
import { TabsEnum } from './types'
|
|
||||||
import {
|
|
||||||
PortalToFollowElem,
|
|
||||||
PortalToFollowElemContent,
|
|
||||||
PortalToFollowElemTrigger,
|
|
||||||
} from '@/app/components/base/portal-to-follow-elem'
|
|
||||||
import Input from '@/app/components/base/input'
|
|
||||||
import SearchBox from '@/app/components/plugins/marketplace/search-box'
|
|
||||||
|
|
||||||
import {
|
const NodeSelectorWrapper = (props: NodeSelectorProps) => {
|
||||||
Plus02,
|
const availableNodesMetaData = useHooksStore(s => s.availableNodesMetaData)
|
||||||
} from '@/app/components/base/icons/src/vender/line/general'
|
|
||||||
|
|
||||||
type NodeSelectorProps = {
|
const blocks = useMemo(() => {
|
||||||
open?: boolean
|
const result = availableNodesMetaData?.nodes || []
|
||||||
onOpenChange?: (open: boolean) => void
|
console.log(result, 'result')
|
||||||
onSelect: OnSelectBlock
|
|
||||||
trigger?: (open: boolean) => React.ReactNode
|
|
||||||
placement?: Placement
|
|
||||||
offset?: OffsetOptions
|
|
||||||
triggerStyle?: React.CSSProperties
|
|
||||||
triggerClassName?: (open: boolean) => string
|
|
||||||
triggerInnerClassName?: string
|
|
||||||
popupClassName?: string
|
|
||||||
asChild?: boolean
|
|
||||||
availableBlocksTypes?: BlockEnum[]
|
|
||||||
disabled?: boolean
|
|
||||||
noBlocks?: boolean
|
|
||||||
}
|
|
||||||
const NodeSelector: FC<NodeSelectorProps> = ({
|
|
||||||
open: openFromProps,
|
|
||||||
onOpenChange,
|
|
||||||
onSelect,
|
|
||||||
trigger,
|
|
||||||
placement = 'right',
|
|
||||||
offset = 6,
|
|
||||||
triggerClassName,
|
|
||||||
triggerInnerClassName,
|
|
||||||
triggerStyle,
|
|
||||||
popupClassName,
|
|
||||||
asChild,
|
|
||||||
availableBlocksTypes,
|
|
||||||
disabled,
|
|
||||||
noBlocks = false,
|
|
||||||
}) => {
|
|
||||||
const { t } = useTranslation()
|
|
||||||
const [searchText, setSearchText] = useState('')
|
|
||||||
const [tags, setTags] = useState<string[]>([])
|
|
||||||
const [localOpen, setLocalOpen] = useState(false)
|
|
||||||
const open = openFromProps === undefined ? localOpen : openFromProps
|
|
||||||
const handleOpenChange = useCallback((newOpen: boolean) => {
|
|
||||||
setLocalOpen(newOpen)
|
|
||||||
|
|
||||||
if (!newOpen)
|
return result.filter((block) => {
|
||||||
setSearchText('')
|
if (block.type === BlockEnum.Start)
|
||||||
|
return false
|
||||||
|
|
||||||
if (onOpenChange)
|
if (block.type === BlockEnum.IterationStart)
|
||||||
onOpenChange(newOpen)
|
return false
|
||||||
}, [onOpenChange])
|
|
||||||
const handleTrigger = useCallback<MouseEventHandler<HTMLDivElement>>((e) => {
|
|
||||||
if (disabled)
|
|
||||||
return
|
|
||||||
e.stopPropagation()
|
|
||||||
handleOpenChange(!open)
|
|
||||||
}, [handleOpenChange, open, disabled])
|
|
||||||
const handleSelect = useCallback<OnSelectBlock>((type, toolDefaultValue) => {
|
|
||||||
handleOpenChange(false)
|
|
||||||
onSelect(type, toolDefaultValue)
|
|
||||||
}, [handleOpenChange, onSelect])
|
|
||||||
|
|
||||||
const [activeTab, setActiveTab] = useState(noBlocks ? TabsEnum.Tools : TabsEnum.Blocks)
|
if (block.type === BlockEnum.LoopStart)
|
||||||
const handleActiveTabChange = useCallback((newActiveTab: TabsEnum) => {
|
return false
|
||||||
setActiveTab(newActiveTab)
|
|
||||||
}, [])
|
|
||||||
const searchPlaceholder = useMemo(() => {
|
|
||||||
if (activeTab === TabsEnum.Blocks)
|
|
||||||
return t('workflow.tabs.searchBlock')
|
|
||||||
|
|
||||||
if (activeTab === TabsEnum.Tools)
|
return true
|
||||||
return t('workflow.tabs.searchTool')
|
})
|
||||||
return ''
|
}, [availableNodesMetaData?.nodes])
|
||||||
}, [activeTab, t])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PortalToFollowElem
|
<NodeSelector
|
||||||
placement={placement}
|
{...props}
|
||||||
offset={offset}
|
blocks={blocks}
|
||||||
open={open}
|
/>
|
||||||
onOpenChange={handleOpenChange}
|
|
||||||
>
|
|
||||||
<PortalToFollowElemTrigger
|
|
||||||
asChild={asChild}
|
|
||||||
onClick={handleTrigger}
|
|
||||||
className={triggerInnerClassName}
|
|
||||||
>
|
|
||||||
{
|
|
||||||
trigger
|
|
||||||
? trigger(open)
|
|
||||||
: (
|
|
||||||
<div
|
|
||||||
className={`
|
|
||||||
z-10 flex h-4
|
|
||||||
w-4 cursor-pointer items-center justify-center rounded-full bg-components-button-primary-bg text-text-primary-on-surface hover:bg-components-button-primary-bg-hover
|
|
||||||
${triggerClassName?.(open)}
|
|
||||||
`}
|
|
||||||
style={triggerStyle}
|
|
||||||
>
|
|
||||||
<Plus02 className='h-2.5 w-2.5' />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</PortalToFollowElemTrigger>
|
|
||||||
<PortalToFollowElemContent className='z-[1000]'>
|
|
||||||
<div className={`rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-lg ${popupClassName}`}>
|
|
||||||
<div className='px-2 pt-2' onClick={e => e.stopPropagation()}>
|
|
||||||
{activeTab === TabsEnum.Blocks && (
|
|
||||||
<Input
|
|
||||||
showLeftIcon
|
|
||||||
showClearIcon
|
|
||||||
autoFocus
|
|
||||||
value={searchText}
|
|
||||||
placeholder={searchPlaceholder}
|
|
||||||
onChange={e => setSearchText(e.target.value)}
|
|
||||||
onClear={() => setSearchText('')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{activeTab === TabsEnum.Tools && (
|
|
||||||
<SearchBox
|
|
||||||
search={searchText}
|
|
||||||
onSearchChange={setSearchText}
|
|
||||||
tags={tags}
|
|
||||||
onTagsChange={setTags}
|
|
||||||
size='small'
|
|
||||||
placeholder={t('plugin.searchTools')!}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<Tabs
|
|
||||||
activeTab={activeTab}
|
|
||||||
onActiveTabChange={handleActiveTabChange}
|
|
||||||
onSelect={handleSelect}
|
|
||||||
searchText={searchText}
|
|
||||||
tags={tags}
|
|
||||||
availableBlocksTypes={availableBlocksTypes}
|
|
||||||
noBlocks={noBlocks}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</PortalToFollowElemContent>
|
|
||||||
</PortalToFollowElem>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo(NodeSelector)
|
export default NodeSelectorWrapper
|
||||||
|
|||||||
175
web/app/components/workflow/block-selector/main.tsx
Normal file
175
web/app/components/workflow/block-selector/main.tsx
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
import type {
|
||||||
|
FC,
|
||||||
|
MouseEventHandler,
|
||||||
|
} from 'react'
|
||||||
|
import {
|
||||||
|
memo,
|
||||||
|
useCallback,
|
||||||
|
useMemo,
|
||||||
|
useState,
|
||||||
|
} from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import type {
|
||||||
|
OffsetOptions,
|
||||||
|
Placement,
|
||||||
|
} from '@floating-ui/react'
|
||||||
|
import type {
|
||||||
|
BlockEnum,
|
||||||
|
NodeDefault,
|
||||||
|
OnSelectBlock,
|
||||||
|
} from '../types'
|
||||||
|
import Tabs from './tabs'
|
||||||
|
import { TabsEnum } from './types'
|
||||||
|
import {
|
||||||
|
PortalToFollowElem,
|
||||||
|
PortalToFollowElemContent,
|
||||||
|
PortalToFollowElemTrigger,
|
||||||
|
} from '@/app/components/base/portal-to-follow-elem'
|
||||||
|
import Input from '@/app/components/base/input'
|
||||||
|
import SearchBox from '@/app/components/plugins/marketplace/search-box'
|
||||||
|
|
||||||
|
import {
|
||||||
|
Plus02,
|
||||||
|
} from '@/app/components/base/icons/src/vender/line/general'
|
||||||
|
|
||||||
|
export type NodeSelectorProps = {
|
||||||
|
open?: boolean
|
||||||
|
onOpenChange?: (open: boolean) => void
|
||||||
|
onSelect: OnSelectBlock
|
||||||
|
trigger?: (open: boolean) => React.ReactNode
|
||||||
|
placement?: Placement
|
||||||
|
offset?: OffsetOptions
|
||||||
|
triggerStyle?: React.CSSProperties
|
||||||
|
triggerClassName?: (open: boolean) => string
|
||||||
|
triggerInnerClassName?: string
|
||||||
|
popupClassName?: string
|
||||||
|
asChild?: boolean
|
||||||
|
availableBlocksTypes?: BlockEnum[]
|
||||||
|
disabled?: boolean
|
||||||
|
blocks?: NodeDefault[]
|
||||||
|
}
|
||||||
|
const NodeSelector: FC<NodeSelectorProps> = ({
|
||||||
|
open: openFromProps,
|
||||||
|
onOpenChange,
|
||||||
|
onSelect,
|
||||||
|
trigger,
|
||||||
|
placement = 'right',
|
||||||
|
offset = 6,
|
||||||
|
triggerClassName,
|
||||||
|
triggerInnerClassName,
|
||||||
|
triggerStyle,
|
||||||
|
popupClassName,
|
||||||
|
asChild,
|
||||||
|
availableBlocksTypes,
|
||||||
|
disabled,
|
||||||
|
blocks = [],
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const [searchText, setSearchText] = useState('')
|
||||||
|
const [tags, setTags] = useState<string[]>([])
|
||||||
|
const [localOpen, setLocalOpen] = useState(false)
|
||||||
|
const open = openFromProps === undefined ? localOpen : openFromProps
|
||||||
|
const handleOpenChange = useCallback((newOpen: boolean) => {
|
||||||
|
setLocalOpen(newOpen)
|
||||||
|
|
||||||
|
if (!newOpen)
|
||||||
|
setSearchText('')
|
||||||
|
|
||||||
|
if (onOpenChange)
|
||||||
|
onOpenChange(newOpen)
|
||||||
|
}, [onOpenChange])
|
||||||
|
const handleTrigger = useCallback<MouseEventHandler<HTMLDivElement>>((e) => {
|
||||||
|
if (disabled)
|
||||||
|
return
|
||||||
|
e.stopPropagation()
|
||||||
|
handleOpenChange(!open)
|
||||||
|
}, [handleOpenChange, open, disabled])
|
||||||
|
const handleSelect = useCallback<OnSelectBlock>((type, toolDefaultValue) => {
|
||||||
|
handleOpenChange(false)
|
||||||
|
onSelect(type, toolDefaultValue)
|
||||||
|
}, [handleOpenChange, onSelect])
|
||||||
|
|
||||||
|
const [activeTab, setActiveTab] = useState(!blocks.length ? TabsEnum.Tools : TabsEnum.Blocks)
|
||||||
|
const handleActiveTabChange = useCallback((newActiveTab: TabsEnum) => {
|
||||||
|
setActiveTab(newActiveTab)
|
||||||
|
}, [])
|
||||||
|
const searchPlaceholder = useMemo(() => {
|
||||||
|
if (activeTab === TabsEnum.Blocks)
|
||||||
|
return t('workflow.tabs.searchBlock')
|
||||||
|
|
||||||
|
if (activeTab === TabsEnum.Tools)
|
||||||
|
return t('workflow.tabs.searchTool')
|
||||||
|
return ''
|
||||||
|
}, [activeTab, t])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PortalToFollowElem
|
||||||
|
placement={placement}
|
||||||
|
offset={offset}
|
||||||
|
open={open}
|
||||||
|
onOpenChange={handleOpenChange}
|
||||||
|
>
|
||||||
|
<PortalToFollowElemTrigger
|
||||||
|
asChild={asChild}
|
||||||
|
onClick={handleTrigger}
|
||||||
|
className={triggerInnerClassName}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
trigger
|
||||||
|
? trigger(open)
|
||||||
|
: (
|
||||||
|
<div
|
||||||
|
className={`
|
||||||
|
z-10 flex h-4
|
||||||
|
w-4 cursor-pointer items-center justify-center rounded-full bg-components-button-primary-bg text-text-primary-on-surface hover:bg-components-button-primary-bg-hover
|
||||||
|
${triggerClassName?.(open)}
|
||||||
|
`}
|
||||||
|
style={triggerStyle}
|
||||||
|
>
|
||||||
|
<Plus02 className='h-2.5 w-2.5' />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</PortalToFollowElemTrigger>
|
||||||
|
<PortalToFollowElemContent className='z-[1000]'>
|
||||||
|
<div className={`rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-lg ${popupClassName}`}>
|
||||||
|
<div className='px-2 pt-2' onClick={e => e.stopPropagation()}>
|
||||||
|
{activeTab === TabsEnum.Blocks && (
|
||||||
|
<Input
|
||||||
|
showLeftIcon
|
||||||
|
showClearIcon
|
||||||
|
autoFocus
|
||||||
|
value={searchText}
|
||||||
|
placeholder={searchPlaceholder}
|
||||||
|
onChange={e => setSearchText(e.target.value)}
|
||||||
|
onClear={() => setSearchText('')}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{activeTab === TabsEnum.Tools && (
|
||||||
|
<SearchBox
|
||||||
|
search={searchText}
|
||||||
|
onSearchChange={setSearchText}
|
||||||
|
tags={tags}
|
||||||
|
onTagsChange={setTags}
|
||||||
|
size='small'
|
||||||
|
placeholder={t('plugin.searchTools')!}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<Tabs
|
||||||
|
activeTab={activeTab}
|
||||||
|
onActiveTabChange={handleActiveTabChange}
|
||||||
|
onSelect={handleSelect}
|
||||||
|
searchText={searchText}
|
||||||
|
tags={tags}
|
||||||
|
availableBlocksTypes={availableBlocksTypes}
|
||||||
|
blocks={blocks}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</PortalToFollowElemContent>
|
||||||
|
</PortalToFollowElem>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(NodeSelector)
|
||||||
@ -1,7 +1,10 @@
|
|||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import { memo } from 'react'
|
import { memo } from 'react'
|
||||||
import { useAllBuiltInTools, useAllCustomTools, useAllWorkflowTools } from '@/service/use-tools'
|
import { useAllBuiltInTools, useAllCustomTools, useAllWorkflowTools } from '@/service/use-tools'
|
||||||
import type { BlockEnum } from '../types'
|
import type {
|
||||||
|
BlockEnum,
|
||||||
|
NodeDefault,
|
||||||
|
} from '../types'
|
||||||
import { useTabs } from './hooks'
|
import { useTabs } from './hooks'
|
||||||
import type { ToolDefaultValue } from './types'
|
import type { ToolDefaultValue } from './types'
|
||||||
import { TabsEnum } from './types'
|
import { TabsEnum } from './types'
|
||||||
@ -16,7 +19,7 @@ export type TabsProps = {
|
|||||||
tags: string[]
|
tags: string[]
|
||||||
onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void
|
onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void
|
||||||
availableBlocksTypes?: BlockEnum[]
|
availableBlocksTypes?: BlockEnum[]
|
||||||
noBlocks?: boolean
|
blocks: NodeDefault[]
|
||||||
}
|
}
|
||||||
const Tabs: FC<TabsProps> = ({
|
const Tabs: FC<TabsProps> = ({
|
||||||
activeTab,
|
activeTab,
|
||||||
@ -25,7 +28,7 @@ const Tabs: FC<TabsProps> = ({
|
|||||||
searchText,
|
searchText,
|
||||||
onSelect,
|
onSelect,
|
||||||
availableBlocksTypes,
|
availableBlocksTypes,
|
||||||
noBlocks,
|
blocks,
|
||||||
}) => {
|
}) => {
|
||||||
const tabs = useTabs()
|
const tabs = useTabs()
|
||||||
const { data: buildInTools } = useAllBuiltInTools()
|
const { data: buildInTools } = useAllBuiltInTools()
|
||||||
@ -35,7 +38,7 @@ const Tabs: FC<TabsProps> = ({
|
|||||||
return (
|
return (
|
||||||
<div onClick={e => e.stopPropagation()}>
|
<div onClick={e => e.stopPropagation()}>
|
||||||
{
|
{
|
||||||
!noBlocks && (
|
!!blocks.length && (
|
||||||
<div className='flex items-center border-b-[0.5px] border-divider-subtle px-3'>
|
<div className='flex items-center border-b-[0.5px] border-divider-subtle px-3'>
|
||||||
{
|
{
|
||||||
tabs.map(tab => (
|
tabs.map(tab => (
|
||||||
@ -57,11 +60,12 @@ const Tabs: FC<TabsProps> = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
activeTab === TabsEnum.Blocks && !noBlocks && (
|
activeTab === TabsEnum.Blocks && !!blocks.length && (
|
||||||
<Blocks
|
<Blocks
|
||||||
searchText={searchText}
|
searchText={searchText}
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
availableBlocksTypes={availableBlocksTypes}
|
availableBlocksTypes={availableBlocksTypes}
|
||||||
|
blocks={blocks}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
import { BlockEnum } from './types'
|
|
||||||
|
|
||||||
export const ALL_AVAILABLE_BLOCKS = Object.values(BlockEnum)
|
|
||||||
export const ALL_CHAT_AVAILABLE_BLOCKS = ALL_AVAILABLE_BLOCKS.filter(key => key !== BlockEnum.End && key !== BlockEnum.Start) as BlockEnum[]
|
|
||||||
export const ALL_COMPLETION_AVAILABLE_BLOCKS = ALL_AVAILABLE_BLOCKS.filter(key => key !== BlockEnum.Answer && key !== BlockEnum.Start) as BlockEnum[]
|
|
||||||
@ -1,405 +1,6 @@
|
|||||||
import type { Var } from './types'
|
import type { Var } from './types'
|
||||||
import { BlockEnum, VarType } from './types'
|
import { BlockEnum, VarType } from './types'
|
||||||
import StartNodeDefault from './nodes/start/default'
|
|
||||||
import AnswerDefault from './nodes/answer/default'
|
|
||||||
import LLMDefault from './nodes/llm/default'
|
|
||||||
import KnowledgeRetrievalDefault from './nodes/knowledge-retrieval/default'
|
|
||||||
import QuestionClassifierDefault from './nodes/question-classifier/default'
|
|
||||||
import IfElseDefault from './nodes/if-else/default'
|
|
||||||
import CodeDefault from './nodes/code/default'
|
|
||||||
import TemplateTransformDefault from './nodes/template-transform/default'
|
|
||||||
import HttpRequestDefault from './nodes/http/default'
|
|
||||||
import ParameterExtractorDefault from './nodes/parameter-extractor/default'
|
|
||||||
import ToolDefault from './nodes/tool/default'
|
|
||||||
import VariableAssignerDefault from './nodes/variable-assigner/default'
|
|
||||||
import AssignerDefault from './nodes/assigner/default'
|
|
||||||
import EndNodeDefault from './nodes/end/default'
|
|
||||||
import IterationDefault from './nodes/iteration/default'
|
|
||||||
import LoopDefault from './nodes/loop/default'
|
|
||||||
import DocExtractorDefault from './nodes/document-extractor/default'
|
|
||||||
import ListFilterDefault from './nodes/list-operator/default'
|
|
||||||
import IterationStartDefault from './nodes/iteration-start/default'
|
|
||||||
import AgentDefault from './nodes/agent/default'
|
|
||||||
import LoopStartDefault from './nodes/loop-start/default'
|
|
||||||
import LoopEndDefault from './nodes/loop-end/default'
|
|
||||||
|
|
||||||
type NodesExtraData = {
|
|
||||||
author: string
|
|
||||||
about: string
|
|
||||||
availablePrevNodes: BlockEnum[]
|
|
||||||
availableNextNodes: BlockEnum[]
|
|
||||||
getAvailablePrevNodes: (isChatMode: boolean) => BlockEnum[]
|
|
||||||
getAvailableNextNodes: (isChatMode: boolean) => BlockEnum[]
|
|
||||||
checkValid: any
|
|
||||||
}
|
|
||||||
export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = {
|
|
||||||
[BlockEnum.Start]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: StartNodeDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: StartNodeDefault.getAvailableNextNodes,
|
|
||||||
checkValid: StartNodeDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.End]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: EndNodeDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: EndNodeDefault.getAvailableNextNodes,
|
|
||||||
checkValid: EndNodeDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.Answer]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: AnswerDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: AnswerDefault.getAvailableNextNodes,
|
|
||||||
checkValid: AnswerDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.LLM]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: LLMDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: LLMDefault.getAvailableNextNodes,
|
|
||||||
checkValid: LLMDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.KnowledgeRetrieval]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: KnowledgeRetrievalDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: KnowledgeRetrievalDefault.getAvailableNextNodes,
|
|
||||||
checkValid: KnowledgeRetrievalDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.IfElse]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: IfElseDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: IfElseDefault.getAvailableNextNodes,
|
|
||||||
checkValid: IfElseDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.Iteration]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: IterationDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: IterationDefault.getAvailableNextNodes,
|
|
||||||
checkValid: IterationDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.IterationStart]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: IterationStartDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: IterationStartDefault.getAvailableNextNodes,
|
|
||||||
checkValid: IterationStartDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.Loop]: {
|
|
||||||
author: 'AICT-Team',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: LoopDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: LoopDefault.getAvailableNextNodes,
|
|
||||||
checkValid: LoopDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.LoopStart]: {
|
|
||||||
author: 'AICT-Team',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: LoopStartDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: LoopStartDefault.getAvailableNextNodes,
|
|
||||||
checkValid: LoopStartDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.LoopEnd]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: LoopEndDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: LoopEndDefault.getAvailableNextNodes,
|
|
||||||
checkValid: LoopEndDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.Code]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: CodeDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: CodeDefault.getAvailableNextNodes,
|
|
||||||
checkValid: CodeDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.TemplateTransform]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: TemplateTransformDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: TemplateTransformDefault.getAvailableNextNodes,
|
|
||||||
checkValid: TemplateTransformDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.QuestionClassifier]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: QuestionClassifierDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: QuestionClassifierDefault.getAvailableNextNodes,
|
|
||||||
checkValid: QuestionClassifierDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.HttpRequest]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: HttpRequestDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: HttpRequestDefault.getAvailableNextNodes,
|
|
||||||
checkValid: HttpRequestDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.VariableAssigner]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: VariableAssignerDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: VariableAssignerDefault.getAvailableNextNodes,
|
|
||||||
checkValid: VariableAssignerDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.Assigner]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: AssignerDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: AssignerDefault.getAvailableNextNodes,
|
|
||||||
checkValid: AssignerDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.VariableAggregator]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: VariableAssignerDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: VariableAssignerDefault.getAvailableNextNodes,
|
|
||||||
checkValid: VariableAssignerDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.ParameterExtractor]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: ParameterExtractorDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: ParameterExtractorDefault.getAvailableNextNodes,
|
|
||||||
checkValid: ParameterExtractorDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.Tool]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: ToolDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: ToolDefault.getAvailableNextNodes,
|
|
||||||
checkValid: ToolDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.DocExtractor]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: DocExtractorDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: DocExtractorDefault.getAvailableNextNodes,
|
|
||||||
checkValid: DocExtractorDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.ListFilter]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: ListFilterDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: ListFilterDefault.getAvailableNextNodes,
|
|
||||||
checkValid: ListFilterDefault.checkValid,
|
|
||||||
},
|
|
||||||
[BlockEnum.Agent]: {
|
|
||||||
author: 'Dify',
|
|
||||||
about: '',
|
|
||||||
availablePrevNodes: [],
|
|
||||||
availableNextNodes: [],
|
|
||||||
getAvailablePrevNodes: ListFilterDefault.getAvailablePrevNodes,
|
|
||||||
getAvailableNextNodes: ListFilterDefault.getAvailableNextNodes,
|
|
||||||
checkValid: AgentDefault.checkValid,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export const NODES_INITIAL_DATA = {
|
|
||||||
[BlockEnum.Start]: {
|
|
||||||
type: BlockEnum.Start,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
...StartNodeDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.End]: {
|
|
||||||
type: BlockEnum.End,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
...EndNodeDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.Answer]: {
|
|
||||||
type: BlockEnum.Answer,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
...AnswerDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.LLM]: {
|
|
||||||
type: BlockEnum.LLM,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
variables: [],
|
|
||||||
...LLMDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.KnowledgeRetrieval]: {
|
|
||||||
type: BlockEnum.KnowledgeRetrieval,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
query_variable_selector: [],
|
|
||||||
dataset_ids: [],
|
|
||||||
retrieval_mode: 'single',
|
|
||||||
...KnowledgeRetrievalDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.IfElse]: {
|
|
||||||
type: BlockEnum.IfElse,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
...IfElseDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.Iteration]: {
|
|
||||||
type: BlockEnum.Iteration,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
...IterationDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.IterationStart]: {
|
|
||||||
type: BlockEnum.IterationStart,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
...IterationStartDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.Loop]: {
|
|
||||||
type: BlockEnum.Loop,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
...LoopDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.LoopStart]: {
|
|
||||||
type: BlockEnum.LoopStart,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
...LoopStartDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.LoopEnd]: {
|
|
||||||
type: BlockEnum.LoopEnd,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
...LoopEndDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.Code]: {
|
|
||||||
type: BlockEnum.Code,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
variables: [],
|
|
||||||
code_language: 'python3',
|
|
||||||
code: '',
|
|
||||||
outputs: [],
|
|
||||||
...CodeDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.TemplateTransform]: {
|
|
||||||
type: BlockEnum.TemplateTransform,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
variables: [],
|
|
||||||
template: '',
|
|
||||||
...TemplateTransformDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.QuestionClassifier]: {
|
|
||||||
type: BlockEnum.QuestionClassifier,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
query_variable_selector: [],
|
|
||||||
topics: [],
|
|
||||||
...QuestionClassifierDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.HttpRequest]: {
|
|
||||||
type: BlockEnum.HttpRequest,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
variables: [],
|
|
||||||
...HttpRequestDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.ParameterExtractor]: {
|
|
||||||
type: BlockEnum.ParameterExtractor,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
variables: [],
|
|
||||||
...ParameterExtractorDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.VariableAssigner]: {
|
|
||||||
type: BlockEnum.VariableAssigner,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
variables: [],
|
|
||||||
output_type: '',
|
|
||||||
...VariableAssignerDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.VariableAggregator]: {
|
|
||||||
type: BlockEnum.VariableAggregator,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
variables: [],
|
|
||||||
output_type: '',
|
|
||||||
...VariableAssignerDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.Assigner]: {
|
|
||||||
type: BlockEnum.Assigner,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
...AssignerDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.Tool]: {
|
|
||||||
type: BlockEnum.Tool,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
...ToolDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.DocExtractor]: {
|
|
||||||
type: BlockEnum.DocExtractor,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
...DocExtractorDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.ListFilter]: {
|
|
||||||
type: BlockEnum.ListFilter,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
...ListFilterDefault.defaultValue,
|
|
||||||
},
|
|
||||||
[BlockEnum.Agent]: {
|
|
||||||
type: BlockEnum.Agent,
|
|
||||||
title: '',
|
|
||||||
desc: '',
|
|
||||||
...AgentDefault.defaultValue,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
export const MAX_ITERATION_PARALLEL_NUM = 10
|
export const MAX_ITERATION_PARALLEL_NUM = 10
|
||||||
export const MIN_ITERATION_PARALLEL_NUM = 1
|
export const MIN_ITERATION_PARALLEL_NUM = 1
|
||||||
export const DEFAULT_ITER_TIMES = 1
|
export const DEFAULT_ITER_TIMES = 1
|
||||||
|
|||||||
42
web/app/components/workflow/constants/node.ts
Normal file
42
web/app/components/workflow/constants/node.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import llmDefault from '@/app/components/workflow/nodes/llm/default'
|
||||||
|
import knowledgeRetrievalDefault from '@/app/components/workflow/nodes/knowledge-retrieval/default'
|
||||||
|
import agentDefault from '@/app/components/workflow/nodes/agent/default'
|
||||||
|
|
||||||
|
import questionClassifierDefault from '@/app/components/workflow/nodes/question-classifier/default'
|
||||||
|
|
||||||
|
import ifElseDefault from '@/app/components/workflow/nodes/if-else/default'
|
||||||
|
import iterationDefault from '@/app/components/workflow/nodes/iteration/default'
|
||||||
|
import iterationStartDefault from '@/app/components/workflow/nodes/iteration-start/default'
|
||||||
|
import loopDefault from '@/app/components/workflow/nodes/loop/default'
|
||||||
|
import loopStartDefault from '@/app/components/workflow/nodes/loop-start/default'
|
||||||
|
import loopEndDefault from '@/app/components/workflow/nodes/loop-end/default'
|
||||||
|
|
||||||
|
import codeDefault from '@/app/components/workflow/nodes/code/default'
|
||||||
|
import templateTransformDefault from '@/app/components/workflow/nodes/template-transform/default'
|
||||||
|
import variableAggregatorDefault from '@/app/components/workflow/nodes/variable-assigner/default'
|
||||||
|
import documentExtractorDefault from '@/app/components/workflow/nodes/document-extractor/default'
|
||||||
|
import assignerDefault from '@/app/components/workflow/nodes/assigner/default'
|
||||||
|
import httpRequestDefault from '@/app/components/workflow/nodes/http/default'
|
||||||
|
import parameterExtractorDefault from '@/app/components/workflow/nodes/parameter-extractor/default'
|
||||||
|
import listOperatorDefault from '@/app/components/workflow/nodes/list-operator/default'
|
||||||
|
|
||||||
|
export const WORKFLOW_COMMON_NODES = [
|
||||||
|
llmDefault,
|
||||||
|
knowledgeRetrievalDefault,
|
||||||
|
agentDefault,
|
||||||
|
questionClassifierDefault,
|
||||||
|
ifElseDefault,
|
||||||
|
iterationDefault,
|
||||||
|
iterationStartDefault,
|
||||||
|
loopDefault,
|
||||||
|
loopStartDefault,
|
||||||
|
loopEndDefault,
|
||||||
|
codeDefault,
|
||||||
|
templateTransformDefault,
|
||||||
|
variableAggregatorDefault,
|
||||||
|
documentExtractorDefault,
|
||||||
|
assignerDefault,
|
||||||
|
parameterExtractorDefault,
|
||||||
|
httpRequestDefault,
|
||||||
|
listOperatorDefault,
|
||||||
|
]
|
||||||
@ -56,8 +56,9 @@ const CustomEdge = ({
|
|||||||
})
|
})
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
const { handleNodeAdd } = useNodesInteractions()
|
const { handleNodeAdd } = useNodesInteractions()
|
||||||
const { availablePrevBlocks } = useAvailableBlocks((data as Edge['data'])!.targetType, (data as Edge['data'])?.isInIteration, (data as Edge['data'])?.isInLoop)
|
const { availablePrevBlocks } = useAvailableBlocks((data as Edge['data'])!.targetType, (data as Edge['data'])?.isInIteration || (data as Edge['data'])?.isInLoop)
|
||||||
const { availableNextBlocks } = useAvailableBlocks((data as Edge['data'])!.sourceType, (data as Edge['data'])?.isInIteration, (data as Edge['data'])?.isInLoop)
|
const { availableNextBlocks } = useAvailableBlocks((data as Edge['data'])!.sourceType, (data as Edge['data'])?.isInIteration || (data as Edge['data'])?.isInLoop)
|
||||||
|
console.log(availableNextBlocks, 'xx')
|
||||||
const {
|
const {
|
||||||
_sourceRunningStatus,
|
_sourceRunningStatus,
|
||||||
_targetRunningStatus,
|
_targetRunningStatus,
|
||||||
|
|||||||
@ -7,8 +7,16 @@ import {
|
|||||||
} from 'zustand'
|
} from 'zustand'
|
||||||
import { createStore } from 'zustand/vanilla'
|
import { createStore } from 'zustand/vanilla'
|
||||||
import { HooksStoreContext } from './provider'
|
import { HooksStoreContext } from './provider'
|
||||||
|
import type {
|
||||||
|
BlockEnum,
|
||||||
|
NodeDefault,
|
||||||
|
} from '@/app/components/workflow/types'
|
||||||
|
|
||||||
type CommonHooksFnMap = {
|
export type AvailableNodesMetaData = {
|
||||||
|
nodes: NodeDefault[]
|
||||||
|
nodesMap?: Record<BlockEnum, NodeDefault<any>>
|
||||||
|
}
|
||||||
|
export type CommonHooksFnMap = {
|
||||||
doSyncWorkflowDraft: (
|
doSyncWorkflowDraft: (
|
||||||
notRefreshWhenSyncError?: boolean,
|
notRefreshWhenSyncError?: boolean,
|
||||||
callback?: {
|
callback?: {
|
||||||
@ -26,6 +34,7 @@ type CommonHooksFnMap = {
|
|||||||
handleStartWorkflowRun: () => void
|
handleStartWorkflowRun: () => void
|
||||||
handleWorkflowStartRunInWorkflow: () => void
|
handleWorkflowStartRunInWorkflow: () => void
|
||||||
handleWorkflowStartRunInChatflow: () => void
|
handleWorkflowStartRunInChatflow: () => void
|
||||||
|
availableNodesMetaData?: AvailableNodesMetaData
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Shape = {
|
export type Shape = {
|
||||||
@ -43,6 +52,9 @@ export const createHooksStore = ({
|
|||||||
handleStartWorkflowRun = noop,
|
handleStartWorkflowRun = noop,
|
||||||
handleWorkflowStartRunInWorkflow = noop,
|
handleWorkflowStartRunInWorkflow = noop,
|
||||||
handleWorkflowStartRunInChatflow = noop,
|
handleWorkflowStartRunInChatflow = noop,
|
||||||
|
availableNodesMetaData = {
|
||||||
|
nodes: [],
|
||||||
|
},
|
||||||
}: Partial<Shape>) => {
|
}: Partial<Shape>) => {
|
||||||
return createStore<Shape>(set => ({
|
return createStore<Shape>(set => ({
|
||||||
refreshAll: props => set(state => ({ ...state, ...props })),
|
refreshAll: props => set(state => ({ ...state, ...props })),
|
||||||
@ -56,6 +68,7 @@ export const createHooksStore = ({
|
|||||||
handleStartWorkflowRun,
|
handleStartWorkflowRun,
|
||||||
handleWorkflowStartRunInWorkflow,
|
handleWorkflowStartRunInWorkflow,
|
||||||
handleWorkflowStartRunInChatflow,
|
handleWorkflowStartRunInChatflow,
|
||||||
|
availableNodesMetaData,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
export * from './use-edges-interactions'
|
export * from './use-edges-interactions'
|
||||||
export * from './use-node-data-update'
|
export * from './use-node-data-update'
|
||||||
export * from './use-nodes-interactions'
|
export * from './use-nodes-interactions'
|
||||||
export * from './use-nodes-data'
|
|
||||||
export * from './use-nodes-sync-draft'
|
export * from './use-nodes-sync-draft'
|
||||||
export * from './use-workflow'
|
export * from './use-workflow'
|
||||||
export * from './use-workflow-run'
|
export * from './use-workflow-run'
|
||||||
@ -16,3 +15,5 @@ export * from './use-shortcuts'
|
|||||||
export * from './use-workflow-interactions'
|
export * from './use-workflow-interactions'
|
||||||
export * from './use-workflow-mode'
|
export * from './use-workflow-mode'
|
||||||
export * from './use-format-time-from-now'
|
export * from './use-format-time-from-now'
|
||||||
|
export * from './use-nodes-meta-data'
|
||||||
|
export * from './use-available-blocks'
|
||||||
|
|||||||
58
web/app/components/workflow/hooks/use-available-blocks.ts
Normal file
58
web/app/components/workflow/hooks/use-available-blocks.ts
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import {
|
||||||
|
useCallback,
|
||||||
|
useMemo,
|
||||||
|
} from 'react'
|
||||||
|
import { BlockEnum } from '../types'
|
||||||
|
import { useNodesMetaData } from './use-nodes-meta-data'
|
||||||
|
|
||||||
|
const availableBlocksFilter = (nodeType: BlockEnum, inContainer?: boolean) => {
|
||||||
|
if (inContainer && (nodeType === BlockEnum.Iteration || nodeType === BlockEnum.Loop || nodeType === BlockEnum.End))
|
||||||
|
return false
|
||||||
|
|
||||||
|
if (!inContainer && nodeType === BlockEnum.LoopEnd)
|
||||||
|
return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useAvailableBlocks = (nodeType?: BlockEnum, inContainer?: boolean) => {
|
||||||
|
const {
|
||||||
|
nodes: availableNodes,
|
||||||
|
} = useNodesMetaData()
|
||||||
|
const availableNodesType = useMemo(() => availableNodes.map(node => node.type), [availableNodes])
|
||||||
|
const availablePrevBlocks = useMemo(() => {
|
||||||
|
if (!nodeType || nodeType === BlockEnum.Start)
|
||||||
|
return []
|
||||||
|
|
||||||
|
return availableNodesType
|
||||||
|
}, [availableNodesType, nodeType])
|
||||||
|
const availableNextBlocks = useMemo(() => {
|
||||||
|
if (!nodeType || nodeType === BlockEnum.End || nodeType === BlockEnum.LoopEnd)
|
||||||
|
return []
|
||||||
|
|
||||||
|
return availableNodesType
|
||||||
|
}, [availableNodesType, nodeType])
|
||||||
|
|
||||||
|
const getAvailableBlocks = useCallback((nodeType?: BlockEnum, inContainer?: boolean) => {
|
||||||
|
let availablePrevBlocks = availableNodesType
|
||||||
|
if (!nodeType || nodeType === BlockEnum.Start)
|
||||||
|
availablePrevBlocks = []
|
||||||
|
|
||||||
|
let availableNextBlocks = availableNodesType
|
||||||
|
if (!nodeType || nodeType === BlockEnum.End || nodeType === BlockEnum.LoopEnd)
|
||||||
|
availableNextBlocks = []
|
||||||
|
|
||||||
|
return {
|
||||||
|
availablePrevBlocks: availablePrevBlocks.filter(nType => availableBlocksFilter(nType, inContainer)),
|
||||||
|
availableNextBlocks: availableNextBlocks.filter(nType => availableBlocksFilter(nType, inContainer)),
|
||||||
|
}
|
||||||
|
}, [availableNodesType])
|
||||||
|
|
||||||
|
return useMemo(() => {
|
||||||
|
return {
|
||||||
|
getAvailableBlocks,
|
||||||
|
availablePrevBlocks: availablePrevBlocks.filter(nType => availableBlocksFilter(nType, inContainer)),
|
||||||
|
availableNextBlocks: availableNextBlocks.filter(nType => availableBlocksFilter(nType, inContainer)),
|
||||||
|
}
|
||||||
|
}, [getAvailableBlocks, availablePrevBlocks, availableNextBlocks, inContainer])
|
||||||
|
}
|
||||||
@ -22,7 +22,7 @@ import {
|
|||||||
} from '../constants'
|
} from '../constants'
|
||||||
import type { ToolNodeType } from '../nodes/tool/types'
|
import type { ToolNodeType } from '../nodes/tool/types'
|
||||||
import { useIsChatMode } from './use-workflow'
|
import { useIsChatMode } from './use-workflow'
|
||||||
import { useNodesExtraData } from './use-nodes-data'
|
import { useNodesMetaData } from './use-nodes-meta-data'
|
||||||
import { useToastContext } from '@/app/components/base/toast'
|
import { useToastContext } from '@/app/components/base/toast'
|
||||||
import { CollectionType } from '@/app/components/tools/types'
|
import { CollectionType } from '@/app/components/tools/types'
|
||||||
import { useGetLanguage } from '@/context/i18n'
|
import { useGetLanguage } from '@/context/i18n'
|
||||||
@ -37,7 +37,7 @@ import { fetchDatasets } from '@/service/datasets'
|
|||||||
export const useChecklist = (nodes: Node[], edges: Edge[]) => {
|
export const useChecklist = (nodes: Node[], edges: Edge[]) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const language = useGetLanguage()
|
const language = useGetLanguage()
|
||||||
const nodesExtraData = useNodesExtraData()
|
const { nodesMap: nodesExtraData } = useNodesMetaData()
|
||||||
const isChatMode = useIsChatMode()
|
const isChatMode = useIsChatMode()
|
||||||
const buildInTools = useStore(s => s.buildInTools)
|
const buildInTools = useStore(s => s.buildInTools)
|
||||||
const customTools = useStore(s => s.customTools)
|
const customTools = useStore(s => s.customTools)
|
||||||
@ -100,7 +100,7 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => {
|
|||||||
|
|
||||||
if (node.type === CUSTOM_NODE) {
|
if (node.type === CUSTOM_NODE) {
|
||||||
const checkData = getCheckData(node.data)
|
const checkData = getCheckData(node.data)
|
||||||
const { errorMessage } = nodesExtraData[node.data.type].checkValid(checkData, t, moreDataForCheckValid)
|
const { errorMessage } = nodesExtraData![node.data.type].checkValid(checkData, t, moreDataForCheckValid)
|
||||||
|
|
||||||
if (errorMessage || !validNodes.find(n => n.id === node.id)) {
|
if (errorMessage || !validNodes.find(n => n.id === node.id)) {
|
||||||
list.push({
|
list.push({
|
||||||
@ -148,7 +148,7 @@ export const useChecklistBeforePublish = () => {
|
|||||||
const { notify } = useToastContext()
|
const { notify } = useToastContext()
|
||||||
const isChatMode = useIsChatMode()
|
const isChatMode = useIsChatMode()
|
||||||
const store = useStoreApi()
|
const store = useStoreApi()
|
||||||
const nodesExtraData = useNodesExtraData()
|
const { nodesMap: nodesExtraData } = useNodesMetaData()
|
||||||
const { data: strategyProviders } = useStrategyProviders()
|
const { data: strategyProviders } = useStrategyProviders()
|
||||||
const updateDatasetsDetail = useDatasetsDetailStore(s => s.updateDatasetsDetail)
|
const updateDatasetsDetail = useDatasetsDetailStore(s => s.updateDatasetsDetail)
|
||||||
const updateTime = useRef(0)
|
const updateTime = useRef(0)
|
||||||
@ -228,7 +228,7 @@ export const useChecklistBeforePublish = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const checkData = getCheckData(node.data, datasets)
|
const checkData = getCheckData(node.data, datasets)
|
||||||
const { errorMessage } = nodesExtraData[node.data.type as BlockEnum].checkValid(checkData, t, moreDataForCheckValid)
|
const { errorMessage } = nodesExtraData![node.data.type as BlockEnum].checkValid(checkData, t, moreDataForCheckValid)
|
||||||
|
|
||||||
if (errorMessage) {
|
if (errorMessage) {
|
||||||
notify({ type: 'error', message: `[${node.data.title}] ${errorMessage}` })
|
notify({ type: 'error', message: `[${node.data.title}] ${errorMessage}` })
|
||||||
|
|||||||
@ -1,77 +0,0 @@
|
|||||||
import { useMemo } from 'react'
|
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
import produce from 'immer'
|
|
||||||
import { BlockEnum } from '../types'
|
|
||||||
import {
|
|
||||||
NODES_EXTRA_DATA,
|
|
||||||
NODES_INITIAL_DATA,
|
|
||||||
} from '../constants'
|
|
||||||
import { useIsChatMode } from './use-workflow'
|
|
||||||
|
|
||||||
export const useNodesInitialData = () => {
|
|
||||||
const { t } = useTranslation()
|
|
||||||
|
|
||||||
return useMemo(() => produce(NODES_INITIAL_DATA, (draft) => {
|
|
||||||
Object.keys(draft).forEach((key) => {
|
|
||||||
draft[key as BlockEnum].title = t(`workflow.blocks.${key}`)
|
|
||||||
})
|
|
||||||
}), [t])
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useNodesExtraData = () => {
|
|
||||||
const { t } = useTranslation()
|
|
||||||
const isChatMode = useIsChatMode()
|
|
||||||
|
|
||||||
return useMemo(() => produce(NODES_EXTRA_DATA, (draft) => {
|
|
||||||
Object.keys(draft).forEach((key) => {
|
|
||||||
draft[key as BlockEnum].about = t(`workflow.blocksAbout.${key}`)
|
|
||||||
draft[key as BlockEnum].availablePrevNodes = draft[key as BlockEnum].getAvailablePrevNodes(isChatMode)
|
|
||||||
draft[key as BlockEnum].availableNextNodes = draft[key as BlockEnum].getAvailableNextNodes(isChatMode)
|
|
||||||
})
|
|
||||||
}), [t, isChatMode])
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useAvailableBlocks = (nodeType?: BlockEnum, isInIteration?: boolean, isInLoop?: boolean) => {
|
|
||||||
const nodesExtraData = useNodesExtraData()
|
|
||||||
const availablePrevBlocks = useMemo(() => {
|
|
||||||
if (!nodeType)
|
|
||||||
return []
|
|
||||||
return nodesExtraData[nodeType].availablePrevNodes || []
|
|
||||||
}, [nodeType, nodesExtraData])
|
|
||||||
|
|
||||||
const availableNextBlocks = useMemo(() => {
|
|
||||||
if (!nodeType)
|
|
||||||
return []
|
|
||||||
|
|
||||||
return nodesExtraData[nodeType].availableNextNodes || []
|
|
||||||
}, [nodeType, nodesExtraData])
|
|
||||||
|
|
||||||
return useMemo(() => {
|
|
||||||
return {
|
|
||||||
availablePrevBlocks: availablePrevBlocks.filter((nType) => {
|
|
||||||
if (isInIteration && (nType === BlockEnum.Iteration || nType === BlockEnum.Loop || nType === BlockEnum.End))
|
|
||||||
return false
|
|
||||||
|
|
||||||
if (isInLoop && (nType === BlockEnum.Iteration || nType === BlockEnum.Loop || nType === BlockEnum.End))
|
|
||||||
return false
|
|
||||||
|
|
||||||
if (!isInLoop && nType === BlockEnum.LoopEnd)
|
|
||||||
return false
|
|
||||||
|
|
||||||
return true
|
|
||||||
}),
|
|
||||||
availableNextBlocks: availableNextBlocks.filter((nType) => {
|
|
||||||
if (isInIteration && (nType === BlockEnum.Iteration || nType === BlockEnum.Loop || nType === BlockEnum.End))
|
|
||||||
return false
|
|
||||||
|
|
||||||
if (isInLoop && (nType === BlockEnum.Iteration || nType === BlockEnum.Loop || nType === BlockEnum.End))
|
|
||||||
return false
|
|
||||||
|
|
||||||
if (!isInLoop && nType === BlockEnum.LoopEnd)
|
|
||||||
return false
|
|
||||||
|
|
||||||
return true
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}, [isInIteration, availablePrevBlocks, availableNextBlocks, isInLoop])
|
|
||||||
}
|
|
||||||
@ -31,7 +31,6 @@ import {
|
|||||||
ITERATION_PADDING,
|
ITERATION_PADDING,
|
||||||
LOOP_CHILDREN_Z_INDEX,
|
LOOP_CHILDREN_Z_INDEX,
|
||||||
LOOP_PADDING,
|
LOOP_PADDING,
|
||||||
NODES_INITIAL_DATA,
|
|
||||||
NODE_WIDTH_X_OFFSET,
|
NODE_WIDTH_X_OFFSET,
|
||||||
X_OFFSET,
|
X_OFFSET,
|
||||||
Y_OFFSET,
|
Y_OFFSET,
|
||||||
@ -60,6 +59,7 @@ import {
|
|||||||
useWorkflowReadOnly,
|
useWorkflowReadOnly,
|
||||||
} from './use-workflow'
|
} from './use-workflow'
|
||||||
import { WorkflowHistoryEvent, useWorkflowHistory } from './use-workflow-history'
|
import { WorkflowHistoryEvent, useWorkflowHistory } from './use-workflow-history'
|
||||||
|
import { useNodesMetaData } from './use-nodes-meta-data'
|
||||||
|
|
||||||
export const useNodesInteractions = () => {
|
export const useNodesInteractions = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
@ -84,6 +84,7 @@ export const useNodesInteractions = () => {
|
|||||||
handleNodeLoopChildrenCopy,
|
handleNodeLoopChildrenCopy,
|
||||||
} = useNodeLoopInteractions()
|
} = useNodeLoopInteractions()
|
||||||
const dragNodeStartPosition = useRef({ x: 0, y: 0 } as { x: number; y: number })
|
const dragNodeStartPosition = useRef({ x: 0, y: 0 } as { x: number; y: number })
|
||||||
|
const { nodesMap: nodesMetaDataMap } = useNodesMetaData()
|
||||||
|
|
||||||
const { saveStateToHistory, undo, redo } = useWorkflowHistory()
|
const { saveStateToHistory, undo, redo } = useWorkflowHistory()
|
||||||
|
|
||||||
@ -682,6 +683,10 @@ export const useNodesInteractions = () => {
|
|||||||
} = store.getState()
|
} = store.getState()
|
||||||
const nodes = getNodes()
|
const nodes = getNodes()
|
||||||
const nodesWithSameType = nodes.filter(node => node.data.type === nodeType)
|
const nodesWithSameType = nodes.filter(node => node.data.type === nodeType)
|
||||||
|
const {
|
||||||
|
defaultValue,
|
||||||
|
title,
|
||||||
|
} = nodesMetaDataMap![nodeType]
|
||||||
const {
|
const {
|
||||||
newNode,
|
newNode,
|
||||||
newIterationStartNode,
|
newIterationStartNode,
|
||||||
@ -689,8 +694,8 @@ export const useNodesInteractions = () => {
|
|||||||
} = generateNewNode({
|
} = generateNewNode({
|
||||||
type: getNodeCustomTypeByNodeDataType(nodeType),
|
type: getNodeCustomTypeByNodeDataType(nodeType),
|
||||||
data: {
|
data: {
|
||||||
...NODES_INITIAL_DATA[nodeType],
|
...(defaultValue as any),
|
||||||
title: nodesWithSameType.length > 0 ? `${t(`workflow.blocks.${nodeType}`)} ${nodesWithSameType.length + 1}` : t(`workflow.blocks.${nodeType}`),
|
title: nodesWithSameType.length > 0 ? `${title} ${nodesWithSameType.length + 1}` : title,
|
||||||
...(toolDefaultValue || {}),
|
...(toolDefaultValue || {}),
|
||||||
selected: true,
|
selected: true,
|
||||||
_showAddVariablePopup: (nodeType === BlockEnum.VariableAssigner || nodeType === BlockEnum.VariableAggregator) && !!prevNodeId,
|
_showAddVariablePopup: (nodeType === BlockEnum.VariableAssigner || nodeType === BlockEnum.VariableAggregator) && !!prevNodeId,
|
||||||
@ -1093,7 +1098,7 @@ export const useNodesInteractions = () => {
|
|||||||
}
|
}
|
||||||
handleSyncWorkflowDraft()
|
handleSyncWorkflowDraft()
|
||||||
saveStateToHistory(WorkflowHistoryEvent.NodeAdd)
|
saveStateToHistory(WorkflowHistoryEvent.NodeAdd)
|
||||||
}, [getNodesReadOnly, store, t, handleSyncWorkflowDraft, saveStateToHistory, workflowStore, getAfterNodesInSameBranch, checkNestedParallelLimit])
|
}, [getNodesReadOnly, store, handleSyncWorkflowDraft, saveStateToHistory, workflowStore, getAfterNodesInSameBranch, checkNestedParallelLimit, nodesMetaDataMap])
|
||||||
|
|
||||||
const handleNodeChange = useCallback((
|
const handleNodeChange = useCallback((
|
||||||
currentNodeId: string,
|
currentNodeId: string,
|
||||||
@ -1114,6 +1119,10 @@ export const useNodesInteractions = () => {
|
|||||||
const currentNode = nodes.find(node => node.id === currentNodeId)!
|
const currentNode = nodes.find(node => node.id === currentNodeId)!
|
||||||
const connectedEdges = getConnectedEdges([currentNode], edges)
|
const connectedEdges = getConnectedEdges([currentNode], edges)
|
||||||
const nodesWithSameType = nodes.filter(node => node.data.type === nodeType)
|
const nodesWithSameType = nodes.filter(node => node.data.type === nodeType)
|
||||||
|
const {
|
||||||
|
defaultValue,
|
||||||
|
title,
|
||||||
|
} = nodesMetaDataMap![nodeType]
|
||||||
const {
|
const {
|
||||||
newNode: newCurrentNode,
|
newNode: newCurrentNode,
|
||||||
newIterationStartNode,
|
newIterationStartNode,
|
||||||
@ -1121,8 +1130,8 @@ export const useNodesInteractions = () => {
|
|||||||
} = generateNewNode({
|
} = generateNewNode({
|
||||||
type: getNodeCustomTypeByNodeDataType(nodeType),
|
type: getNodeCustomTypeByNodeDataType(nodeType),
|
||||||
data: {
|
data: {
|
||||||
...NODES_INITIAL_DATA[nodeType],
|
...(defaultValue as any),
|
||||||
title: nodesWithSameType.length > 0 ? `${t(`workflow.blocks.${nodeType}`)} ${nodesWithSameType.length + 1}` : t(`workflow.blocks.${nodeType}`),
|
title: nodesWithSameType.length > 0 ? `${title} ${nodesWithSameType.length + 1}` : title,
|
||||||
...(toolDefaultValue || {}),
|
...(toolDefaultValue || {}),
|
||||||
_connectedSourceHandleIds: [],
|
_connectedSourceHandleIds: [],
|
||||||
_connectedTargetHandleIds: [],
|
_connectedTargetHandleIds: [],
|
||||||
@ -1175,7 +1184,7 @@ export const useNodesInteractions = () => {
|
|||||||
handleSyncWorkflowDraft()
|
handleSyncWorkflowDraft()
|
||||||
|
|
||||||
saveStateToHistory(WorkflowHistoryEvent.NodeChange)
|
saveStateToHistory(WorkflowHistoryEvent.NodeChange)
|
||||||
}, [getNodesReadOnly, store, t, handleSyncWorkflowDraft, saveStateToHistory])
|
}, [getNodesReadOnly, store, handleSyncWorkflowDraft, saveStateToHistory, nodesMetaDataMap])
|
||||||
|
|
||||||
const handleNodesCancelSelected = useCallback(() => {
|
const handleNodesCancelSelected = useCallback(() => {
|
||||||
const {
|
const {
|
||||||
@ -1285,7 +1294,7 @@ export const useNodesInteractions = () => {
|
|||||||
} = generateNewNode({
|
} = generateNewNode({
|
||||||
type: nodeToPaste.type,
|
type: nodeToPaste.type,
|
||||||
data: {
|
data: {
|
||||||
...NODES_INITIAL_DATA[nodeType],
|
...nodesMetaDataMap![nodeType].defaultValue,
|
||||||
...nodeToPaste.data,
|
...nodeToPaste.data,
|
||||||
selected: false,
|
selected: false,
|
||||||
_isBundled: false,
|
_isBundled: false,
|
||||||
@ -1361,7 +1370,7 @@ export const useNodesInteractions = () => {
|
|||||||
saveStateToHistory(WorkflowHistoryEvent.NodePaste)
|
saveStateToHistory(WorkflowHistoryEvent.NodePaste)
|
||||||
handleSyncWorkflowDraft()
|
handleSyncWorkflowDraft()
|
||||||
}
|
}
|
||||||
}, [getNodesReadOnly, workflowStore, store, reactflow, saveStateToHistory, handleSyncWorkflowDraft, handleNodeIterationChildrenCopy, handleNodeLoopChildrenCopy])
|
}, [getNodesReadOnly, workflowStore, store, reactflow, saveStateToHistory, handleSyncWorkflowDraft, handleNodeIterationChildrenCopy, handleNodeLoopChildrenCopy, nodesMetaDataMap])
|
||||||
|
|
||||||
const handleNodesDuplicate = useCallback((nodeId?: string) => {
|
const handleNodesDuplicate = useCallback((nodeId?: string) => {
|
||||||
if (getNodesReadOnly())
|
if (getNodesReadOnly())
|
||||||
|
|||||||
14
web/app/components/workflow/hooks/use-nodes-meta-data.ts
Normal file
14
web/app/components/workflow/hooks/use-nodes-meta-data.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { useMemo } from 'react'
|
||||||
|
import type { AvailableNodesMetaData } from '@/app/components/workflow/hooks-store'
|
||||||
|
import { useHooksStore } from '@/app/components/workflow/hooks-store'
|
||||||
|
|
||||||
|
export const useNodesMetaData = () => {
|
||||||
|
const availableNodesMetaData = useHooksStore(s => s.availableNodesMetaData)
|
||||||
|
|
||||||
|
return useMemo(() => {
|
||||||
|
return {
|
||||||
|
nodes: availableNodesMetaData?.nodes || [],
|
||||||
|
nodesMap: availableNodesMetaData?.nodesMap || {},
|
||||||
|
} as AvailableNodesMetaData
|
||||||
|
}, [availableNodesMetaData])
|
||||||
|
}
|
||||||
@ -35,7 +35,7 @@ import {
|
|||||||
} from '../constants'
|
} from '../constants'
|
||||||
import { CUSTOM_NOTE_NODE } from '../note-node/constants'
|
import { CUSTOM_NOTE_NODE } from '../note-node/constants'
|
||||||
import { findUsedVarNodes, getNodeOutputVars, updateNodeVars } from '../nodes/_base/components/variable/utils'
|
import { findUsedVarNodes, getNodeOutputVars, updateNodeVars } from '../nodes/_base/components/variable/utils'
|
||||||
import { useNodesExtraData } from './use-nodes-data'
|
import { useAvailableBlocks } from './use-available-blocks'
|
||||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||||
import {
|
import {
|
||||||
fetchAllBuiltInTools,
|
fetchAllBuiltInTools,
|
||||||
@ -58,7 +58,7 @@ export const useWorkflow = () => {
|
|||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const store = useStoreApi()
|
const store = useStoreApi()
|
||||||
const workflowStore = useWorkflowStore()
|
const workflowStore = useWorkflowStore()
|
||||||
const nodesExtraData = useNodesExtraData()
|
const { getAvailableBlocks } = useAvailableBlocks()
|
||||||
const setPanelWidth = useCallback((width: number) => {
|
const setPanelWidth = useCallback((width: number) => {
|
||||||
localStorage.setItem('workflow-node-panel-width', `${width}`)
|
localStorage.setItem('workflow-node-panel-width', `${width}`)
|
||||||
workflowStore.setState({ panelWidth: width })
|
workflowStore.setState({ panelWidth: width })
|
||||||
@ -364,8 +364,8 @@ export const useWorkflow = () => {
|
|||||||
return false
|
return false
|
||||||
|
|
||||||
if (sourceNode && targetNode) {
|
if (sourceNode && targetNode) {
|
||||||
const sourceNodeAvailableNextNodes = nodesExtraData[sourceNode.data.type].availableNextNodes
|
const sourceNodeAvailableNextNodes = getAvailableBlocks(sourceNode.data.type, !!sourceNode.parentId).availableNextBlocks
|
||||||
const targetNodeAvailablePrevNodes = [...nodesExtraData[targetNode.data.type].availablePrevNodes, BlockEnum.Start]
|
const targetNodeAvailablePrevNodes = getAvailableBlocks(targetNode.data.type, !!targetNode.parentId).availablePrevBlocks
|
||||||
|
|
||||||
if (!sourceNodeAvailableNextNodes.includes(targetNode.data.type))
|
if (!sourceNodeAvailableNextNodes.includes(targetNode.data.type))
|
||||||
return false
|
return false
|
||||||
@ -389,7 +389,7 @@ export const useWorkflow = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return !hasCycle(targetNode)
|
return !hasCycle(targetNode)
|
||||||
}, [store, nodesExtraData, checkParallelLimit])
|
}, [store, checkParallelLimit, getAvailableBlocks])
|
||||||
|
|
||||||
const getNode = useCallback((nodeId?: string) => {
|
const getNode = useCallback((nodeId?: string) => {
|
||||||
const { getNodes } = store.getState()
|
const { getNodes } = store.getState()
|
||||||
|
|||||||
@ -17,7 +17,7 @@ const ErrorHandleTip = ({
|
|||||||
|
|
||||||
if (type === ErrorHandleTypeEnum.defaultValue)
|
if (type === ErrorHandleTypeEnum.defaultValue)
|
||||||
return t('workflow.nodes.common.errorHandle.defaultValue.inLog')
|
return t('workflow.nodes.common.errorHandle.defaultValue.inLog')
|
||||||
}, [])
|
}, [t, type])
|
||||||
|
|
||||||
if (!type)
|
if (!type)
|
||||||
return null
|
return null
|
||||||
|
|||||||
@ -38,7 +38,7 @@ const Add = ({
|
|||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
const { handleNodeAdd } = useNodesInteractions()
|
const { handleNodeAdd } = useNodesInteractions()
|
||||||
const { nodesReadOnly } = useNodesReadOnly()
|
const { nodesReadOnly } = useNodesReadOnly()
|
||||||
const { availableNextBlocks } = useAvailableBlocks(nodeData.type, nodeData.isInIteration, nodeData.isInLoop)
|
const { availableNextBlocks } = useAvailableBlocks(nodeData.type, nodeData.isInIteration || nodeData.isInLoop)
|
||||||
const { checkParallelLimit } = useWorkflow()
|
const { checkParallelLimit } = useWorkflow()
|
||||||
|
|
||||||
const handleSelect = useCallback<OnSelectBlock>((type, toolDefaultValue) => {
|
const handleSelect = useCallback<OnSelectBlock>((type, toolDefaultValue) => {
|
||||||
|
|||||||
@ -36,7 +36,7 @@ const ChangeItem = ({
|
|||||||
const {
|
const {
|
||||||
availablePrevBlocks,
|
availablePrevBlocks,
|
||||||
availableNextBlocks,
|
availableNextBlocks,
|
||||||
} = useAvailableBlocks(data.type, data.isInIteration, data.isInLoop)
|
} = useAvailableBlocks(data.type, data.isInIteration || data.isInLoop)
|
||||||
|
|
||||||
const handleSelect = useCallback<OnSelectBlock>((type, toolDefaultValue) => {
|
const handleSelect = useCallback<OnSelectBlock>((type, toolDefaultValue) => {
|
||||||
handleNodeChange(nodeId, type, sourceHandle, toolDefaultValue)
|
handleNodeChange(nodeId, type, sourceHandle, toolDefaultValue)
|
||||||
|
|||||||
@ -47,7 +47,7 @@ export const NodeTargetHandle = memo(({
|
|||||||
const { handleNodeAdd } = useNodesInteractions()
|
const { handleNodeAdd } = useNodesInteractions()
|
||||||
const { getNodesReadOnly } = useNodesReadOnly()
|
const { getNodesReadOnly } = useNodesReadOnly()
|
||||||
const connected = data._connectedTargetHandleIds?.includes(handleId)
|
const connected = data._connectedTargetHandleIds?.includes(handleId)
|
||||||
const { availablePrevBlocks } = useAvailableBlocks(data.type, data.isInIteration, data.isInLoop)
|
const { availablePrevBlocks } = useAvailableBlocks(data.type, data.isInIteration || data.isInLoop)
|
||||||
const isConnectable = !!availablePrevBlocks.length
|
const isConnectable = !!availablePrevBlocks.length
|
||||||
|
|
||||||
const handleOpenChange = useCallback((v: boolean) => {
|
const handleOpenChange = useCallback((v: boolean) => {
|
||||||
@ -129,7 +129,7 @@ export const NodeSourceHandle = memo(({
|
|||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
const { handleNodeAdd } = useNodesInteractions()
|
const { handleNodeAdd } = useNodesInteractions()
|
||||||
const { getNodesReadOnly } = useNodesReadOnly()
|
const { getNodesReadOnly } = useNodesReadOnly()
|
||||||
const { availableNextBlocks } = useAvailableBlocks(data.type, data.isInIteration, data.isInLoop)
|
const { availableNextBlocks } = useAvailableBlocks(data.type, data.isInIteration || data.isInLoop)
|
||||||
const isConnectable = !!availableNextBlocks.length
|
const isConnectable = !!availableNextBlocks.length
|
||||||
const isChatMode = useIsChatMode()
|
const isChatMode = useIsChatMode()
|
||||||
const { checkParallelLimit } = useWorkflow()
|
const { checkParallelLimit } = useWorkflow()
|
||||||
|
|||||||
@ -30,7 +30,7 @@ const ChangeBlock = ({
|
|||||||
const {
|
const {
|
||||||
availablePrevBlocks,
|
availablePrevBlocks,
|
||||||
availableNextBlocks,
|
availableNextBlocks,
|
||||||
} = useAvailableBlocks(nodeData.type, nodeData.isInIteration, nodeData.isInLoop)
|
} = useAvailableBlocks(nodeData.type, nodeData.isInIteration || nodeData.isInLoop)
|
||||||
|
|
||||||
const availableNodes = useMemo(() => {
|
const availableNodes = useMemo(() => {
|
||||||
if (availablePrevBlocks.length && availableNextBlocks.length)
|
if (availablePrevBlocks.length && availableNextBlocks.length)
|
||||||
|
|||||||
@ -12,8 +12,8 @@ import {
|
|||||||
import { useStore } from '@/app/components/workflow/store'
|
import { useStore } from '@/app/components/workflow/store'
|
||||||
import {
|
import {
|
||||||
useNodeDataUpdate,
|
useNodeDataUpdate,
|
||||||
useNodesExtraData,
|
|
||||||
useNodesInteractions,
|
useNodesInteractions,
|
||||||
|
useNodesMetaData,
|
||||||
useNodesReadOnly,
|
useNodesReadOnly,
|
||||||
useNodesSyncDraft,
|
useNodesSyncDraft,
|
||||||
} from '@/app/components/workflow/hooks'
|
} from '@/app/components/workflow/hooks'
|
||||||
@ -48,14 +48,14 @@ const PanelOperatorPopup = ({
|
|||||||
const { handleNodeDataUpdate } = useNodeDataUpdate()
|
const { handleNodeDataUpdate } = useNodeDataUpdate()
|
||||||
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
|
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
|
||||||
const { nodesReadOnly } = useNodesReadOnly()
|
const { nodesReadOnly } = useNodesReadOnly()
|
||||||
const nodesExtraData = useNodesExtraData()
|
const { nodesMap: nodesExtraData } = useNodesMetaData()
|
||||||
const buildInTools = useStore(s => s.buildInTools)
|
const buildInTools = useStore(s => s.buildInTools)
|
||||||
const customTools = useStore(s => s.customTools)
|
const customTools = useStore(s => s.customTools)
|
||||||
const workflowTools = useStore(s => s.workflowTools)
|
const workflowTools = useStore(s => s.workflowTools)
|
||||||
const edge = edges.find(edge => edge.target === id)
|
const edge = edges.find(edge => edge.target === id)
|
||||||
const author = useMemo(() => {
|
const author = useMemo(() => {
|
||||||
if (data.type !== BlockEnum.Tool)
|
if (data.type !== BlockEnum.Tool)
|
||||||
return nodesExtraData[data.type].author
|
return nodesExtraData![data.type].author
|
||||||
|
|
||||||
if (data.provider_type === CollectionType.builtIn)
|
if (data.provider_type === CollectionType.builtIn)
|
||||||
return buildInTools.find(toolWithProvider => canFindTool(toolWithProvider.id, data.provider_id))?.author
|
return buildInTools.find(toolWithProvider => canFindTool(toolWithProvider.id, data.provider_id))?.author
|
||||||
@ -68,7 +68,7 @@ const PanelOperatorPopup = ({
|
|||||||
|
|
||||||
const about = useMemo(() => {
|
const about = useMemo(() => {
|
||||||
if (data.type !== BlockEnum.Tool)
|
if (data.type !== BlockEnum.Tool)
|
||||||
return nodesExtraData[data.type].about
|
return nodesExtraData![data.type].description
|
||||||
|
|
||||||
if (data.provider_type === CollectionType.builtIn)
|
if (data.provider_type === CollectionType.builtIn)
|
||||||
return buildInTools.find(toolWithProvider => canFindTool(toolWithProvider.id, data.provider_id))?.description[language]
|
return buildInTools.find(toolWithProvider => canFindTool(toolWithProvider.id, data.provider_id))?.description[language]
|
||||||
|
|||||||
@ -1,69 +1,15 @@
|
|||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { useGetLanguage } from '@/context/i18n'
|
import type { BlockEnum } from '@/app/components/workflow/types'
|
||||||
import { BlockEnum } from '@/app/components/workflow/types'
|
import { useNodesMetaData } from '@/app/components/workflow/hooks'
|
||||||
|
|
||||||
export const useNodeHelpLink = (nodeType: BlockEnum) => {
|
export const useNodeHelpLink = (nodeType: BlockEnum) => {
|
||||||
const language = useGetLanguage()
|
const availableNodesMetaData = useNodesMetaData()
|
||||||
const prefixLink = useMemo(() => {
|
|
||||||
if (language === 'zh_Hans')
|
|
||||||
return 'https://docs.dify.ai/zh-hans/guides/workflow/node/'
|
|
||||||
|
|
||||||
return 'https://docs.dify.ai/guides/workflow/node/'
|
const link = useMemo(() => {
|
||||||
}, [language])
|
const result = availableNodesMetaData?.nodesMap?.[nodeType]?.helpLinkUri || ''
|
||||||
const linkMap = useMemo(() => {
|
|
||||||
if (language === 'zh_Hans') {
|
|
||||||
return {
|
|
||||||
[BlockEnum.Start]: 'start',
|
|
||||||
[BlockEnum.End]: 'end',
|
|
||||||
[BlockEnum.Answer]: 'answer',
|
|
||||||
[BlockEnum.LLM]: 'llm',
|
|
||||||
[BlockEnum.KnowledgeRetrieval]: 'knowledge-retrieval',
|
|
||||||
[BlockEnum.QuestionClassifier]: 'question-classifier',
|
|
||||||
[BlockEnum.IfElse]: 'ifelse',
|
|
||||||
[BlockEnum.Code]: 'code',
|
|
||||||
[BlockEnum.TemplateTransform]: 'template',
|
|
||||||
[BlockEnum.VariableAssigner]: 'variable-assigner',
|
|
||||||
[BlockEnum.VariableAggregator]: 'variable-aggregator',
|
|
||||||
[BlockEnum.Assigner]: 'variable-assigner',
|
|
||||||
[BlockEnum.Iteration]: 'iteration',
|
|
||||||
[BlockEnum.Loop]: 'loop',
|
|
||||||
[BlockEnum.ParameterExtractor]: 'parameter-extractor',
|
|
||||||
[BlockEnum.HttpRequest]: 'http-request',
|
|
||||||
[BlockEnum.Tool]: 'tools',
|
|
||||||
[BlockEnum.DocExtractor]: 'doc-extractor',
|
|
||||||
[BlockEnum.ListFilter]: 'list-operator',
|
|
||||||
[BlockEnum.Agent]: 'agent',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return result
|
||||||
[BlockEnum.Start]: 'start',
|
}, [availableNodesMetaData, nodeType])
|
||||||
[BlockEnum.End]: 'end',
|
|
||||||
[BlockEnum.Answer]: 'answer',
|
|
||||||
[BlockEnum.LLM]: 'llm',
|
|
||||||
[BlockEnum.KnowledgeRetrieval]: 'knowledge-retrieval',
|
|
||||||
[BlockEnum.QuestionClassifier]: 'question-classifier',
|
|
||||||
[BlockEnum.IfElse]: 'ifelse',
|
|
||||||
[BlockEnum.Code]: 'code',
|
|
||||||
[BlockEnum.TemplateTransform]: 'template',
|
|
||||||
[BlockEnum.VariableAssigner]: 'variable-assigner',
|
|
||||||
[BlockEnum.VariableAggregator]: 'variable-aggregator',
|
|
||||||
[BlockEnum.Assigner]: 'variable-assigner',
|
|
||||||
[BlockEnum.Iteration]: 'iteration',
|
|
||||||
[BlockEnum.Loop]: 'loop',
|
|
||||||
[BlockEnum.ParameterExtractor]: 'parameter-extractor',
|
|
||||||
[BlockEnum.HttpRequest]: 'http-request',
|
|
||||||
[BlockEnum.Tool]: 'tools',
|
|
||||||
[BlockEnum.DocExtractor]: 'doc-extractor',
|
|
||||||
[BlockEnum.ListFilter]: 'list-operator',
|
|
||||||
[BlockEnum.Agent]: 'agent',
|
|
||||||
}
|
|
||||||
}, [language]) as Record<string, string>
|
|
||||||
|
|
||||||
const link = linkMap[nodeType]
|
return link
|
||||||
|
|
||||||
if (!link)
|
|
||||||
return ''
|
|
||||||
|
|
||||||
return `${prefixLink}${link}`
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -68,7 +68,7 @@ const BasePanel: FC<BasePanelProps> = ({
|
|||||||
const { handleNodeSelect } = useNodesInteractions()
|
const { handleNodeSelect } = useNodesInteractions()
|
||||||
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
|
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
|
||||||
const { nodesReadOnly } = useNodesReadOnly()
|
const { nodesReadOnly } = useNodesReadOnly()
|
||||||
const { availableNextBlocks } = useAvailableBlocks(data.type, data.isInIteration, data.isInLoop)
|
const { availableNextBlocks } = useAvailableBlocks(data.type, data.isInIteration || data.isInLoop)
|
||||||
const toolIcon = useToolIcon(data)
|
const toolIcon = useToolIcon(data)
|
||||||
|
|
||||||
const handleResize = useCallback((width: number) => {
|
const handleResize = useCallback((width: number) => {
|
||||||
|
|||||||
@ -1,23 +1,18 @@
|
|||||||
import type { StrategyDetail, StrategyPluginDetail } from '@/app/components/plugins/types'
|
import type { StrategyDetail, StrategyPluginDetail } from '@/app/components/plugins/types'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
|
||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import type { AgentNodeType } from './types'
|
import type { AgentNodeType } from './types'
|
||||||
import { FormTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
import { FormTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||||
import { renderI18nObject } from '@/i18n'
|
import { renderI18nObject } from '@/i18n'
|
||||||
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<AgentNodeType> = {
|
const nodeDefault: NodeDefault<AgentNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
sort: 3,
|
||||||
|
type: BlockEnum.Agent,
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode) {
|
|
||||||
return isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode) {
|
|
||||||
return isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
},
|
|
||||||
checkValid(payload, t, moreDataForCheckValid: {
|
checkValid(payload, t, moreDataForCheckValid: {
|
||||||
strategyProvider?: StrategyPluginDetail,
|
strategyProvider?: StrategyPluginDetail,
|
||||||
strategy?: StrategyDetail
|
strategy?: StrategyDetail
|
||||||
|
|||||||
@ -1,25 +1,17 @@
|
|||||||
import { BlockEnum } from '../../types'
|
|
||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import type { AnswerNodeType } from './types'
|
import type { AnswerNodeType } from './types'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<AnswerNodeType> = {
|
const nodeDefault: NodeDefault<AnswerNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
sort: 2.1,
|
||||||
|
type: BlockEnum.Answer,
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
variables: [],
|
variables: [],
|
||||||
answer: '',
|
answer: '',
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid(payload: AnswerNodeType, t: any) {
|
checkValid(payload: AnswerNodeType, t: any) {
|
||||||
let errorMessages = ''
|
let errorMessages = ''
|
||||||
const { answer } = payload
|
const { answer } = payload
|
||||||
|
|||||||
@ -1,24 +1,21 @@
|
|||||||
import { BlockEnum } from '../../types'
|
|
||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import { type AssignerNodeType, WriteMode } from './types'
|
import { type AssignerNodeType, WriteMode } from './types'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
import { BlockClassificationEnum } from '@/app/components/workflow/block-selector/types'
|
||||||
const i18nPrefix = 'workflow.errorMsg'
|
const i18nPrefix = 'workflow.errorMsg'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<AssignerNodeType> = {
|
const nodeDefault: NodeDefault<AssignerNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
classification: BlockClassificationEnum.Transform,
|
||||||
|
sort: 5,
|
||||||
|
type: BlockEnum.Assigner,
|
||||||
|
helpLinkUri: 'variable-assigner',
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
version: '2',
|
version: '2',
|
||||||
items: [],
|
items: [],
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid(payload: AssignerNodeType, t: any) {
|
checkValid(payload: AssignerNodeType, t: any) {
|
||||||
let errorMessages = ''
|
let errorMessages = ''
|
||||||
const {
|
const {
|
||||||
|
|||||||
@ -1,27 +1,23 @@
|
|||||||
import { BlockEnum } from '../../types'
|
|
||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import { CodeLanguage, type CodeNodeType } from './types'
|
import { CodeLanguage, type CodeNodeType } from './types'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
import { BlockClassificationEnum } from '@/app/components/workflow/block-selector/types'
|
||||||
|
|
||||||
const i18nPrefix = 'workflow.errorMsg'
|
const i18nPrefix = 'workflow.errorMsg'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<CodeNodeType> = {
|
const nodeDefault: NodeDefault<CodeNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
classification: BlockClassificationEnum.Transform,
|
||||||
|
sort: 1,
|
||||||
|
type: BlockEnum.Code,
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
code: '',
|
code: '',
|
||||||
code_language: CodeLanguage.python3,
|
code_language: CodeLanguage.python3,
|
||||||
variables: [],
|
variables: [],
|
||||||
outputs: {},
|
outputs: {},
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid(payload: CodeNodeType, t: any) {
|
checkValid(payload: CodeNodeType, t: any) {
|
||||||
let errorMessages = ''
|
let errorMessages = ''
|
||||||
const { code, variables } = payload
|
const { code, variables } = payload
|
||||||
|
|||||||
@ -1,24 +1,21 @@
|
|||||||
import { BlockEnum } from '../../types'
|
|
||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import type { DocExtractorNodeType } from './types'
|
import type { DocExtractorNodeType } from './types'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
import { BlockClassificationEnum } from '@/app/components/workflow/block-selector/types'
|
||||||
const i18nPrefix = 'workflow.errorMsg'
|
const i18nPrefix = 'workflow.errorMsg'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<DocExtractorNodeType> = {
|
const nodeDefault: NodeDefault<DocExtractorNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
classification: BlockClassificationEnum.Transform,
|
||||||
|
sort: 4,
|
||||||
|
type: BlockEnum.DocExtractor,
|
||||||
|
helpLinkUri: 'doc-extractor',
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
variable_selector: [],
|
variable_selector: [],
|
||||||
is_array_file: false,
|
is_array_file: false,
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid(payload: DocExtractorNodeType, t: any) {
|
checkValid(payload: DocExtractorNodeType, t: any) {
|
||||||
let errorMessages = ''
|
let errorMessages = ''
|
||||||
const { variable_selector: variable } = payload
|
const { variable_selector: variable } = payload
|
||||||
|
|||||||
@ -1,21 +1,16 @@
|
|||||||
import { BlockEnum } from '../../types'
|
|
||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import type { EndNodeType } from './types'
|
import type { EndNodeType } from './types'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<EndNodeType> = {
|
const nodeDefault: NodeDefault<EndNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
sort: 2.1,
|
||||||
|
type: BlockEnum.End,
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
outputs: [],
|
outputs: [],
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
getAvailableNextNodes() {
|
|
||||||
return []
|
|
||||||
},
|
|
||||||
checkValid() {
|
checkValid() {
|
||||||
return {
|
return {
|
||||||
isValid: true,
|
isValid: true,
|
||||||
|
|||||||
@ -1,13 +1,16 @@
|
|||||||
import { BlockEnum } from '../../types'
|
|
||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import { AuthorizationType, BodyType, Method } from './types'
|
import { AuthorizationType, BodyType, Method } from './types'
|
||||||
import type { BodyPayload, HttpNodeType } from './types'
|
import type { BodyPayload, HttpNodeType } from './types'
|
||||||
import {
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
ALL_CHAT_AVAILABLE_BLOCKS,
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
ALL_COMPLETION_AVAILABLE_BLOCKS,
|
import { BlockClassificationEnum } from '@/app/components/workflow/block-selector/types'
|
||||||
} from '@/app/components/workflow/blocks'
|
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<HttpNodeType> = {
|
const nodeDefault: NodeDefault<HttpNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
classification: BlockClassificationEnum.Utilities,
|
||||||
|
sort: 1,
|
||||||
|
type: BlockEnum.HttpRequest,
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
variables: [],
|
variables: [],
|
||||||
method: Method.get,
|
method: Method.get,
|
||||||
@ -33,16 +36,6 @@ const nodeDefault: NodeDefault<HttpNodeType> = {
|
|||||||
retry_interval: 100,
|
retry_interval: 100,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid(payload: HttpNodeType, t: any) {
|
checkValid(payload: HttpNodeType, t: any) {
|
||||||
let errorMessages = ''
|
let errorMessages = ''
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,18 @@
|
|||||||
import { BlockEnum, type NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import { type IfElseNodeType, LogicalOperator } from './types'
|
import { type IfElseNodeType, LogicalOperator } from './types'
|
||||||
import { isEmptyRelatedOperator } from './utils'
|
import { isEmptyRelatedOperator } from './utils'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
import { BlockClassificationEnum } from '@/app/components/workflow/block-selector/types'
|
||||||
const i18nPrefix = 'workflow.errorMsg'
|
const i18nPrefix = 'workflow.errorMsg'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<IfElseNodeType> = {
|
const nodeDefault: NodeDefault<IfElseNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
classification: BlockClassificationEnum.Logic,
|
||||||
|
sort: 1,
|
||||||
|
type: BlockEnum.IfElse,
|
||||||
|
helpLinkUri: 'ifelse',
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
_targetBranches: [
|
_targetBranches: [
|
||||||
{
|
{
|
||||||
@ -24,16 +32,6 @@ const nodeDefault: NodeDefault<IfElseNodeType> = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid(payload: IfElseNodeType, t: any) {
|
checkValid(payload: IfElseNodeType, t: any) {
|
||||||
let errorMessages = ''
|
let errorMessages = ''
|
||||||
const { cases } = payload
|
const { cases } = payload
|
||||||
|
|||||||
@ -1,16 +1,14 @@
|
|||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import type { IterationStartNodeType } from './types'
|
import type { IterationStartNodeType } from './types'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<IterationStartNodeType> = {
|
const nodeDefault: NodeDefault<IterationStartNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
sort: -1,
|
||||||
|
type: BlockEnum.IterationStart,
|
||||||
|
}),
|
||||||
defaultValue: {},
|
defaultValue: {},
|
||||||
getAvailablePrevNodes() {
|
|
||||||
return []
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid() {
|
checkValid() {
|
||||||
return {
|
return {
|
||||||
isValid: true,
|
isValid: true,
|
||||||
|
|||||||
@ -1,13 +1,17 @@
|
|||||||
import { BlockEnum, ErrorHandleMode } from '../../types'
|
import { ErrorHandleMode } from '../../types'
|
||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import type { IterationNodeType } from './types'
|
import type { IterationNodeType } from './types'
|
||||||
import {
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
ALL_CHAT_AVAILABLE_BLOCKS,
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
ALL_COMPLETION_AVAILABLE_BLOCKS,
|
import { BlockClassificationEnum } from '@/app/components/workflow/block-selector/types'
|
||||||
} from '@/app/components/workflow/blocks'
|
|
||||||
const i18nPrefix = 'workflow'
|
const i18nPrefix = 'workflow'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<IterationNodeType> = {
|
const nodeDefault: NodeDefault<IterationNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
classification: BlockClassificationEnum.Logic,
|
||||||
|
sort: 2,
|
||||||
|
type: BlockEnum.Iteration,
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
start_node_id: '',
|
start_node_id: '',
|
||||||
iterator_selector: [],
|
iterator_selector: [],
|
||||||
@ -18,20 +22,6 @@ const nodeDefault: NodeDefault<IterationNodeType> = {
|
|||||||
parallel_nums: 10,
|
parallel_nums: 10,
|
||||||
error_handle_mode: ErrorHandleMode.Terminated,
|
error_handle_mode: ErrorHandleMode.Terminated,
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(
|
|
||||||
type => type !== BlockEnum.End,
|
|
||||||
)
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid(payload: IterationNodeType, t: any) {
|
checkValid(payload: IterationNodeType, t: any) {
|
||||||
let errorMessages = ''
|
let errorMessages = ''
|
||||||
|
|
||||||
|
|||||||
@ -12,13 +12,14 @@ import {
|
|||||||
} from '../../utils'
|
} from '../../utils'
|
||||||
import {
|
import {
|
||||||
ITERATION_PADDING,
|
ITERATION_PADDING,
|
||||||
NODES_INITIAL_DATA,
|
|
||||||
} from '../../constants'
|
} from '../../constants'
|
||||||
import { CUSTOM_ITERATION_START_NODE } from '../iteration-start/constants'
|
import { CUSTOM_ITERATION_START_NODE } from '../iteration-start/constants'
|
||||||
|
import { useNodesMetaData } from '@/app/components/workflow/hooks'
|
||||||
|
|
||||||
export const useNodeIterationInteractions = () => {
|
export const useNodeIterationInteractions = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const store = useStoreApi()
|
const store = useStoreApi()
|
||||||
|
const { nodesMap: nodesMetaDataMap } = useNodesMetaData()
|
||||||
|
|
||||||
const handleNodeIterationRerender = useCallback((nodeId: string) => {
|
const handleNodeIterationRerender = useCallback((nodeId: string) => {
|
||||||
const {
|
const {
|
||||||
@ -120,7 +121,7 @@ export const useNodeIterationInteractions = () => {
|
|||||||
const { newNode } = generateNewNode({
|
const { newNode } = generateNewNode({
|
||||||
type: getNodeCustomTypeByNodeDataType(childNodeType),
|
type: getNodeCustomTypeByNodeDataType(childNodeType),
|
||||||
data: {
|
data: {
|
||||||
...NODES_INITIAL_DATA[childNodeType],
|
...nodesMetaDataMap![childNodeType].defaultValue,
|
||||||
...child.data,
|
...child.data,
|
||||||
selected: false,
|
selected: false,
|
||||||
_isBundled: false,
|
_isBundled: false,
|
||||||
|
|||||||
@ -1,13 +1,17 @@
|
|||||||
import { BlockEnum } from '../../types'
|
|
||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import type { KnowledgeRetrievalNodeType } from './types'
|
import type { KnowledgeRetrievalNodeType } from './types'
|
||||||
import { checkoutRerankModelConfigedInRetrievalSettings } from './utils'
|
import { checkoutRerankModelConfigedInRetrievalSettings } from './utils'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
|
||||||
import { DATASET_DEFAULT } from '@/config'
|
import { DATASET_DEFAULT } from '@/config'
|
||||||
import { RETRIEVE_TYPE } from '@/types/app'
|
import { RETRIEVE_TYPE } from '@/types/app'
|
||||||
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
const i18nPrefix = 'workflow'
|
const i18nPrefix = 'workflow'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<KnowledgeRetrievalNodeType> = {
|
const nodeDefault: NodeDefault<KnowledgeRetrievalNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
sort: 2,
|
||||||
|
type: BlockEnum.KnowledgeRetrieval,
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
query_variable_selector: [],
|
query_variable_selector: [],
|
||||||
dataset_ids: [],
|
dataset_ids: [],
|
||||||
@ -18,16 +22,6 @@ const nodeDefault: NodeDefault<KnowledgeRetrievalNodeType> = {
|
|||||||
reranking_enable: false,
|
reranking_enable: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid(payload: KnowledgeRetrievalNodeType, t: any) {
|
checkValid(payload: KnowledgeRetrievalNodeType, t: any) {
|
||||||
let errorMessages = ''
|
let errorMessages = ''
|
||||||
if (!errorMessages && (!payload.query_variable_selector || payload.query_variable_selector.length === 0))
|
if (!errorMessages && (!payload.query_variable_selector || payload.query_variable_selector.length === 0))
|
||||||
|
|||||||
@ -1,11 +1,18 @@
|
|||||||
import { BlockEnum, VarType } from '../../types'
|
import { VarType } from '../../types'
|
||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import { comparisonOperatorNotRequireValue } from '../if-else/utils'
|
import { comparisonOperatorNotRequireValue } from '../if-else/utils'
|
||||||
import { type ListFilterNodeType, OrderBy } from './types'
|
import { type ListFilterNodeType, OrderBy } from './types'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
import { BlockClassificationEnum } from '@/app/components/workflow/block-selector/types'
|
||||||
const i18nPrefix = 'workflow.errorMsg'
|
const i18nPrefix = 'workflow.errorMsg'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<ListFilterNodeType> = {
|
const nodeDefault: NodeDefault<ListFilterNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
classification: BlockClassificationEnum.Utilities,
|
||||||
|
sort: 2,
|
||||||
|
type: BlockEnum.ListFilter,
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
variable: [],
|
variable: [],
|
||||||
filter_by: {
|
filter_by: {
|
||||||
@ -26,16 +33,6 @@ const nodeDefault: NodeDefault<ListFilterNodeType> = {
|
|||||||
size: 10,
|
size: 10,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid(payload: ListFilterNodeType, t: any) {
|
checkValid(payload: ListFilterNodeType, t: any) {
|
||||||
let errorMessages = ''
|
let errorMessages = ''
|
||||||
const { variable, var_type, filter_by } = payload
|
const { variable, var_type, filter_by } = payload
|
||||||
|
|||||||
@ -1,11 +1,16 @@
|
|||||||
import { BlockEnum, EditionType } from '../../types'
|
import { EditionType } from '../../types'
|
||||||
import { type NodeDefault, type PromptItem, PromptRole } from '../../types'
|
import { type NodeDefault, type PromptItem, PromptRole } from '../../types'
|
||||||
import type { LLMNodeType } from './types'
|
import type { LLMNodeType } from './types'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
|
||||||
const i18nPrefix = 'workflow.errorMsg'
|
const i18nPrefix = 'workflow.errorMsg'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<LLMNodeType> = {
|
const nodeDefault: NodeDefault<LLMNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
sort: 1,
|
||||||
|
type: BlockEnum.LLM,
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
model: {
|
model: {
|
||||||
provider: '',
|
provider: '',
|
||||||
@ -27,16 +32,6 @@ const nodeDefault: NodeDefault<LLMNodeType> = {
|
|||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid(payload: LLMNodeType, t: any) {
|
checkValid(payload: LLMNodeType, t: any) {
|
||||||
let errorMessages = ''
|
let errorMessages = ''
|
||||||
if (!errorMessages && !payload.model.provider)
|
if (!errorMessages && !payload.model.provider)
|
||||||
|
|||||||
@ -1,18 +1,18 @@
|
|||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
|
||||||
import type {
|
import type {
|
||||||
SimpleNodeType,
|
SimpleNodeType,
|
||||||
} from '@/app/components/workflow/simple-node/types'
|
} from '@/app/components/workflow/simple-node/types'
|
||||||
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
import { BlockClassificationEnum } from '@/app/components/workflow/block-selector/types'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<SimpleNodeType> = {
|
const nodeDefault: NodeDefault<SimpleNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
classification: BlockClassificationEnum.Logic,
|
||||||
|
sort: 2,
|
||||||
|
type: BlockEnum.LoopEnd,
|
||||||
|
}),
|
||||||
defaultValue: {},
|
defaultValue: {},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
getAvailableNextNodes() {
|
|
||||||
return []
|
|
||||||
},
|
|
||||||
checkValid() {
|
checkValid() {
|
||||||
return {
|
return {
|
||||||
isValid: true,
|
isValid: true,
|
||||||
|
|||||||
@ -1,16 +1,14 @@
|
|||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import type { LoopStartNodeType } from './types'
|
import type { LoopStartNodeType } from './types'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<LoopStartNodeType> = {
|
const nodeDefault: NodeDefault<LoopStartNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
sort: -1,
|
||||||
|
type: BlockEnum.LoopStart,
|
||||||
|
}),
|
||||||
defaultValue: {},
|
defaultValue: {},
|
||||||
getAvailablePrevNodes() {
|
|
||||||
return []
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid() {
|
checkValid() {
|
||||||
return {
|
return {
|
||||||
isValid: true,
|
isValid: true,
|
||||||
|
|||||||
@ -32,7 +32,7 @@ const AddBlock = ({
|
|||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { nodesReadOnly } = useNodesReadOnly()
|
const { nodesReadOnly } = useNodesReadOnly()
|
||||||
const { handleNodeAdd } = useNodesInteractions()
|
const { handleNodeAdd } = useNodesInteractions()
|
||||||
const { availableNextBlocks } = useAvailableBlocks(BlockEnum.Start, false, true)
|
const { availableNextBlocks } = useAvailableBlocks(BlockEnum.Start, true)
|
||||||
|
|
||||||
const handleSelect = useCallback<OnSelectBlock>((type, toolDefaultValue) => {
|
const handleSelect = useCallback<OnSelectBlock>((type, toolDefaultValue) => {
|
||||||
handleNodeAdd(
|
handleNodeAdd(
|
||||||
|
|||||||
@ -1,13 +1,20 @@
|
|||||||
import { BlockEnum } from '../../types'
|
|
||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import { ComparisonOperator, LogicalOperator, type LoopNodeType } from './types'
|
import { ComparisonOperator, LogicalOperator, type LoopNodeType } from './types'
|
||||||
import { isEmptyRelatedOperator } from './utils'
|
import { isEmptyRelatedOperator } from './utils'
|
||||||
import { TransferMethod } from '@/types/app'
|
import { TransferMethod } from '@/types/app'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
|
||||||
import { LOOP_NODE_MAX_COUNT } from '@/config'
|
import { LOOP_NODE_MAX_COUNT } from '@/config'
|
||||||
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
import { BlockClassificationEnum } from '@/app/components/workflow/block-selector/types'
|
||||||
const i18nPrefix = 'workflow.errorMsg'
|
const i18nPrefix = 'workflow.errorMsg'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<LoopNodeType> = {
|
const nodeDefault: NodeDefault<LoopNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
classification: BlockClassificationEnum.Logic,
|
||||||
|
sort: 3,
|
||||||
|
type: BlockEnum.Loop,
|
||||||
|
// author: 'AICT-Team',
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
start_node_id: '',
|
start_node_id: '',
|
||||||
break_conditions: [],
|
break_conditions: [],
|
||||||
@ -15,16 +22,6 @@ const nodeDefault: NodeDefault<LoopNodeType> = {
|
|||||||
_children: [],
|
_children: [],
|
||||||
logical_operator: LogicalOperator.and,
|
logical_operator: LogicalOperator.and,
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid(payload: LoopNodeType, t: any) {
|
checkValid(payload: LoopNodeType, t: any) {
|
||||||
let errorMessages = ''
|
let errorMessages = ''
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { useCallback } from 'react'
|
import { useCallback } from 'react'
|
||||||
import produce from 'immer'
|
import produce from 'immer'
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
import { useStoreApi } from 'reactflow'
|
import { useStoreApi } from 'reactflow'
|
||||||
import type {
|
import type {
|
||||||
BlockEnum,
|
BlockEnum,
|
||||||
@ -12,13 +11,13 @@ import {
|
|||||||
} from '../../utils'
|
} from '../../utils'
|
||||||
import {
|
import {
|
||||||
LOOP_PADDING,
|
LOOP_PADDING,
|
||||||
NODES_INITIAL_DATA,
|
|
||||||
} from '../../constants'
|
} from '../../constants'
|
||||||
import { CUSTOM_LOOP_START_NODE } from '../loop-start/constants'
|
import { CUSTOM_LOOP_START_NODE } from '../loop-start/constants'
|
||||||
|
import { useNodesMetaData } from '@/app/components/workflow/hooks'
|
||||||
|
|
||||||
export const useNodeLoopInteractions = () => {
|
export const useNodeLoopInteractions = () => {
|
||||||
const { t } = useTranslation()
|
|
||||||
const store = useStoreApi()
|
const store = useStoreApi()
|
||||||
|
const { nodesMap: nodesMetaDataMap } = useNodesMetaData()
|
||||||
|
|
||||||
const handleNodeLoopRerender = useCallback((nodeId: string) => {
|
const handleNodeLoopRerender = useCallback((nodeId: string) => {
|
||||||
const {
|
const {
|
||||||
@ -115,17 +114,21 @@ export const useNodeLoopInteractions = () => {
|
|||||||
|
|
||||||
return childrenNodes.map((child, index) => {
|
return childrenNodes.map((child, index) => {
|
||||||
const childNodeType = child.data.type as BlockEnum
|
const childNodeType = child.data.type as BlockEnum
|
||||||
|
const {
|
||||||
|
defaultValue,
|
||||||
|
title,
|
||||||
|
} = nodesMetaDataMap![childNodeType]
|
||||||
const nodesWithSameType = nodes.filter(node => node.data.type === childNodeType)
|
const nodesWithSameType = nodes.filter(node => node.data.type === childNodeType)
|
||||||
const { newNode } = generateNewNode({
|
const { newNode } = generateNewNode({
|
||||||
type: getNodeCustomTypeByNodeDataType(childNodeType),
|
type: getNodeCustomTypeByNodeDataType(childNodeType),
|
||||||
data: {
|
data: {
|
||||||
...NODES_INITIAL_DATA[childNodeType],
|
...defaultValue,
|
||||||
...child.data,
|
...child.data,
|
||||||
selected: false,
|
selected: false,
|
||||||
_isBundled: false,
|
_isBundled: false,
|
||||||
_connectedSourceHandleIds: [],
|
_connectedSourceHandleIds: [],
|
||||||
_connectedTargetHandleIds: [],
|
_connectedTargetHandleIds: [],
|
||||||
title: nodesWithSameType.length > 0 ? `${t(`workflow.blocks.${childNodeType}`)} ${nodesWithSameType.length + 1}` : t(`workflow.blocks.${childNodeType}`),
|
title: nodesWithSameType.length > 0 ? `${title} ${nodesWithSameType.length + 1}` : title,
|
||||||
loop_id: newNodeId,
|
loop_id: newNodeId,
|
||||||
|
|
||||||
},
|
},
|
||||||
@ -138,7 +141,7 @@ export const useNodeLoopInteractions = () => {
|
|||||||
newNode.id = `${newNodeId}${newNode.id + index}`
|
newNode.id = `${newNodeId}${newNode.id + index}`
|
||||||
return newNode
|
return newNode
|
||||||
})
|
})
|
||||||
}, [store, t])
|
}, [store, nodesMetaDataMap])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
handleNodeLoopRerender,
|
handleNodeLoopRerender,
|
||||||
|
|||||||
@ -1,10 +1,16 @@
|
|||||||
import { BlockEnum } from '../../types'
|
|
||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import { type ParameterExtractorNodeType, ReasoningModeType } from './types'
|
import { type ParameterExtractorNodeType, ReasoningModeType } from './types'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
import { BlockClassificationEnum } from '@/app/components/workflow/block-selector/types'
|
||||||
const i18nPrefix = 'workflow'
|
const i18nPrefix = 'workflow'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<ParameterExtractorNodeType> = {
|
const nodeDefault: NodeDefault<ParameterExtractorNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
classification: BlockClassificationEnum.Transform,
|
||||||
|
sort: 6,
|
||||||
|
type: BlockEnum.ParameterExtractor,
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
query: [],
|
query: [],
|
||||||
model: {
|
model: {
|
||||||
@ -20,16 +26,6 @@ const nodeDefault: NodeDefault<ParameterExtractorNodeType> = {
|
|||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid(payload: ParameterExtractorNodeType, t: any) {
|
checkValid(payload: ParameterExtractorNodeType, t: any) {
|
||||||
let errorMessages = ''
|
let errorMessages = ''
|
||||||
if (!errorMessages && (!payload.query || payload.query.length === 0))
|
if (!errorMessages && (!payload.query || payload.query.length === 0))
|
||||||
|
|||||||
@ -1,11 +1,17 @@
|
|||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import { BlockEnum } from '../../types'
|
|
||||||
import type { QuestionClassifierNodeType } from './types'
|
import type { QuestionClassifierNodeType } from './types'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
import { BlockClassificationEnum } from '@/app/components/workflow/block-selector/types'
|
||||||
|
|
||||||
const i18nPrefix = 'workflow'
|
const i18nPrefix = 'workflow'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<QuestionClassifierNodeType> = {
|
const nodeDefault: NodeDefault<QuestionClassifierNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
classification: BlockClassificationEnum.QuestionUnderstand,
|
||||||
|
sort: 1,
|
||||||
|
type: BlockEnum.QuestionClassifier,
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
query_variable_selector: [],
|
query_variable_selector: [],
|
||||||
model: {
|
model: {
|
||||||
@ -40,16 +46,6 @@ const nodeDefault: NodeDefault<QuestionClassifierNodeType> = {
|
|||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid(payload: QuestionClassifierNodeType, t: any) {
|
checkValid(payload: QuestionClassifierNodeType, t: any) {
|
||||||
let errorMessages = ''
|
let errorMessages = ''
|
||||||
if (!errorMessages && (!payload.query_variable_selector || payload.query_variable_selector.length === 0))
|
if (!errorMessages && (!payload.query_variable_selector || payload.query_variable_selector.length === 0))
|
||||||
|
|||||||
@ -1,18 +1,16 @@
|
|||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import type { StartNodeType } from './types'
|
import type { StartNodeType } from './types'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<StartNodeType> = {
|
const nodeDefault: NodeDefault<StartNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
sort: 0.1,
|
||||||
|
type: BlockEnum.Start,
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
variables: [],
|
variables: [],
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes() {
|
|
||||||
return []
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid() {
|
checkValid() {
|
||||||
return {
|
return {
|
||||||
isValid: true,
|
isValid: true,
|
||||||
|
|||||||
@ -1,23 +1,21 @@
|
|||||||
import { BlockEnum } from '../../types'
|
|
||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import type { TemplateTransformNodeType } from './types'
|
import type { TemplateTransformNodeType } from './types'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
import { BlockClassificationEnum } from '@/app/components/workflow/block-selector/types'
|
||||||
const i18nPrefix = 'workflow.errorMsg'
|
const i18nPrefix = 'workflow.errorMsg'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<TemplateTransformNodeType> = {
|
const nodeDefault: NodeDefault<TemplateTransformNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
classification: BlockClassificationEnum.Transform,
|
||||||
|
sort: 2,
|
||||||
|
type: BlockEnum.TemplateTransform,
|
||||||
|
helpLinkUri: 'template',
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
|
template: '',
|
||||||
variables: [],
|
variables: [],
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid(payload: TemplateTransformNodeType, t: any) {
|
checkValid(payload: TemplateTransformNodeType, t: any) {
|
||||||
let errorMessages = ''
|
let errorMessages = ''
|
||||||
const { template, variables } = payload
|
const { template, variables } = payload
|
||||||
|
|||||||
@ -1,26 +1,21 @@
|
|||||||
import { BlockEnum } from '../../types'
|
|
||||||
import type { NodeDefault } from '../../types'
|
import type { NodeDefault } from '../../types'
|
||||||
import type { ToolNodeType } from './types'
|
import type { ToolNodeType } from './types'
|
||||||
import { VarType as VarKindType } from '@/app/components/workflow/nodes/tool/types'
|
import { VarType as VarKindType } from '@/app/components/workflow/nodes/tool/types'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
|
||||||
const i18nPrefix = 'workflow.errorMsg'
|
const i18nPrefix = 'workflow.errorMsg'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<ToolNodeType> = {
|
const nodeDefault: NodeDefault<ToolNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
sort: -1,
|
||||||
|
type: BlockEnum.Tool,
|
||||||
|
helpLinkUri: 'tools',
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
tool_parameters: {},
|
tool_parameters: {},
|
||||||
tool_configurations: {},
|
tool_configurations: {},
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid(payload: ToolNodeType, t: any, moreDataForCheckValid: any) {
|
checkValid(payload: ToolNodeType, t: any, moreDataForCheckValid: any) {
|
||||||
const { toolInputsSchema, toolSettingSchema, language, notAuthed } = moreDataForCheckValid
|
const { toolInputsSchema, toolSettingSchema, language, notAuthed } = moreDataForCheckValid
|
||||||
let errorMessages = ''
|
let errorMessages = ''
|
||||||
|
|||||||
@ -1,25 +1,21 @@
|
|||||||
import { type NodeDefault, VarType } from '../../types'
|
import { type NodeDefault, VarType } from '../../types'
|
||||||
import { BlockEnum } from '../../types'
|
|
||||||
import type { VariableAssignerNodeType } from './types'
|
import type { VariableAssignerNodeType } from './types'
|
||||||
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks'
|
import { genNodeMetaData } from '@/app/components/workflow/utils'
|
||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
import { BlockClassificationEnum } from '@/app/components/workflow/block-selector/types'
|
||||||
|
|
||||||
const i18nPrefix = 'workflow'
|
const i18nPrefix = 'workflow'
|
||||||
|
|
||||||
const nodeDefault: NodeDefault<VariableAssignerNodeType> = {
|
const nodeDefault: NodeDefault<VariableAssignerNodeType> = {
|
||||||
|
...genNodeMetaData({
|
||||||
|
classification: BlockClassificationEnum.Transform,
|
||||||
|
sort: 3,
|
||||||
|
type: BlockEnum.VariableAggregator,
|
||||||
|
}),
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
output_type: VarType.any,
|
output_type: VarType.any,
|
||||||
variables: [],
|
variables: [],
|
||||||
},
|
},
|
||||||
getAvailablePrevNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode
|
|
||||||
? ALL_CHAT_AVAILABLE_BLOCKS
|
|
||||||
: ALL_COMPLETION_AVAILABLE_BLOCKS.filter(type => type !== BlockEnum.End)
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
getAvailableNextNodes(isChatMode: boolean) {
|
|
||||||
const nodes = isChatMode ? ALL_CHAT_AVAILABLE_BLOCKS : ALL_COMPLETION_AVAILABLE_BLOCKS
|
|
||||||
return nodes
|
|
||||||
},
|
|
||||||
checkValid(payload: VariableAssignerNodeType, t: any) {
|
checkValid(payload: VariableAssignerNodeType, t: any) {
|
||||||
let errorMessages = ''
|
let errorMessages = ''
|
||||||
const { variables, advanced_settings } = payload
|
const { variables, advanced_settings } = payload
|
||||||
|
|||||||
@ -13,10 +13,10 @@ import {
|
|||||||
} from '../utils'
|
} from '../utils'
|
||||||
import {
|
import {
|
||||||
useAvailableBlocks,
|
useAvailableBlocks,
|
||||||
|
useNodesMetaData,
|
||||||
useNodesReadOnly,
|
useNodesReadOnly,
|
||||||
usePanelInteractions,
|
usePanelInteractions,
|
||||||
} from '../hooks'
|
} from '../hooks'
|
||||||
import { NODES_INITIAL_DATA } from '../constants'
|
|
||||||
import { useWorkflowStore } from '../store'
|
import { useWorkflowStore } from '../store'
|
||||||
import TipPopup from './tip-popup'
|
import TipPopup from './tip-popup'
|
||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
@ -43,6 +43,7 @@ const AddBlock = ({
|
|||||||
const { handlePaneContextmenuCancel } = usePanelInteractions()
|
const { handlePaneContextmenuCancel } = usePanelInteractions()
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
const { availableNextBlocks } = useAvailableBlocks(BlockEnum.Start, false)
|
const { availableNextBlocks } = useAvailableBlocks(BlockEnum.Start, false)
|
||||||
|
const { nodesMap: nodesMetaDataMap } = useNodesMetaData()
|
||||||
|
|
||||||
const handleOpenChange = useCallback((open: boolean) => {
|
const handleOpenChange = useCallback((open: boolean) => {
|
||||||
setOpen(open)
|
setOpen(open)
|
||||||
@ -56,11 +57,15 @@ const AddBlock = ({
|
|||||||
} = store.getState()
|
} = store.getState()
|
||||||
const nodes = getNodes()
|
const nodes = getNodes()
|
||||||
const nodesWithSameType = nodes.filter(node => node.data.type === type)
|
const nodesWithSameType = nodes.filter(node => node.data.type === type)
|
||||||
|
const {
|
||||||
|
defaultValue,
|
||||||
|
title,
|
||||||
|
} = nodesMetaDataMap![type]
|
||||||
const { newNode } = generateNewNode({
|
const { newNode } = generateNewNode({
|
||||||
type: getNodeCustomTypeByNodeDataType(type),
|
type: getNodeCustomTypeByNodeDataType(type),
|
||||||
data: {
|
data: {
|
||||||
...NODES_INITIAL_DATA[type],
|
...(defaultValue as any),
|
||||||
title: nodesWithSameType.length > 0 ? `${t(`workflow.blocks.${type}`)} ${nodesWithSameType.length + 1}` : t(`workflow.blocks.${type}`),
|
title: nodesWithSameType.length > 0 ? `${title} ${nodesWithSameType.length + 1}` : title,
|
||||||
...(toolDefaultValue || {}),
|
...(toolDefaultValue || {}),
|
||||||
_isCandidate: true,
|
_isCandidate: true,
|
||||||
},
|
},
|
||||||
@ -72,7 +77,7 @@ const AddBlock = ({
|
|||||||
workflowStore.setState({
|
workflowStore.setState({
|
||||||
candidateNode: newNode,
|
candidateNode: newNode,
|
||||||
})
|
})
|
||||||
}, [store, workflowStore, t])
|
}, [store, workflowStore, nodesMetaDataMap])
|
||||||
|
|
||||||
const renderTriggerElement = useCallback((open: boolean) => {
|
const renderTriggerElement = useCallback((open: boolean) => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import type {
|
|||||||
} from '@/app/components/workflow/nodes/_base/components/error-handle/types'
|
} from '@/app/components/workflow/nodes/_base/components/error-handle/types'
|
||||||
import type { WorkflowRetryConfig } from '@/app/components/workflow/nodes/_base/components/retry/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 { StructuredOutput } from '@/app/components/workflow/nodes/llm/types'
|
||||||
|
import type { BlockClassificationEnum } from '@/app/components/workflow/block-selector/types'
|
||||||
|
|
||||||
export enum BlockEnum {
|
export enum BlockEnum {
|
||||||
Start = 'start',
|
Start = 'start',
|
||||||
@ -285,17 +286,15 @@ export type NodeOutPutVar = {
|
|||||||
isLoop?: boolean
|
isLoop?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Block = {
|
export type NodeDefault<T = {}> = {
|
||||||
classification?: string
|
classification: BlockClassificationEnum
|
||||||
|
sort: number
|
||||||
type: BlockEnum
|
type: BlockEnum
|
||||||
title: string
|
title: string
|
||||||
|
author: string
|
||||||
description?: string
|
description?: string
|
||||||
}
|
helpLinkUri?: string
|
||||||
|
|
||||||
export type NodeDefault<T> = {
|
|
||||||
defaultValue: Partial<T>
|
defaultValue: Partial<T>
|
||||||
getAvailablePrevNodes: (isChatMode: boolean) => BlockEnum[]
|
|
||||||
getAvailableNextNodes: (isChatMode: boolean) => BlockEnum[]
|
|
||||||
checkValid: (payload: T, t: any, moreDataForCheckValid?: any) => { isValid: boolean; errorMessage?: string }
|
checkValid: (payload: T, t: any, moreDataForCheckValid?: any) => { isValid: boolean; errorMessage?: string }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
web/app/components/workflow/utils/gen-node-meta-data.ts
Normal file
28
web/app/components/workflow/utils/gen-node-meta-data.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { BlockClassificationEnum } from '@/app/components/workflow/block-selector/types'
|
||||||
|
import type { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
|
||||||
|
export type GenNodeMetaDataParams = {
|
||||||
|
classification?: BlockClassificationEnum
|
||||||
|
sort: number
|
||||||
|
type: BlockEnum
|
||||||
|
title?: string
|
||||||
|
author?: string
|
||||||
|
helpLinkUri?: string
|
||||||
|
}
|
||||||
|
export const genNodeMetaData = ({
|
||||||
|
classification = BlockClassificationEnum.Default,
|
||||||
|
sort,
|
||||||
|
type,
|
||||||
|
title = '',
|
||||||
|
author = 'Dify',
|
||||||
|
helpLinkUri,
|
||||||
|
}: GenNodeMetaDataParams) => {
|
||||||
|
return {
|
||||||
|
classification,
|
||||||
|
sort,
|
||||||
|
type,
|
||||||
|
title,
|
||||||
|
author,
|
||||||
|
helpLinkUri: helpLinkUri || type,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,3 +6,4 @@ export * from './common'
|
|||||||
export * from './tool'
|
export * from './tool'
|
||||||
export * from './workflow'
|
export * from './workflow'
|
||||||
export * from './variable'
|
export * from './variable'
|
||||||
|
export * from './gen-node-meta-data'
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user