store.ts
Overview
store.ts defines a centralized state management store for handling a graph-based flow editor using React and Zustand. It manages nodes and edges of a flow diagram, which are of type RAGFlowNodeType and Edge, respectively. The store provides reactive state and a comprehensive set of actions to manipulate the graph, including adding, updating, deleting nodes and edges, handling selections, duplications, and specific logic for different operator types such as switches, iterations, and agents.
This file acts as the core state hub for the flow editor, encapsulating all graph-related logic, and enabling components within the application to subscribe to and modify the graph state in a consistent and performant manner.
Detailed Explanation
Types and Imports
RAGFlowNodeType: Represents a node in the graph, imported from an external interface.
Edge: Represents connections between nodes.
Various types and functions imported from @xyflow/react support event handling and graph operations.
Utility functions and constants from local modules handle node duplication, naming, and edge equality.
Zustand is used with middleware devtools (for Redux DevTools integration) and
immer(for immutable updates).
RFState Interface
Defines the shape of the store's state and actions:
Property / Method | Type / Signature | Description |
|---|---|---|
|
| Array of nodes in the graph. |
|
| Array of edges connecting nodes. |
|
| IDs of currently selected nodes. |
|
| IDs of currently selected edges. |
|
| ID of the node currently clicked/active. |
|
| ID of the currently clicked tool. |
| Callback to update nodes on changes. | |
| Callback to update edges on changes. | |
| Handler for mouse enter events on edges. | |
| Handler for mouse leave events on edges. | |
| Handler when a new edge connection is created. | |
| Replaces current nodes with the given array. | |
| Replaces current edges with the given array. | |
| Updates downstream edges of a given node based on provided edges. | |
| [(nodeId: string, values: any, path?: (string | number)[]) => RAGFlowNodeType[]](/projects/311/73962) |
| Updates selected node and edge IDs based on user selection. | |
| Adds a new node to the graph. | |
| [(id?: string | null) => RAGFlowNodeType |
| Updates an existing node by replacing it in the nodes array. | |
| Adds a new edge connection between nodes. | |
| [(id: string) => Edge | undefined](/projects/311/71659) |
| Updates node form data when an edge is connected (e.g., special logic for switch nodes). | |
| [(source: string, sourceHandle?: string | null, target?: string |
| Duplicates a node with a new name, with special handling for iteration nodes. | |
| Duplicates an iteration node along with all its child nodes recursively. | |
| Deletes all currently selected edges. | |
| Deletes a specific edge and updates related node forms if necessary. | |
| Deletes a node by ID, with special handling if node is an Agent type. | |
| Deletes all downstream nodes and edges related to an Agent node. | |
| Deletes the tool node connected to an Agent node. | |
| Deletes an iteration node and all its child nodes. | |
| [(operatorName: Operator) => RAGFlowNodeType | undefined](/projects/311/73962) |
| Updates a single form field value on a node. | |
| [(id?: string | null) => string |
| [(id?: string | null) => string |
| Updates the display name of a node. | |
|
| Generates a unique node name based on existing nodes. |
| Sets the current clicked node ID. | |
| Sets the current clicked tool ID. | |
| [(id?: string | null) => RAGFlowNodeType |
| Deletes edges from a source node with a specific source handle. | |
| [(id: string | null) => string |
| Updates nodes' |
Key Implementations and Algorithms
Edge and Node Change Handlers
onNodesChangeandonEdgesChangeuse applyNodeChanges and applyEdgeChanges functions to efficiently handle incremental graph updates.Mouse event handlers on edges (
onEdgeMouseEnterandonEdgeMouseLeave) use mapEdgeMouseEvent to update edge state on hover for UI feedback.
Edge Updates by Node
setEdgesByNodeIdcompares current downstream edges of a node with previously stored edges, using deep equality checks (isEdgeEqual), and selectively updates edges only if there are differences to optimize rendering and state updates.
Node Duplication
duplicateNodesupports generic duplication and special handling for iteration nodes viaduplicateIterationNode, which recursively duplicates children nodes and correctly assigns new parent IDs.Names are generated uniquely with generateNodeNamesWithIncreasingIndex to avoid conflicts.
Form Data Updates on Connections
For nodes of type
Switch, the form data is updated when edges are connected or disconnected to reflect the new routing logic.updateSwitchFormDatamaintains arrays of target node IDs connected to switch conditions or the "else" condition.
Deletion Logic
Nodes and edges can be deleted individually or in groups (e.g., downstream nodes of an Agent).
Deleting an edge also triggers updates to related node form fields to keep data consistent.
Special handling is provided for deleting iteration nodes and their children.
Interaction with Other Parts of the System
Flow Components: Components rendering the graph use
useGraphStoreto subscribe to nodes and edges, and invoke actions to update the graph based on user interaction.Constants and Utilities: Uses constants like
Operator,NodeHandleId, and utility functions (duplicateNodeForm,generateDuplicateNode,isEdgeEqual) to maintain consistency in naming, duplication, and edge comparison.External Libraries: Relies on @xyflow/react for graph primitives and event types,
lodashfor deep object manipulation, and Zustand for state management with Immer and Devtools middleware.Flow Data Model: Manages nodes and edges conforming to
RAGFlowNodeTypeandEdgeinterfaces, which are part of the domain model representing the flow graph.
Usage Examples
Adding a Node
const newNode: RAGFlowNodeType = {
id: 'node-1',
data: { label: 'Agent', name: 'Agent 1', form: {} },
position: { x: 100, y: 100 },
};
useGraphStore.getState().addNode(newNode);
Connecting Nodes
useGraphStore.getState().onConnect({
source: 'node-1',
sourceHandle: 'output-1',
target: 'node-2',
targetHandle: 'input-1',
});
Deleting a Node
useGraphStore.getState().deleteNodeById('node-1');
Updating Node Form Data
useGraphStore.getState().updateNodeForm('node-1', { description: 'Updated agent' });
Mermaid Class Diagram
classDiagram
class RFState {
+nodes: RAGFlowNodeType[]
+edges: Edge[]
+selectedNodeIds: string[]
+selectedEdgeIds: string[]
+clickedNodeId: string
+clickedToolId: string
+onNodesChange(changes)
+onEdgesChange(changes)
+onEdgeMouseEnter(event, edge)
+onEdgeMouseLeave(event, edge)
+onConnect(connection)
+onSelectionChange(params)
+setNodes(nodes)
+setEdges(edges)
+setEdgesByNodeId(nodeId, edges)
+addNode(node)
+updateNode(node)
+getNode(id)
+addEdge(connection)
+getEdge(id)
+updateFormDataOnConnect(connection)
+updateSwitchFormData(source, sourceHandle, target, isConnecting)
+duplicateNode(id, name)
+duplicateIterationNode(id, name)
+deleteEdge()
+deleteEdgeById(id)
+deleteNodeById(id)
+deleteAgentDownstreamNodesById(id)
+deleteAgentToolNodeById(id)
+deleteIterationNodeById(id)
+findNodeByName(name)
+updateNodeForm(nodeId, values, path)
+updateMutableNodeFormItem(id, field, value)
+getOperatorTypeFromId(id)
+getParentIdById(id)
+updateNodeName(id, name)
+generateNodeName(name)
+setClickedNodeId(id)
+setClickedToolId(id)
+findUpstreamNodeById(id)
+deleteEdgesBySourceAndSourceHandle(source, sourceHandle)
+findAgentToolNodeById(id)
+selectNodeIds(nodeIds)
}
class useGraphStore {
<<singleton>>
+RFState state and actions
}
Summary
The store.ts file provides a comprehensive and sophisticated graph state management solution leveraging Zustand and Immer.
It maintains a robust API to manipulate nodes and edges, supporting complex operations such as duplication, conditional updates, and deletion cascades.
The store is tightly integrated with the graph UI components and utilities, making it the backbone of the graph editing experience in the application.
This modular and reactive store simplifies the management of graph workflows, ensuring data consistency and enabling complex flow logic to be handled declaratively.
End of documentation.