@internal Used to flatten the subgraph before execution.
(
/** The set of computed node DTOs for this execution. */
executableNodes: Map<ExecutionId, ExecutableLGraphNode>,
/** The path of subgraph node IDs. */
subgraphNodePath: readonly NodeId[] = [],
/** Internal recursion param. The list of nodes to add to. */
nodes: ExecutableLGraphNode[] = [],
/** Internal recursion param. The set of visited nodes. */
visited = new Set<SubgraphNode>(),
)
| 313 | |
| 314 | /** @internal Used to flatten the subgraph before execution. */ |
| 315 | getInnerNodes( |
| 316 | /** The set of computed node DTOs for this execution. */ |
| 317 | executableNodes: Map<ExecutionId, ExecutableLGraphNode>, |
| 318 | /** The path of subgraph node IDs. */ |
| 319 | subgraphNodePath: readonly NodeId[] = [], |
| 320 | /** Internal recursion param. The list of nodes to add to. */ |
| 321 | nodes: ExecutableLGraphNode[] = [], |
| 322 | /** Internal recursion param. The set of visited nodes. */ |
| 323 | visited = new Set<SubgraphNode>(), |
| 324 | ): ExecutableLGraphNode[] { |
| 325 | if (visited.has(this)) { |
| 326 | const nodeInfo = `${this.id}${this.title ? ` (${this.title})` : ""}` |
| 327 | const subgraphInfo = `'${this.subgraph.name || "Unnamed Subgraph"}'` |
| 328 | const depth = subgraphNodePath.length |
| 329 | throw new RecursionError( |
| 330 | `Circular reference detected at depth ${depth} in node ${nodeInfo} of subgraph ${subgraphInfo}. ` + |
| 331 | `This creates an infinite loop in the subgraph hierarchy.`, |
| 332 | ) |
| 333 | } |
| 334 | visited.add(this) |
| 335 | |
| 336 | const subgraphInstanceIdPath = [...subgraphNodePath, this.id] |
| 337 | |
| 338 | // Store the subgraph node DTO |
| 339 | const parentSubgraphNode = this.graph.rootGraph.resolveSubgraphIdPath(subgraphNodePath).at(-1) |
| 340 | const subgraphNodeDto = new ExecutableNodeDTO(this, subgraphNodePath, executableNodes, parentSubgraphNode) |
| 341 | executableNodes.set(subgraphNodeDto.id, subgraphNodeDto) |
| 342 | |
| 343 | for (const node of this.subgraph.nodes) { |
| 344 | if ("getInnerNodes" in node) { |
| 345 | node.getInnerNodes(executableNodes, subgraphInstanceIdPath, nodes, new Set(visited)) |
| 346 | } else { |
| 347 | // Create minimal DTOs rather than cloning the node |
| 348 | const aVeryRealNode = new ExecutableNodeDTO(node, subgraphInstanceIdPath, executableNodes, this) |
| 349 | executableNodes.set(aVeryRealNode.id, aVeryRealNode) |
| 350 | nodes.push(aVeryRealNode) |
| 351 | } |
| 352 | } |
| 353 | return nodes |
| 354 | } |
| 355 | |
| 356 | override removeWidgetByName(name: string): void { |
| 357 | const widget = this.widgets.find(w => w.name === name) |
no test coverage detected