utils.ts
Overview
The utils.ts file provides a comprehensive set of utility functions primarily focused on managing and transforming graph-based data structures that represent workflows composed of nodes and edges. These workflows are related to operators such as Agent, Categorize, Tool, Note, and others in a DSL (Domain Specific Language) environment, likely for a flowchart or pipeline editor interface.
The file contains utilities for:
Building and manipulating DSL components from graph nodes and edges.
Handling operator-specific parameters and forms.
Managing node positions and names.
Converting between data formats (objects to lists, lists to objects).
Filtering and mapping edges and nodes.
Supporting UI-related functionalities such as drag handles and drawer widths.
Supporting debugging and error handling.
This file interacts closely with types and interfaces representing nodes, edges, and operator forms, and it is used in the context of a React-based flow management system (e.g., using @xyflow/react).
Detailed Descriptions
Imports and Dependencies
Interfaces:
IAgentForm,ICategorizeForm,ICategorizeItem, ICategorizeItemResult for form data shapes.Types: DSLComponents, RAGFlowNodeType represent the graph nodes/components.
Utility functions: removeUselessFieldsFromValues for cleaning form data.
React Flow types:
Edge,Node,XYPosition.Form types from Ant Design:
FormInstance,FormListFieldData.Lodash utilities for functional programming and deep data handling.
Constants and internal interfaces from related modules.
Functions and Exports
buildAgentExceptionGoto(edges: Edge[], nodeId: string): string[]
Filters edges starting from a given node's "AgentException" handle and returns the list of target node IDs.
Parameters:
edges: Array of graph edges.nodeId: The source node ID.
Returns: Array of target node IDs connected via AgentException handle.
Usage: Used to retrieve exception handling targets for Agent nodes.
buildComponentDownstreamOrUpstream(edges: Edge[], nodeId: string, isBuildDownstream = true, nodes: Node[]): string[]
Builds either downstream or upstream node IDs connected to a given node, with specific filtering rules for Agent nodes.
Parameters:
edges: Array of graph edges.nodeId: Node ID to find neighbors.isBuildDownstream: Boolean to specify downstream (true) or upstream (false).nodes: List of all nodes in the graph.
Returns: Array of node IDs connected downstream or upstream.
Implementation Detail:
Excludes certain edges for Agent nodes (like exception goto edges, downstream tools, and agents connected via specific handles).
Usage: Helps build component relationships for DSL construction.
removeUselessDataInTheOperator(operatorName: string, params: Record<string, unknown>): Record<string, unknown>
Curried function cleaning operator parameters by removing unnecessary fields, specifically for Generate and Categorize operators.
Parameters:
operatorName: The operator's name.params: Parameters object.
Returns: Cleaned parameters object.
Usage: Ensures operator params are clean before further processing.
buildAgentTools(edges: Edge[], nodes: Node[], nodeId: string): {params: IAgentForm, name?: string, id?: string}
Recursively gathers tools connected under an Agent node, including nested sub-agents connected via the "AgentBottom" handle.
Parameters:
edges: Array of edges.nodes: Array of nodes.nodeId: Agent node ID.
Returns: An object with params (agent form with tools),
name, andid.Implementation Detail:
Recursively traverses sub-agent links and appends their tool info.
Usage: Builds complete parameter sets for Agent operators including sub-components.
filterTargetsBySourceHandleId(edges: Edge[], handleId: string): string[]
Filters edges by a specific source handle ID and returns target node IDs.
Parameters:
edges: Array of edges.handleId: Source handle identifier.
Returns: Array of target node IDs.
Usage: Used in Categorize operator to link categories to their targets.
buildCategorize(edges: Edge[], nodes: Node[], nodeId: string): ICategorizeForm
Constructs a Categorize form parameter object by processing edges and nodes, syncing category items with edges.
Parameters:
edges: Edges array.nodes: Nodes array.nodeId: Categorize node ID.
Returns: Categorize form object without the items field, with category_description containing synced data.
Implementation Detail:
Converts the items array into a category_description object keyed by category name.
Converts examples to simple arrays.
Links targets via handle UUIDs.
Usage: Keeps Categorize node form data consistent with graph edges.
buildOperatorParams(operatorName: string): (params: any) => any
Creates a pipeline function for processing operator parameters, currently applying removeUselessDataInTheOperator.
Parameters:
operatorName: Operator label.
Returns: A function accepting operator params and returning cleaned params.
Usage: Standardizes operator parameter processing.
isBottomSubAgent(edges: Edge[], nodeId?: string): boolean
Determines if a node is a bottom sub-agent by checking if it is the target of an edge with "AgentTop" handle.
Parameters:
edges: Array of edges.nodeId: Node ID.
Returns: true if node is a bottom sub-agent, else
false.Usage: Used to exclude bottom sub-agents from certain DSL builds.
buildDslComponentsByGraph(nodes: RAGFlowNodeType[], edges: Edge[], oldDslComponents: DSLComponents): DSLComponents
Main builder function that constructs DSL components from the graph nodes and edges.
Parameters:
nodes: Array of flow nodes.edges: Array of edges.oldDslComponents: Existing DSL components for merging.
Returns: A DSLComponents object representing the workflow.
Implementation Detail:
Filters nodes excluding certain operators and bottom sub-agents.
Builds operator params with operator-specific logic (e.g., Agent, Categorize).
Computes downstream and upstream node relationships.
Merges with old DSL components.
Usage: Central function that converts graph representation into DSL components for execution or storage.
receiveMessageError(res: any): boolean
Simple utility to check if a message response contains an error based on HTTP status and response code.
Parameters:
res: Response object.
Returns: true if error, else
false.Usage: Used to uniformly detect errors in message responses.
replaceIdWithText(obj: Record<string, unknown> | unknown[] | unknown, getNameById: (id?: string) => string | undefined): unknown
Recursively replaces string IDs in an object with their corresponding text labels using a provided lookup function.
Parameters:
obj: The object or array to process.getNameById: Function mapping ID strings to text labels.
Returns: New object or array with IDs replaced by text labels.
Usage: Used to prepare data for display or export by replacing IDs with human-readable names.
isEdgeEqual(previous: Edge, current: Edge): boolean
Checks whether two edges are equal based on source, target, and source handle.
Parameters:
previous: Previous edge.current: Current edge.
Returns: true if equal, else
false.Usage: Helps in diffing or updating edge data.
buildNewPositionMap(currentKeys: string[], previousPositionMap: Record<string, IPosition>): {intersectionKeys: string[], newPositionMap: Record<string, IPosition>}
Computes a new position map for nodes, attempting to reuse existing positions and assigning new positions from predefined anchor points for new keys.
Parameters:
currentKeys: Current node keys.previousPositionMap: Previous position mapping.
Returns: Object containing:
intersectionKeys: Keys common in previous and current.newPositionMap: Positions assigned to new keys.
Implementation Detail:
Uses
CategorizeAnchorPointPositionsas possible coordinates.Avoids overlapping index assignments.
Usage: Used for positioning nodes in UI forms like Categorize operator.
isKeysEqual(currentKeys: string[], previousKeys: string[]): boolean
Checks if two arrays of keys are equal (ignoring order).
Parameters:
currentKeyspreviousKeys
Returns: Boolean indicating equality.
Usage: For detecting changes in node or category keys.
getOperatorIndex(handleTitle: string): string | undefined
Extracts the index (assumed last word) from a handle title string.
Parameters:
handleTitle: String like"Case 1".
Returns: The last segment after splitting by space.
Usage: Helps in indexing cases or handles.
getOtherFieldValues(form: FormInstance, formListName = 'items', field: FormListFieldData, latestField: string): any[]
Returns values of a specific field from all form list items except the current one.
Parameters:
form: Ant Design Form instance.formListName: List name in the form (default 'items').field: Current form list field data.latestField: Field name to extract.
Returns: Array of field values excluding current.
Usage: Used in form validation or uniqueness checks.
generateSwitchHandleText(idx: number): string
Generates switch case handle text like "Case 1".
Parameters:
idx: Zero-based case index.
Returns: String label for case handle.
Usage: For dynamically labeling switch handles.
getNodeDragHandle(nodeType?: string): string | undefined
Returns a CSS selector for the drag handle of a node if applicable.
Parameters:
nodeType: Node label/type.
Returns: Selector string or undefined.
Usage: Adds drag handles specifically for Note nodes.
generateNodeNamesWithIncreasingIndex(name: string, nodes: RAGFlowNodeType[]): string
Generates a new node name by incrementing index suffix to avoid collisions.
Parameters:
name: Base name prefix.nodes: Existing nodes to check.
Returns: New unique node name like
"name_1".Implementation Detail:
Parses existing node names with suffix
_index.Finds first gap in the sequence to assign new index.
Usage: For naming new nodes uniquely.
duplicateNodeForm(nodeData?: RAGFlowNodeType['data']): RAGFlowNodeType['data']
Creates a deep copy of node form data, removing downstream links for Categorize and Relevant operators to avoid duplicating connections.
Parameters:
nodeData: Node data containing label and form.
Returns: New node data with cleaned form.
Usage: Used when duplicating nodes in the UI.
getDrawerWidth(): string | number
Returns drawer width based on window size, responsive design.
Returns:
'40%'if width > 1278px, else470.Usage: UI utility for responsive drawer sizing.
needsSingleStepDebugging(label: string): boolean
Returns whether an operator supports single-step debugging, excluding operators in NoDebugOperatorsList.
Parameters:
label: Operator label.
Returns: Boolean indicating debug support.
Usage: Controls debugging UI features.
getRelativePositionToIterationNode(nodes: RAGFlowNodeType[], position?: XYPosition): {parentId: string, position: XYPosition} | undefined
Computes the position of a node relative to any Iteration node in the graph.
Parameters:
nodes: All graph nodes.position: Absolute position of the node.
Returns: Relative position and parent Id if inside an Iteration node, else undefined.
Usage: For grouping or nesting nodes inside iterations.
generateDuplicateNode(position?: XYPosition, label?: string): RAGFlowNodeType
Generates a new node object for duplication with incremented position and unique ID.
Parameters:
position: Original node position.label: Node label.
Returns: New node data with unique ID and offset position.
Usage: For duplicating nodes with proper placement.
convertToStringArray(list?: Array<{ value: string | number | boolean }>): string[]
Converts an array of objects with value property to an array of strings.
Parameters:
list: Array of objects.
Returns: Array of strings.
Usage: Converts form data formats.
convertToObjectArray(list: Array<string | number | boolean>): Array<{ value: string | number | boolean }>
Converts an array of primitive values into objects with value property.
Parameters:
list: Array of primitives.
Returns: Array of objects.
Usage: Converts arrays for form compatibility.
buildCategorizeListFromObject(categorizeItem: ICategorizeItemResult): ICategorizeItem[]
Converts a Categorize form object into a list format.
Parameters:
categorizeItem: Object keyed by category names.
Returns: Array of categorized items sorted by
index.Usage: Synchronizes edge data with form list.
buildCategorizeObjectFromList(list: ICategorizeItem[]): ICategorizeItemResult
Converts a Categorize items list back into an object keyed by category names.
Parameters:
list: Array of Categorize items.
Returns: Object keyed by category names.
Usage: Converts form list data back to object for storage.
getAgentNodeTools(agentNode?: RAGFlowNodeType): IAgentForm['tools']
Returns the tools array from an Agent node's form.
Parameters:
agentNode: Agent node.
Returns: Tools array or empty array.
Usage: Accessor utility.
getAgentNodeMCP(agentNode?: RAGFlowNodeType): IAgentForm['mcp']
Returns the MCP (multi-component parameter) array from an Agent node's form.
Parameters:
agentNode: Agent node.
Returns: MCP array or empty array.
Usage: Accessor utility.
mapEdgeMouseEvent(edges: Edge[], edgeId: string, isHovered: boolean): Edge[]
Returns a new edges array with the specified edge marked as hovered or not.
Parameters:
edges: Edges array.edgeId: Target edge ID.isHovered: Hover state.
Returns: Updated edges array.
Usage: UI interaction handling for edge hover effects.
buildBeginQueryWithObject(inputs: Record<string, BeginQuery>, values: BeginQuery[]): Record<string, BeginQuery>
Builds a new inputs object by merging existing keys with corresponding values from an array.
Parameters:
inputs: Current inputs object.values: Array of BeginQuery values.
Returns: New inputs object with updated values.
Usage: Synchronizes form or query inputs.
Important Implementation Details
Curried Functions: Usage of lodash's
curryto create reusable parameter-processing functions.Recursive Data Building: Recursive retrieval of nested agent tools.
Filtering and Exclusion: Special handling to exclude certain operators or sub-agent nodes during DSL building.
Position Mapping: Intelligent assignment of anchor positions for categories avoiding overlap.
Deep Object Traversal: Recursive replacement of IDs with text labels.
UI Integration: Functions tailored for integration with React Flow and Ant Design forms.
Interaction With Other System Parts
Uses interfaces from @/interfaces/database/agent and @/interfaces/database/flow for data typing.
Depends on @xyflow/react for graph types (
Edge,Node).Uses Ant Design's form components (
FormInstance,FormListFieldData) for form data handling.Interacts with constants and internal types defined in sibling files (
./constant,./interface).Helps construct DSL components consumed by flow execution engines or UI renderers.
Supports UI features such as node duplication, drag handles, and drawer widths.
Usage Example
import { buildDslComponentsByGraph } from './utils';
import { nodes, edges } from './flowData';
import oldDsl from './oldDsl';
// Build the DSL components from current graph state
const newDslComponents = buildDslComponentsByGraph(nodes, edges, oldDsl);
// Now `newDslComponents` can be used to render the DSL or execute workflow logic.
Visual Diagram: Function Flowchart of utils.ts
flowchart TD
A[buildDslComponentsByGraph] --> B[buildAgentTools]
A --> C[buildCategorize]
A --> D[buildComponentDownstreamOrUpstream]
B --> E[buildAgentTools (recursive)]
C --> F[filterTargetsBySourceHandleId]
A --> G[buildOperatorParams]
G --> H[removeUselessDataInTheOperator]
A --> I[isBottomSubAgent]
A --> J[ExcludeOperators list]
K[replaceIdWithText] -->|Recursive| K
L[mapEdgeMouseEvent] --> M[edges update]
N[generateDuplicateNode] --> O[getNodeDragHandle]
P[buildNewPositionMap] --> Q[CategorizeAnchorPointPositions]
R[buildCategorizeListFromObject] --> S[convertToObjectArray]
T[buildCategorizeObjectFromList] --> U[convertToStringArray]
Summary
The utils.ts file is a core utility module for handling graph-based workflow