diff --git a/web/src/components/xyflow/base-node.tsx b/web/src/components/xyflow/base-node.tsx
index 5ecc1b4d9..222afdaa1 100644
--- a/web/src/components/xyflow/base-node.tsx
+++ b/web/src/components/xyflow/base-node.tsx
@@ -9,7 +9,7 @@ export const BaseNode = forwardRef<
) {
- const { theme } = useTheme();
const getNode = useGraphStore((state) => state.getNode);
const edges = useGraphStore((state) => state.edges);
@@ -26,34 +26,25 @@ function InnerAgentNode({
}, [edges, getNode, id]);
return (
-
-
+
+
{isNotParentAgent && (
<>
-
-
+
+ >
>
)}
-
+
);
}
diff --git a/web/src/pages/agent/canvas/node/begin-node.tsx b/web/src/pages/agent/canvas/node/begin-node.tsx
index 87fed0ee8..c13db7c6f 100644
--- a/web/src/pages/agent/canvas/node/begin-node.tsx
+++ b/web/src/pages/agent/canvas/node/begin-node.tsx
@@ -1,8 +1,6 @@
-import { useTheme } from '@/components/theme-provider';
import { IBeginNode } from '@/interfaces/database/flow';
-import { Handle, NodeProps, Position } from '@xyflow/react';
+import { NodeProps, Position } from '@xyflow/react';
import { Flex } from 'antd';
-import classNames from 'classnames';
import get from 'lodash/get';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
@@ -10,42 +8,31 @@ import {
BeginQueryType,
BeginQueryTypeIconMap,
Operator,
- operatorMap,
} from '../../constant';
import { BeginQuery } from '../../interface';
import OperatorIcon from '../../operator-icon';
+import { CommonHandle } from './handle';
import { RightHandleStyle } from './handle-icon';
import styles from './index.less';
+import { NodeWrapper } from './node-wrapper';
// TODO: do not allow other nodes to connect to this node
-function InnerBeginNode({ selected, data }: NodeProps
) {
+function InnerBeginNode({ data }: NodeProps) {
const { t } = useTranslation();
const query: BeginQuery[] = get(data, 'form.query', []);
- const { theme } = useTheme();
+
return (
-
-
+
+ >
-
+
{t(`flow.begin`)}
@@ -68,7 +55,7 @@ function InnerBeginNode({ selected, data }: NodeProps) {
);
})}
-
+
);
}
diff --git a/web/src/pages/agent/canvas/node/handle.tsx b/web/src/pages/agent/canvas/node/handle.tsx
new file mode 100644
index 000000000..212208e60
--- /dev/null
+++ b/web/src/pages/agent/canvas/node/handle.tsx
@@ -0,0 +1,17 @@
+import { cn } from '@/lib/utils';
+import { Handle, HandleProps } from '@xyflow/react';
+import { Plus } from 'lucide-react';
+
+export function CommonHandle({ className, ...props }: HandleProps) {
+ return (
+
+
+
+ );
+}
diff --git a/web/src/pages/agent/canvas/node/index.tsx b/web/src/pages/agent/canvas/node/index.tsx
index 286c3e080..d67ec040c 100644
--- a/web/src/pages/agent/canvas/node/index.tsx
+++ b/web/src/pages/agent/canvas/node/index.tsx
@@ -6,6 +6,7 @@ import { memo } from 'react';
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
import styles from './index.less';
import NodeHeader from './node-header';
+import { ToolBar } from './toolbar';
function InnerRagNode({
id,
@@ -15,33 +16,35 @@ function InnerRagNode({
}: NodeProps) {
const { theme } = useTheme();
return (
-
+
+
+
);
}
diff --git a/web/src/pages/agent/canvas/node/message-node.tsx b/web/src/pages/agent/canvas/node/message-node.tsx
index 5ed80dcbc..5c76df9a2 100644
--- a/web/src/pages/agent/canvas/node/message-node.tsx
+++ b/web/src/pages/agent/canvas/node/message-node.tsx
@@ -1,13 +1,15 @@
-import { useTheme } from '@/components/theme-provider';
import { IMessageNode } from '@/interfaces/database/flow';
-import { Handle, NodeProps, Position } from '@xyflow/react';
+import { NodeProps, Position } from '@xyflow/react';
import { Flex } from 'antd';
import classNames from 'classnames';
import { get } from 'lodash';
import { memo } from 'react';
+import { CommonHandle } from './handle';
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
import styles from './index.less';
import NodeHeader from './node-header';
+import { NodeWrapper } from './node-wrapper';
+import { ToolBar } from './toolbar';
function InnerMessageNode({
id,
@@ -16,52 +18,43 @@ function InnerMessageNode({
selected,
}: NodeProps) {
const messages: string[] = get(data, 'form.messages', []);
- const { theme } = useTheme();
return (
-
-
-
- 0,
- })}
- >
+
+
+
+
+ 0,
+ })}
+ >
-
- {messages.map((message, idx) => {
- return (
-
- {message}
-
- );
- })}
-
-
+
+ {messages.map((message, idx) => {
+ return (
+
+ {message}
+
+ );
+ })}
+
+
+
);
}
diff --git a/web/src/pages/agent/canvas/node/node-header.tsx b/web/src/pages/agent/canvas/node/node-header.tsx
index 216657103..9647af1ed 100644
--- a/web/src/pages/agent/canvas/node/node-header.tsx
+++ b/web/src/pages/agent/canvas/node/node-header.tsx
@@ -1,20 +1,7 @@
-import { useTranslate } from '@/hooks/common-hooks';
-import { Flex } from 'antd';
-import { Copy, Play, Trash2 } from 'lucide-react';
-import { Operator, operatorMap } from '../../constant';
+import { cn } from '@/lib/utils';
+import { memo } from 'react';
+import { Operator } from '../../constant';
import OperatorIcon from '../../operator-icon';
-import { needsSingleStepDebugging } from '../../utils';
-import NodeDropdown from './dropdown';
-import { NextNodePopover } from './popover';
-
-import {
- TooltipContent,
- TooltipNode,
- TooltipTrigger,
-} from '@/components/xyflow/tooltip-node';
-import { Position } from '@xyflow/react';
-import { PropsWithChildren, memo } from 'react';
-import { RunTooltip } from '../../flow-tooltip';
interface IProps {
id: string;
label: string;
@@ -24,55 +11,20 @@ interface IProps {
wrapperClassName?: string;
}
-const ExcludedRunStateOperators = [Operator.Answer];
-
-export function RunStatus({ id, name, label }: IProps) {
- const { t } = useTranslate('flow');
- return (
-
- {needsSingleStepDebugging(label) && (
-
-
- // data-play is used to trigger single step debugging
- )}
-
-
- {t('operationResults')}
-
-
-
- );
-}
-
const InnerNodeHeader = ({
label,
- id,
name,
- gap = 4,
className,
wrapperClassName,
}: IProps) => {
return (
-
- {!ExcludedRunStateOperators.includes(label as Operator) && (
-
- )}
-
-
+
);
};
@@ -80,37 +32,3 @@ const InnerNodeHeader = ({
const NodeHeader = memo(InnerNodeHeader);
export default NodeHeader;
-
-function IconWrapper({ children }: PropsWithChildren) {
- return (
-
- {children}
-
- );
-}
-
-type ToolBarProps = {
- selected?: boolean | undefined;
-} & PropsWithChildren;
-
-export function ToolBar({ selected, children }: ToolBarProps) {
- return (
-
- {children}
-
-
-
-
-
- );
-}
diff --git a/web/src/pages/agent/canvas/node/node-wrapper.tsx b/web/src/pages/agent/canvas/node/node-wrapper.tsx
new file mode 100644
index 000000000..8754cf103
--- /dev/null
+++ b/web/src/pages/agent/canvas/node/node-wrapper.tsx
@@ -0,0 +1,18 @@
+import { cn } from '@/lib/utils';
+import { HTMLAttributes, PropsWithChildren } from 'react';
+
+export function NodeWrapper({
+ children,
+ className,
+}: PropsWithChildren & HTMLAttributes) {
+ return (
+
+ );
+}
diff --git a/web/src/pages/agent/canvas/node/retrieval-node.tsx b/web/src/pages/agent/canvas/node/retrieval-node.tsx
index 708aebd05..2b2171961 100644
--- a/web/src/pages/agent/canvas/node/retrieval-node.tsx
+++ b/web/src/pages/agent/canvas/node/retrieval-node.tsx
@@ -1,15 +1,17 @@
-import { useTheme } from '@/components/theme-provider';
import { useFetchKnowledgeList } from '@/hooks/knowledge-hooks';
import { IRetrievalNode } from '@/interfaces/database/flow';
import { UserOutlined } from '@ant-design/icons';
-import { Handle, NodeProps, Position } from '@xyflow/react';
+import { NodeProps, Position } from '@xyflow/react';
import { Avatar, Flex } from 'antd';
import classNames from 'classnames';
import { get } from 'lodash';
import { memo, useMemo } from 'react';
+import { CommonHandle } from './handle';
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
import styles from './index.less';
import NodeHeader from './node-header';
+import { NodeWrapper } from './node-wrapper';
+import { ToolBar } from './toolbar';
function InnerRetrievalNode({
id,
@@ -18,7 +20,6 @@ function InnerRetrievalNode({
selected,
}: NodeProps) {
const knowledgeBaseIds: string[] = get(data, 'form.kb_ids', []);
- const { theme } = useTheme();
const { list: knowledgeList } = useFetchKnowledgeList(true);
const knowledgeBases = useMemo(() => {
return knowledgeBaseIds.map((x) => {
@@ -32,58 +33,52 @@ function InnerRetrievalNode({
}, [knowledgeList, knowledgeBaseIds]);
return (
-
-
-
- 0,
- })}
- >
-
- {knowledgeBases.map((knowledge) => {
- return (
-
-
- }
- src={knowledge.avatar}
- />
-
- {knowledge.name}
+
+
+
+
+ 0,
+ })}
+ >
+
+ {knowledgeBases.map((knowledge) => {
+ return (
+
+
+ }
+ src={knowledge.avatar}
+ />
+
+ {knowledge.name}
+
-
-
- );
- })}
-
-
+
+ );
+ })}
+
+
+
);
}
diff --git a/web/src/pages/agent/canvas/node/switch-node.tsx b/web/src/pages/agent/canvas/node/switch-node.tsx
index a7c25dcfa..1fbd5919e 100644
--- a/web/src/pages/agent/canvas/node/switch-node.tsx
+++ b/web/src/pages/agent/canvas/node/switch-node.tsx
@@ -1,16 +1,16 @@
import { IconFont } from '@/components/icon-font';
-import { useTheme } from '@/components/theme-provider';
import { Card, CardContent } from '@/components/ui/card';
import { ISwitchCondition, ISwitchNode } from '@/interfaces/database/flow';
-import { Handle, NodeProps, Position } from '@xyflow/react';
-import classNames from 'classnames';
+import { NodeProps, Position } from '@xyflow/react';
import { memo, useCallback } from 'react';
import { SwitchOperatorOptions } from '../../constant';
import { useGetComponentLabelByValue } from '../../hooks/use-get-begin-query';
+import { CommonHandle } from './handle';
import { RightHandleStyle } from './handle-icon';
import { useBuildSwitchHandlePositions } from './hooks';
-import styles from './index.less';
-import NodeHeader, { ToolBar } from './node-header';
+import NodeHeader from './node-header';
+import { NodeWrapper } from './node-wrapper';
+import { ToolBar } from './toolbar';
const getConditionKey = (idx: number, length: number) => {
if (idx === 0 && length !== 1) {
@@ -58,32 +58,16 @@ const ConditionBlock = ({
function InnerSwitchNode({ id, data, selected }: NodeProps) {
const { positions } = useBuildSwitchHandlePositions({ data, id });
- const { theme } = useTheme();
return (
-
-
-
+
+
-
+ >
+
{positions.map((position, idx) => {
return (
@@ -103,20 +87,19 @@ function InnerSwitchNode({ id, data, selected }: NodeProps) {
>
)}
-
+ >
);
})}
-
+
);
}
diff --git a/web/src/pages/agent/canvas/node/toolbar.tsx b/web/src/pages/agent/canvas/node/toolbar.tsx
new file mode 100644
index 000000000..53a5f8a11
--- /dev/null
+++ b/web/src/pages/agent/canvas/node/toolbar.tsx
@@ -0,0 +1,74 @@
+import {
+ TooltipContent,
+ TooltipNode,
+ TooltipTrigger,
+} from '@/components/xyflow/tooltip-node';
+import { Position } from '@xyflow/react';
+import { Copy, Play, Trash2 } from 'lucide-react';
+import { MouseEventHandler, PropsWithChildren, useCallback } from 'react';
+import { Operator } from '../../constant';
+import { useDuplicateNode } from '../../hooks';
+import useGraphStore from '../../store';
+
+function IconWrapper({ children }: PropsWithChildren) {
+ return (
+