FEAT: NEW WORKFLOW ENGINE (#3160)

Co-authored-by: Joel <iamjoel007@gmail.com>
Co-authored-by: Yeuoly <admin@srmxy.cn>
Co-authored-by: JzoNg <jzongcode@gmail.com>
Co-authored-by: StyleZhang <jasonapring2015@outlook.com>
Co-authored-by: jyong <jyong@dify.ai>
Co-authored-by: nite-knite <nkCoding@gmail.com>
Co-authored-by: jyong <718720800@qq.com>
This commit is contained in:
takatost
2024-04-08 18:51:46 +08:00
committed by GitHub
parent 2fb9850af5
commit 7753ba2d37
1161 changed files with 103836 additions and 10327 deletions

View File

@@ -0,0 +1,36 @@
import { BlockEnum } from '../../types'
import type { NodeDefault } from '../../types'
import type { AnswerNodeType } from './types'
import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/constants'
const nodeDefault: NodeDefault<AnswerNodeType> = {
defaultValue: {
variables: [],
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) {
let errorMessages = ''
const { answer } = payload
if (!answer)
errorMessages = t('workflow.errorMsg.fieldRequired', { field: t('workflow.nodes.answer.answer') })
return {
isValid: !errorMessages,
errorMessage: errorMessages,
}
},
}
export default nodeDefault

View File

@@ -0,0 +1,26 @@
import type { FC } from 'react'
import React from 'react'
import { useTranslation } from 'react-i18next'
import InfoPanel from '../_base/components/info-panel'
import ReadonlyInputWithSelectVar from '../_base/components/readonly-input-with-select-var'
import type { AnswerNodeType } from './types'
import type { NodeProps } from '@/app/components/workflow/types'
const Node: FC<NodeProps<AnswerNodeType>> = ({
id,
data,
}) => {
const { t } = useTranslation()
return (
<div className='mb-1 px-3 py-1'>
<InfoPanel title={t('workflow.nodes.answer.answer')} content={
<ReadonlyInputWithSelectVar
value={data.answer}
nodeId={id}
/>
} />
</div>
)
}
export default React.memo(Node)

View File

@@ -0,0 +1,44 @@
import type { FC } from 'react'
import React from 'react'
import { useTranslation } from 'react-i18next'
import useConfig from './use-config'
import type { AnswerNodeType } from './types'
import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor'
import type { NodePanelProps } from '@/app/components/workflow/types'
import useAvailableVarList from '@/app/components/workflow/nodes/_base/hooks/use-available-var-list'
const i18nPrefix = 'workflow.nodes.answer'
const Panel: FC<NodePanelProps<AnswerNodeType>> = ({
id,
data,
}) => {
const { t } = useTranslation()
const {
readOnly,
inputs,
handleAnswerChange,
filterVar,
} = useConfig(id, data)
const { availableVars, availableNodes } = useAvailableVarList(id, {
onlyLeafNodeVar: false,
filterVar,
})
return (
<div className='mt-2 mb-2 px-4 space-y-4'>
<Editor
readOnly={readOnly}
justVar
title={t(`${i18nPrefix}.answer`)!}
value={inputs.answer}
onChange={handleAnswerChange}
nodesOutputVars={availableVars}
availableNodes={availableNodes}
/>
</div>
)
}
export default React.memo(Panel)

View File

@@ -0,0 +1,6 @@
import type { CommonNodeType, Variable } from '@/app/components/workflow/types'
export type AnswerNodeType = CommonNodeType & {
variables: Variable[]
answer: string
}

View File

@@ -0,0 +1,41 @@
import { useCallback } from 'react'
import produce from 'immer'
import useVarList from '../_base/hooks/use-var-list'
import type { Var } from '../../types'
import { VarType } from '../../types'
import type { AnswerNodeType } from './types'
import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
import {
useNodesReadOnly,
} from '@/app/components/workflow/hooks'
const useConfig = (id: string, payload: AnswerNodeType) => {
const { nodesReadOnly: readOnly } = useNodesReadOnly()
const { inputs, setInputs } = useNodeCrud<AnswerNodeType>(id, payload)
// variables
const { handleVarListChange, handleAddVariable } = useVarList<AnswerNodeType>({
inputs,
setInputs,
})
const handleAnswerChange = useCallback((value: string) => {
const newInputs = produce(inputs, (draft) => {
draft.answer = value
})
setInputs(newInputs)
}, [inputs, setInputs])
const filterVar = useCallback((varPayload: Var) => {
return varPayload.type !== VarType.arrayObject
}, [])
return {
readOnly,
inputs,
handleVarListChange,
handleAddVariable,
handleAnswerChange,
filterVar,
}
}
export default useConfig

View File

@@ -0,0 +1,5 @@
import type { AnswerNodeType } from './types'
export const checkNodeValid = (payload: AnswerNodeType) => {
return true
}