mirror of
https://github.com/langgenius/dify.git
synced 2026-05-04 09:28:04 +08:00
Merge branch 'main' into feat/grouping-branching
# Conflicts: # web/app/components/workflow/block-icon.tsx # web/app/components/workflow/hooks/use-nodes-interactions.ts # web/app/components/workflow/index.tsx # web/app/components/workflow/nodes/components.ts # web/app/components/workflow/selection-contextmenu.tsx # web/app/components/workflow/utils/workflow-init.ts
This commit is contained in:
@ -1,8 +1,8 @@
|
||||
import type { DataSourceNodeType } from '../nodes/data-source/types'
|
||||
import type {
|
||||
InputVar,
|
||||
ToolWithProvider,
|
||||
} from '../types'
|
||||
import type { DataSourceNodeType } from '../nodes/data-source/types'
|
||||
import { CollectionType } from '@/app/components/tools/types'
|
||||
import { toolParametersToFormSchemas } from '@/app/components/tools/utils/to-form-schema'
|
||||
|
||||
|
||||
@ -1,13 +1,11 @@
|
||||
import ELK from 'elkjs/lib/elk.bundled.js'
|
||||
import type { ElkNode, LayoutOptions } from 'elkjs/lib/elk-api'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import type { CaseItem, IfElseNodeType } from '@/app/components/workflow/nodes/if-else/types'
|
||||
import type {
|
||||
Edge,
|
||||
Node,
|
||||
} from '@/app/components/workflow/types'
|
||||
import {
|
||||
BlockEnum,
|
||||
} from '@/app/components/workflow/types'
|
||||
import ELK from 'elkjs/lib/elk.bundled.js'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import {
|
||||
CUSTOM_NODE,
|
||||
NODE_LAYOUT_HORIZONTAL_PADDING,
|
||||
@ -15,7 +13,9 @@ import {
|
||||
} from '@/app/components/workflow/constants'
|
||||
import { CUSTOM_ITERATION_START_NODE } from '@/app/components/workflow/nodes/iteration-start/constants'
|
||||
import { CUSTOM_LOOP_START_NODE } from '@/app/components/workflow/nodes/loop-start/constants'
|
||||
import type { CaseItem, IfElseNodeType } from '@/app/components/workflow/nodes/if-else/types'
|
||||
import {
|
||||
BlockEnum,
|
||||
} from '@/app/components/workflow/types'
|
||||
|
||||
// Although the file name refers to Dagre, the implementation now relies on ELK's layered algorithm.
|
||||
// Keep the export signatures unchanged to minimise the blast radius while we migrate the layout stack.
|
||||
@ -284,7 +284,7 @@ const collectLayout = (graph: ElkNode, predicate: (id: string) => boolean): Layo
|
||||
const buildIfElseWithPorts = (
|
||||
ifElseNode: Node,
|
||||
edges: Edge[],
|
||||
): { node: ElkNodeShape; portMap: Map<string, string> } | null => {
|
||||
): { node: ElkNodeShape, portMap: Map<string, string> } | null => {
|
||||
const childEdges = edges.filter(edge => edge.source === ifElseNode.id)
|
||||
|
||||
if (childEdges.length <= 1)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { BlockClassificationEnum } from '@/app/components/workflow/block-selector/types'
|
||||
import type { BlockEnum } from '@/app/components/workflow/types'
|
||||
import { BlockClassificationEnum } from '@/app/components/workflow/block-selector/types'
|
||||
|
||||
export type GenNodeMetaDataParams = {
|
||||
classification?: BlockClassificationEnum
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
export * from './node'
|
||||
export * from './edge'
|
||||
export * from './workflow-init'
|
||||
export * from './elk-layout'
|
||||
export * from './common'
|
||||
export * from './tool'
|
||||
export * from './workflow'
|
||||
export * from './variable'
|
||||
export * from './gen-node-meta-data'
|
||||
export * from './data-source'
|
||||
export * from './edge'
|
||||
export * from './elk-layout'
|
||||
export * from './gen-node-meta-data'
|
||||
export * from './node'
|
||||
export * from './tool'
|
||||
export * from './variable'
|
||||
export * from './workflow'
|
||||
export * from './workflow-init'
|
||||
|
||||
@ -7,8 +7,8 @@
|
||||
* Interface for node selection event detail
|
||||
*/
|
||||
export type NodeSelectionDetail = {
|
||||
nodeId: string;
|
||||
focus?: boolean;
|
||||
nodeId: string
|
||||
focus?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import {
|
||||
Position,
|
||||
} from 'reactflow'
|
||||
import type { IterationNodeType } from '../nodes/iteration/types'
|
||||
import type { LoopNodeType } from '../nodes/loop/types'
|
||||
import type {
|
||||
Node,
|
||||
} from '../types'
|
||||
import {
|
||||
BlockEnum,
|
||||
} from '../types'
|
||||
Position,
|
||||
} from 'reactflow'
|
||||
import { CUSTOM_SIMPLE_NODE } from '@/app/components/workflow/simple-node/constants'
|
||||
import {
|
||||
CUSTOM_NODE,
|
||||
ITERATION_CHILDREN_Z_INDEX,
|
||||
@ -16,9 +16,9 @@ import {
|
||||
} from '../constants'
|
||||
import { CUSTOM_ITERATION_START_NODE } from '../nodes/iteration-start/constants'
|
||||
import { CUSTOM_LOOP_START_NODE } from '../nodes/loop-start/constants'
|
||||
import type { IterationNodeType } from '../nodes/iteration/types'
|
||||
import type { LoopNodeType } from '../nodes/loop/types'
|
||||
import { CUSTOM_SIMPLE_NODE } from '@/app/components/workflow/simple-node/constants'
|
||||
import {
|
||||
BlockEnum,
|
||||
} from '../types'
|
||||
|
||||
export function generateNewNode({ data, position, id, zIndex, type, ...rest }: Omit<Node, 'id'> & { id?: string }): {
|
||||
newNode: Node
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import type { ToolNodeType } from '../nodes/tool/types'
|
||||
import type {
|
||||
InputVar,
|
||||
ToolWithProvider,
|
||||
} from '../types'
|
||||
import type { ToolNodeType } from '../nodes/tool/types'
|
||||
import type { StructuredOutput } from '@/app/components/workflow/nodes/llm/types'
|
||||
import { CollectionType } from '@/app/components/tools/types'
|
||||
import { toolParametersToFormSchemas } from '@/app/components/tools/utils/to-form-schema'
|
||||
import { canFindTool } from '@/utils'
|
||||
import type { StructuredOutput } from '@/app/components/workflow/nodes/llm/types'
|
||||
import { Type } from '@/app/components/workflow/nodes/llm/types'
|
||||
import { canFindTool } from '@/utils'
|
||||
|
||||
export const getToolCheckParams = (
|
||||
toolData: ToolNodeType,
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
import type {
|
||||
ValueSelector,
|
||||
} from '../types'
|
||||
import type {
|
||||
BlockEnum,
|
||||
ValueSelector,
|
||||
} from '../types'
|
||||
import { hasErrorHandleNode } from '.'
|
||||
|
||||
export const variableTransformer = (v: ValueSelector | string) => {
|
||||
if (typeof v === 'string')
|
||||
return v.replace(/^{{#|#}}$/g, '').split('.')
|
||||
return v.replace(/^\{\{#|#\}\}$/g, '').split('.')
|
||||
|
||||
return `{{#${v.join('.')}#}}`
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { BlockEnum, type Node, isTriggerNode } from '../types'
|
||||
import type { Node } from '../types'
|
||||
import { BlockEnum, isTriggerNode } from '../types'
|
||||
|
||||
/**
|
||||
* Get the workflow entry node
|
||||
@ -6,7 +7,8 @@ import { BlockEnum, type Node, isTriggerNode } from '../types'
|
||||
*/
|
||||
export function getWorkflowEntryNode(nodes: Node[]): Node | undefined {
|
||||
const triggerNode = nodes.find(node => isTriggerNode(node.data.type))
|
||||
if (triggerNode) return triggerNode
|
||||
if (triggerNode)
|
||||
return triggerNode
|
||||
|
||||
return nodes.find(node => node.data.type === BlockEnum.Start)
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { preprocessNodesAndEdges } from './workflow-init'
|
||||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
import type {
|
||||
Node,
|
||||
} from '@/app/components/workflow/types'
|
||||
import { CUSTOM_ITERATION_START_NODE } from '@/app/components/workflow/nodes/iteration-start/constants'
|
||||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
import { preprocessNodesAndEdges } from './workflow-init'
|
||||
|
||||
describe('preprocessNodesAndEdges', () => {
|
||||
it('process nodes without iteration node or loop node should return origin nodes and edges.', () => {
|
||||
|
||||
@ -1,17 +1,21 @@
|
||||
import {
|
||||
getConnectedEdges,
|
||||
} from 'reactflow'
|
||||
import {
|
||||
cloneDeep,
|
||||
} from 'lodash-es'
|
||||
import type { CustomGroupNodeData } from '../custom-group-node'
|
||||
import type { IfElseNodeType } from '../nodes/if-else/types'
|
||||
import type { IterationNodeType } from '../nodes/iteration/types'
|
||||
import type { LoopNodeType } from '../nodes/loop/types'
|
||||
import type { QuestionClassifierNodeType } from '../nodes/question-classifier/types'
|
||||
import type { ToolNodeType } from '../nodes/tool/types'
|
||||
import type {
|
||||
Edge,
|
||||
Node,
|
||||
} from '../types'
|
||||
import {
|
||||
BlockEnum,
|
||||
ErrorHandleMode,
|
||||
} from '../types'
|
||||
cloneDeep,
|
||||
} from 'lodash-es'
|
||||
import {
|
||||
getConnectedEdges,
|
||||
} from 'reactflow'
|
||||
import { getIterationStartNode, getLoopStartNode } from '@/app/components/workflow/utils/node'
|
||||
import { correctModelProvider } from '@/utils'
|
||||
import {
|
||||
CUSTOM_NODE,
|
||||
DEFAULT_RETRY_INTERVAL,
|
||||
@ -21,24 +25,17 @@ import {
|
||||
NODE_WIDTH_X_OFFSET,
|
||||
START_INITIAL_POSITION,
|
||||
} from '../constants'
|
||||
import { CUSTOM_ITERATION_START_NODE } from '../nodes/iteration-start/constants'
|
||||
import { CUSTOM_LOOP_START_NODE } from '../nodes/loop-start/constants'
|
||||
import type { QuestionClassifierNodeType } from '../nodes/question-classifier/types'
|
||||
import type { IfElseNodeType } from '../nodes/if-else/types'
|
||||
import { branchNameCorrect } from '../nodes/if-else/utils'
|
||||
import type { IterationNodeType } from '../nodes/iteration/types'
|
||||
import type { LoopNodeType } from '../nodes/loop/types'
|
||||
import type { ToolNodeType } from '../nodes/tool/types'
|
||||
import {
|
||||
getIterationStartNode,
|
||||
getLoopStartNode,
|
||||
} from '.'
|
||||
import { correctModelProvider } from '@/utils'
|
||||
import {
|
||||
CUSTOM_GROUP_NODE,
|
||||
GROUP_CHILDREN_Z_INDEX,
|
||||
} from '../custom-group-node'
|
||||
import type { CustomGroupNodeData } from '../custom-group-node'
|
||||
import { branchNameCorrect } from '../nodes/if-else/utils'
|
||||
import { CUSTOM_ITERATION_START_NODE } from '../nodes/iteration-start/constants'
|
||||
import { CUSTOM_LOOP_START_NODE } from '../nodes/loop-start/constants'
|
||||
import {
|
||||
BlockEnum,
|
||||
ErrorHandleMode,
|
||||
} from '../types'
|
||||
|
||||
const WHITE = 'WHITE'
|
||||
const GRAY = 'GRAY'
|
||||
@ -280,7 +277,7 @@ export const initialNodes = (originNodes: Node[], originEdges: Edge[]) => {
|
||||
acc[node.parentId] = [{ nodeId: node.id, nodeType: node.data.type }]
|
||||
}
|
||||
return acc
|
||||
}, {} as Record<string, { nodeId: string; nodeType: BlockEnum }[]>)
|
||||
}, {} as Record<string, { nodeId: string, nodeType: BlockEnum }[]>)
|
||||
|
||||
return nodes.map((node) => {
|
||||
if (!node.type)
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
import {
|
||||
getOutgoers,
|
||||
} from 'reactflow'
|
||||
import { v4 as uuid4 } from 'uuid'
|
||||
import {
|
||||
uniqBy,
|
||||
} from 'lodash-es'
|
||||
import type {
|
||||
Edge,
|
||||
Node,
|
||||
} from '../types'
|
||||
import {
|
||||
uniqBy,
|
||||
} from 'lodash-es'
|
||||
import {
|
||||
getOutgoers,
|
||||
} from 'reactflow'
|
||||
import { v4 as uuid4 } from 'uuid'
|
||||
import {
|
||||
BlockEnum,
|
||||
} from '../types'
|
||||
|
||||
export const canRunBySingle = (nodeType: BlockEnum, isChildNode: boolean) => {
|
||||
// child node means in iteration or loop. Set value to iteration(or loop) may cause variable not exit problem in backend.
|
||||
if(isChildNode && nodeType === BlockEnum.Assigner)
|
||||
if (isChildNode && nodeType === BlockEnum.Assigner)
|
||||
return false
|
||||
return nodeType === BlockEnum.LLM
|
||||
|| nodeType === BlockEnum.KnowledgeRetrieval
|
||||
|
||||
Reference in New Issue
Block a user