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,