Fix: Fixed the issue where the connection lines of placeholder nodes in the agent canvas could not be displayed #9869 (#10485)

### What problem does this PR solve?

Fix: Fixed the issue where the connection lines of placeholder nodes in
the agent canvas could not be displayed #9869

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
balibabu
2025-10-11 15:24:27 +08:00
committed by GitHub
parent fee757eb41
commit 313e92dd9b
5 changed files with 20 additions and 50 deletions

View File

@ -1619,12 +1619,12 @@ General实体和关系提取提示来自 GitHub - microsoft/graphrag基于
tokenizerRequired: '请先添加Tokenizer节点', tokenizerRequired: '请先添加Tokenizer节点',
tokenizerDescription: tokenizerDescription:
'根据所选的搜索方法,将文本转换为所需的数据结构(例如,用于嵌入搜索的向量嵌入)。', '根据所选的搜索方法,将文本转换为所需的数据结构(例如,用于嵌入搜索的向量嵌入)。',
splitter: '分词器拆分器', splitter: '按字符分割',
splitterDescription: splitterDescription:
'根据分词器长度将文本拆分成块,并带有可选的分隔符和重叠。', '根据分词器长度将文本拆分成块,并带有可选的分隔符和重叠。',
hierarchicalMergerDescription: hierarchicalMergerDescription:
'使用正则表达式规则按标题层次结构将文档拆分成多个部分,以实现更精细的控制。', '使用正则表达式规则按标题层次结构将文档拆分成多个部分,以实现更精细的控制。',
hierarchicalMerger: '标题拆分器', hierarchicalMerger: '标题分割',
extractor: '提取器', extractor: '提取器',
extractorDescription: extractorDescription:
'使用 LLM 从文档块(例如摘要、分类等)中提取结构化见解。', '使用 LLM 从文档块(例如摘要、分类等)中提取结构化见解。',

View File

