diff --git a/web/src/pages/agent/canvas/node/agent-node.tsx b/web/src/pages/agent/canvas/node/agent-node.tsx index 212ba6671..862fa239b 100644 --- a/web/src/pages/agent/canvas/node/agent-node.tsx +++ b/web/src/pages/agent/canvas/node/agent-node.tsx @@ -1,7 +1,7 @@ import { IAgentNode } from '@/interfaces/database/flow'; import { Handle, NodeProps, Position } from '@xyflow/react'; import { memo, useMemo } from 'react'; -import { Operator } from '../../constant'; +import { NodeHandleId, Operator } from '../../constant'; import useGraphStore from '../../store'; import { CommonHandle } from './handle'; import { LeftHandleStyle, RightHandleStyle } from './handle-icon'; @@ -31,21 +31,22 @@ function InnerAgentNode({ {isNotParentAgent && ( <> )} diff --git a/web/src/pages/agent/canvas/node/begin-node.tsx b/web/src/pages/agent/canvas/node/begin-node.tsx index d4f92e116..10df9eeef 100644 --- a/web/src/pages/agent/canvas/node/begin-node.tsx +++ b/web/src/pages/agent/canvas/node/begin-node.tsx @@ -7,6 +7,7 @@ import { useTranslation } from 'react-i18next'; import { BeginQueryType, BeginQueryTypeIconMap, + NodeHandleId, Operator, } from '../../constant'; import { BeginQuery } from '../../interface'; @@ -27,9 +28,9 @@ function InnerBeginNode({ data, id }: NodeProps) { type="source" position={Position.Right} isConnectable - className={styles.handle} style={RightHandleStyle} nodeId={id} + id={NodeHandleId.Start} >
diff --git a/web/src/pages/agent/canvas/node/categorize-node.tsx b/web/src/pages/agent/canvas/node/categorize-node.tsx index 7460d1d99..864cb1513 100644 --- a/web/src/pages/agent/canvas/node/categorize-node.tsx +++ b/web/src/pages/agent/canvas/node/categorize-node.tsx @@ -3,6 +3,7 @@ import { ICategorizeNode } from '@/interfaces/database/flow'; import { NodeProps, Position } from '@xyflow/react'; import { get } from 'lodash'; import { memo } from 'react'; +import { NodeHandleId } from '../../constant'; import { CommonHandle } from './handle'; import { RightHandleStyle } from './handle-icon'; import NodeHeader from './node-header'; @@ -23,7 +24,7 @@ export function InnerCategorizeNode({ type="target" position={Position.Left} isConnectable - id={'a'} + id={NodeHandleId.End} nodeId={id} > @@ -47,6 +48,7 @@ export function InnerCategorizeNode({ isConnectable style={{ ...RightHandleStyle, top: position.top }} nodeId={id} + isConnectableEnd={false} > ); diff --git a/web/src/pages/agent/canvas/node/dropdown/next-step-dropdown.tsx b/web/src/pages/agent/canvas/node/dropdown/next-step-dropdown.tsx index 434a5bb3b..e741286f2 100644 --- a/web/src/pages/agent/canvas/node/dropdown/next-step-dropdown.tsx +++ b/web/src/pages/agent/canvas/node/dropdown/next-step-dropdown.tsx @@ -30,8 +30,8 @@ function OperatorItemList({ operators }: OperatorItemProps) { key={x} className="hover:bg-background-card py-1 px-3 cursor-pointer rounded-sm flex gap-2 items-center justify-start" onClick={addCanvasNode(x, { - id: nodeId, - sourceHandle: id, + nodeId, + id, position, })} > diff --git a/web/src/pages/agent/canvas/node/index.tsx b/web/src/pages/agent/canvas/node/index.tsx index 4afad2d2d..b68edf931 100644 --- a/web/src/pages/agent/canvas/node/index.tsx +++ b/web/src/pages/agent/canvas/node/index.tsx @@ -1,6 +1,7 @@ import { IRagNode } from '@/interfaces/database/flow'; import { NodeProps, Position } from '@xyflow/react'; import { memo } from 'react'; +import { NodeHandleId } from '../../constant'; import { CommonHandle } from './handle'; import { LeftHandleStyle, RightHandleStyle } from './handle-icon'; import NodeHeader from './node-header'; @@ -17,8 +18,8 @@ function InnerRagNode({ diff --git a/web/src/pages/agent/canvas/node/message-node.tsx b/web/src/pages/agent/canvas/node/message-node.tsx index 7dd4f77e1..8d4c3199d 100644 --- a/web/src/pages/agent/canvas/node/message-node.tsx +++ b/web/src/pages/agent/canvas/node/message-node.tsx @@ -4,6 +4,7 @@ import { Flex } from 'antd'; import classNames from 'classnames'; import { get } from 'lodash'; import { memo } from 'react'; +import { NodeHandleId } from '../../constant'; import { CommonHandle } from './handle'; import { LeftHandleStyle, RightHandleStyle } from './handle-icon'; import styles from './index.less'; @@ -22,20 +23,21 @@ function InnerMessageNode({ ) { type="target" position={Position.Left} isConnectable - id={'a'} nodeId={id} + id={NodeHandleId.End} >
@@ -96,6 +96,7 @@ function InnerSwitchNode({ id, data, selected }: NodeProps) { isConnectable style={{ ...RightHandleStyle, top: position.top }} nodeId={id} + isConnectableEnd={false} > ); diff --git a/web/src/pages/agent/constant.tsx b/web/src/pages/agent/constant.tsx index d093f1a27..95eb14abe 100644 --- a/web/src/pages/agent/constant.tsx +++ b/web/src/pages/agent/constant.tsx @@ -3008,3 +3008,8 @@ export const NoDebugOperatorsList = [ Operator.Switch, Operator.Iteration, ]; + +export enum NodeHandleId { + Start = 'start', + End = 'end', +} diff --git a/web/src/pages/agent/form/agent-form/index.tsx b/web/src/pages/agent/form/agent-form/index.tsx index bf2a1a6d3..d7998c618 100644 --- a/web/src/pages/agent/form/agent-form/index.tsx +++ b/web/src/pages/agent/form/agent-form/index.tsx @@ -112,7 +112,7 @@ const AgentForm = ({ node }: INextOperatorForm) => { diff --git a/web/src/pages/agent/hooks/use-add-node.ts b/web/src/pages/agent/hooks/use-add-node.ts index 445850a30..eb8e0e98e 100644 --- a/web/src/pages/agent/hooks/use-add-node.ts +++ b/web/src/pages/agent/hooks/use-add-node.ts @@ -1,10 +1,11 @@ import { useFetchModelId } from '@/hooks/logic-hooks'; -import { Node, Position, ReactFlowInstance } from '@xyflow/react'; +import { Connection, Node, Position, ReactFlowInstance } from '@xyflow/react'; import humanId from 'human-id'; import { lowerFirst } from 'lodash'; import { useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { + NodeHandleId, NodeMap, Operator, initialAgentValues, @@ -145,8 +146,8 @@ export function useCalculateNewlyChildPosition() { const maxY = Math.max(...yAxises); const position = { - y: yAxises.length > 0 ? maxY + 262 : (parentNode?.position.y || 0) + 82, - x: (parentNode?.position.x || 0) + 140, + y: yAxises.length > 0 ? maxY + 150 : parentNode?.position.y || 0, + x: (parentNode?.position.x || 0) + 300, }; return position; @@ -157,6 +158,31 @@ export function useCalculateNewlyChildPosition() { return { calculateNewlyBackChildPosition }; } +function useAddChildEdge() { + const addEdge = useGraphStore((state) => state.addEdge); + + const addChildEdge = useCallback( + (position: Position = Position.Right, edge: Partial) => { + if ( + position === Position.Right && + edge.source && + edge.target && + edge.sourceHandle + ) { + addEdge({ + source: edge.source, + target: edge.target, + sourceHandle: edge.sourceHandle, + targetHandle: NodeHandleId.End, + }); + } + }, + [addEdge], + ); + + return { addChildEdge }; +} + export function useAddNode(reactFlowInstance?: ReactFlowInstance) { const addNode = useGraphStore((state) => state.addNode); const getNode = useGraphStore((state) => state.getNode); @@ -166,18 +192,19 @@ export function useAddNode(reactFlowInstance?: ReactFlowInstance) { const getNodeName = useGetNodeName(); const initializeOperatorParams = useInitializeOperatorParams(); const { calculateNewlyBackChildPosition } = useCalculateNewlyChildPosition(); + const { addChildEdge } = useAddChildEdge(); // const [reactFlowInstance, setReactFlowInstance] = // useState>(); const addCanvasNode = useCallback( ( type: string, - params: { id?: string; position?: Position; sourceHandle?: string } = { + params: { nodeId?: string; position: Position; id?: string } = { position: Position.Right, }, ) => (event: React.MouseEvent) => { - const id = params.id; + const nodeId = params.nodeId; // reactFlowInstance.project was renamed to reactFlowInstance.screenToFlowPosition // and you don't need to subtract the reactFlowBounds.left/top anymore @@ -188,7 +215,7 @@ export function useAddNode(reactFlowInstance?: ReactFlowInstance) { }); if (params.position === Position.Right) { - position = calculateNewlyBackChildPosition(id, params.sourceHandle); + position = calculateNewlyBackChildPosition(nodeId, params.id); } const newNode: Node = { @@ -229,12 +256,15 @@ export function useAddNode(reactFlowInstance?: ReactFlowInstance) { }; addNode(newNode); addNode(iterationStartNode); - } else if (type === Operator.Agent) { - const agentNode = getNode(id); + } else if ( + type === Operator.Agent && + params.position === Position.Bottom + ) { + const agentNode = getNode(nodeId); if (agentNode) { // Calculate the coordinates of child nodes to prevent newly added child nodes from covering other child nodes const allChildAgentNodeIds = edges - .filter((x) => x.source === id && x.sourceHandle === 'e') + .filter((x) => x.source === nodeId && x.sourceHandle === 'e') .map((x) => x.target); const xAxises = nodes @@ -249,9 +279,9 @@ export function useAddNode(reactFlowInstance?: ReactFlowInstance) { }; } addNode(newNode); - if (id) { + if (nodeId) { addEdge({ - source: id, + source: nodeId, target: newNode.id, sourceHandle: 'e', targetHandle: 'f', @@ -268,11 +298,18 @@ export function useAddNode(reactFlowInstance?: ReactFlowInstance) { newNode.extent = 'parent'; } addNode(newNode); + addChildEdge(params.position, { + source: params.nodeId, + target: newNode.id, + sourceHandle: params.id, + }); } }, [ + addChildEdge, addEdge, addNode, + calculateNewlyBackChildPosition, edges, getNode, getNodeName,