@ -29,9 +29,8 @@ function InnerButtonEdge({
data, data,
sourceHandleId, sourceHandleId,
}: EdgeProps<Edge<{ isHovered: boolean }>>) { }: EdgeProps<Edge<{ isHovered: boolean }>>) {
const deleteEdgeById = useGraphStore((state) => state.deleteEdgeById); const { deleteEdgeById, getOperatorTypeFromId } = useGraphStore(
const highlightedPlaceholderEdgeId = useGraphStore( (state) => state,
(state) => state.highlightedPlaceholderEdgeId,
); );
const [edgePath, labelX, labelY] = getBezierPath({ const [edgePath, labelX, labelY] = getBezierPath({
@ -48,12 +47,16 @@ function InnerButtonEdge({
: {}; : {};
}, [selected]); }, [selected]);
const isTargetPlaceholder = useMemo(() => {
return getOperatorTypeFromId(target) === Operator.Placeholder;
}, [getOperatorTypeFromId, target]);
const placeholderHighlightStyle = useMemo(() => { const placeholderHighlightStyle = useMemo(() => {
const isHighlighted = highlightedPlaceholderEdgeId === id; const isHighlighted = isTargetPlaceholder;
return isHighlighted return isHighlighted
? { strokeWidth: 2, stroke: 'var(--accent-primary)' } ? { strokeWidth: 2, stroke: 'rgb(var(--accent-primary))' }
: {}; : {};
}, [highlightedPlaceholderEdgeId, id]); }, [isTargetPlaceholder]);
const onEdgeClick = () => { const onEdgeClick = () => {
deleteEdgeById(id); deleteEdgeById(id);
@ -83,9 +86,10 @@ function InnerButtonEdge({
data?.isHovered && data?.isHovered &&
sourceHandleId !== NodeHandleId.Tool && sourceHandleId !== NodeHandleId.Tool &&
sourceHandleId !== NodeHandleId.AgentBottom && // The connection between the agent node and the tool node does not need to display the delete button sourceHandleId !== NodeHandleId.AgentBottom && // The connection between the agent node and the tool node does not need to display the delete button
!target.startsWith(Operator.Tool) !target.startsWith(Operator.Tool) &&
!isTargetPlaceholder
); );
}, [data?.isHovered, sourceHandleId, target]); }, [data?.isHovered, isTargetPlaceholder, sourceHandleId, target]);
return ( return (
<> <>

View File

@ -1,8 +1,7 @@
import { Connection, Position } from '@xyflow/react'; import { Connection, OnConnectEnd, Position } from '@xyflow/react';
import { useCallback, useRef } from 'react'; import { useCallback, useRef } from 'react';
import { useDropdownManager } from '../canvas/context'; import { useDropdownManager } from '../canvas/context';
import { Operator, PREVENT_CLOSE_DELAY } from '../constant'; import { Operator, PREVENT_CLOSE_DELAY } from '../constant';
import useGraphStore from '../store';
import { useAddNode } from './use-add-node'; import { useAddNode } from './use-add-node';
interface ConnectionStartParams { interface ConnectionStartParams {
@ -40,7 +39,6 @@ export const useConnectionDrag = (
const { addCanvasNode } = useAddNode(reactFlowInstance); const { addCanvasNode } = useAddNode(reactFlowInstance);
const { setActiveDropdown } = useDropdownManager(); const { setActiveDropdown } = useDropdownManager();
const { setHighlightedPlaceholderEdgeId } = useGraphStore();
/** /**
* Connection start handler function * Connection start handler function
@ -66,8 +64,8 @@ export const useConnectionDrag = (
/** /**
* Connection end handler function * Connection end handler function
*/ */
const onConnectEnd = useCallback( const onConnectEnd: OnConnectEnd = useCallback(
(event: MouseEvent | TouchEvent) => { (event) => {
if ('clientX' in event && 'clientY' in event) { if ('clientX' in event && 'clientY' in event) {
const { clientX, clientY } = event; const { clientX, clientY } = event;
setDropdownPosition({ x: clientX, y: clientY }); setDropdownPosition({ x: clientX, y: clientY });
@ -113,11 +111,6 @@ export const useConnectionDrag = (
if (newNodeId) { if (newNodeId) {
setCreatedPlaceholderRef(newNodeId); setCreatedPlaceholderRef(newNodeId);
if (connectionStartRef.current) {
const edgeId = `xy-edge__${connectionStartRef.current.nodeId}${connectionStartRef.current.handleId}-${newNodeId}end`;
setHighlightedPlaceholderEdgeId(edgeId);
}
} }
// Calculate placeholder node position and display dropdown menu // Calculate placeholder node position and display dropdown menu
@ -154,7 +147,6 @@ export const useConnectionDrag = (
calculateDropdownPosition, calculateDropdownPosition,
setActiveDropdown, setActiveDropdown,
showModal, showModal,
setHighlightedPlaceholderEdgeId,
checkAndRemoveExistingPlaceholder, checkAndRemoveExistingPlaceholder,
removePlaceholderNode, removePlaceholderNode,
hideModal, hideModal,
@ -206,13 +198,7 @@ export const useConnectionDrag = (
removePlaceholderNode(); removePlaceholderNode();
hideModal(); hideModal();
clearActiveDropdown(); clearActiveDropdown();
setHighlightedPlaceholderEdgeId(null); }, [removePlaceholderNode, hideModal, clearActiveDropdown]);
}, [
removePlaceholderNode,
hideModal,
clearActiveDropdown,
setHighlightedPlaceholderEdgeId,
]);
return { return {
onConnectStart, onConnectStart,

View File

@ -42,9 +42,6 @@ export const usePlaceholderManager = (reactFlowInstance: any) => {
}); });
} }
// Clear highlighted placeholder edge
useGraphStore.getState().setHighlightedPlaceholderEdgeId(null);
// Update ref reference // Update ref reference
if (createdPlaceholderRef.current === existingPlaceholder.id) { if (createdPlaceholderRef.current === existingPlaceholder.id) {
createdPlaceholderRef.current = null; createdPlaceholderRef.current = null;
@ -62,8 +59,7 @@ export const usePlaceholderManager = (reactFlowInstance: any) => {
reactFlowInstance && reactFlowInstance &&
!userSelectedNodeRef.current !userSelectedNodeRef.current
) { ) {
const { nodes, edges, setHighlightedPlaceholderEdgeId } = const { nodes, edges } = useGraphStore.getState();
useGraphStore.getState();
// Remove edges related to placeholder // Remove edges related to placeholder
const edgesToRemove = edges.filter( const edgesToRemove = edges.filter(
@ -84,8 +80,6 @@ export const usePlaceholderManager = (reactFlowInstance: any) => {
}); });
} }
setHighlightedPlaceholderEdgeId(null);
createdPlaceholderRef.current = null; createdPlaceholderRef.current = null;
} }
@ -101,13 +95,7 @@ export const usePlaceholderManager = (reactFlowInstance: any) => {
(newNodeId: string) => { (newNodeId: string) => {
// First establish connection between new node and source, then delete placeholder // First establish connection between new node and source, then delete placeholder
if (createdPlaceholderRef.current && reactFlowInstance) { if (createdPlaceholderRef.current && reactFlowInstance) {
const { const { nodes, edges, addEdge, updateNode } = useGraphStore.getState();
nodes,
edges,
addEdge,
updateNode,
setHighlightedPlaceholderEdgeId,
} = useGraphStore.getState();
// Find placeholder node to get its position // Find placeholder node to get its position
const placeholderNode = nodes.find( const placeholderNode = nodes.find(
@ -157,8 +145,6 @@ export const usePlaceholderManager = (reactFlowInstance: any) => {
edges: edgesToRemove, edges: edgesToRemove,
}); });
} }
setHighlightedPlaceholderEdgeId(null);
} }
// Mark that user has selected a node // Mark that user has selected a node

View File

@ -39,7 +39,6 @@ export type RFState = {
selectedEdgeIds: string[]; selectedEdgeIds: string[];
clickedNodeId: string; // currently selected node clickedNodeId: string; // currently selected node
clickedToolId: string; // currently selected tool id clickedToolId: string; // currently selected tool id
highlightedPlaceholderEdgeId: string | null;
onNodesChange: OnNodesChange<RAGFlowNodeType>; onNodesChange: OnNodesChange<RAGFlowNodeType>;
onEdgesChange: OnEdgesChange; onEdgesChange: OnEdgesChange;
onEdgeMouseEnter?: EdgeMouseHandler<Edge>; onEdgeMouseEnter?: EdgeMouseHandler<Edge>;
@ -90,7 +89,6 @@ export type RFState = {
) => void; // Deleting a condition of a classification operator will delete the related edge ) => void; // Deleting a condition of a classification operator will delete the related edge
findAgentToolNodeById: (id: string | null) => string | undefined; findAgentToolNodeById: (id: string | null) => string | undefined;
selectNodeIds: (nodeIds: string[]) => void; selectNodeIds: (nodeIds: string[]) => void;
setHighlightedPlaceholderEdgeId: (edgeId: string | null) => void;
}; };
// this is our useStore hook that we can use in our components to get parts of the store and call actions // this is our useStore hook that we can use in our components to get parts of the store and call actions
@ -103,7 +101,6 @@ const useGraphStore = create<RFState>()(
selectedEdgeIds: [] as string[], selectedEdgeIds: [] as string[],
clickedNodeId: '', clickedNodeId: '',
clickedToolId: '', clickedToolId: '',
highlightedPlaceholderEdgeId: null,
onNodesChange: (changes) => { onNodesChange: (changes) => {
set({ set({
nodes: applyNodeChanges(changes, get().nodes), nodes: applyNodeChanges(changes, get().nodes),
@ -530,9 +527,6 @@ const useGraphStore = create<RFState>()(
})), })),
); );
}, },
setHighlightedPlaceholderEdgeId: (edgeId) => {
set({ highlightedPlaceholderEdgeId: edgeId });
},
})), })),
{ name: 'graph', trace: true }, { name: 'graph', trace: true },
), ),