def add(self, node: Union[TaskNode, Task, 'TaskChain', DecisionFunc, DecisionLLM]) -> 'TaskChain':
        """
        Adds a node or another chain to this chain.
        
        Args:
            node: The node, task, or chain to add
            
        Returns:
            This chain for method chaining
        """
        # If given a Task, wrap it in a TaskNode
        if isinstance(node, Task):
            node = TaskNode(task=node)
        
        if isinstance(node, TaskNode):
            if self.nodes:
                last_node = self.nodes[-1]
                if last_node.id not in self.edges:
                    self.edges[last_node.id] = []
                self.edges[last_node.id].append(node.id)
                
                # If the last node is a TaskNode, update its next_nodes
                if isinstance(last_node, TaskNode):
                    last_node.next_nodes.append(node)
            self.nodes.append(node)
        elif isinstance(node, (DecisionFunc, DecisionLLM)):
            # Add the decision node itself
            self.nodes.append(node)
            
            # Connect decision node to its branches
            if node.true_branch:
                if isinstance(node.true_branch, TaskNode):
                    if node.id not in self.edges:
                        self.edges[node.id] = []
                    self.edges[node.id].append(node.true_branch.id)
                    
                    # Add true branch node if not already in the chain
                    if node.true_branch not in self.nodes:
                        self.nodes.append(node.true_branch)
                elif isinstance(node.true_branch, TaskChain):
                    # Add all nodes from the true branch chain
                    if node.true_branch.nodes:
                        first_node = node.true_branch.nodes[0]
                        if node.id not in self.edges:
                            self.edges[node.id] = []
                        self.edges[node.id].append(first_node.id)
                        
                        # Add the nodes from the true branch
                        for n in node.true_branch.nodes:
                            if n not in self.nodes:
                                self.nodes.append(n)
                        
                        # Merge the edges from the true branch
                        for src, targets in node.true_branch.edges.items():
                            if src not in self.edges:
                                self.edges[src] = []
                            self.edges[src].extend(targets)
            
            # Connect false branch as well
            if node.false_branch:
                if isinstance(node.false_branch, TaskNode):
                    if node.id not in self.edges:
                        self.edges[node.id] = []
                    self.edges[node.id].append(node.false_branch.id)
                    
                    # Add false branch node if not already in the chain
                    if node.false_branch not in self.nodes:
                        self.nodes.append(node.false_branch)
                elif isinstance(node.false_branch, TaskChain):
                    # Add all nodes from the false branch chain
                    if node.false_branch.nodes:
                        first_node = node.false_branch.nodes[0]
                        if node.id not in self.edges:
                            self.edges[node.id] = []
                        self.edges[node.id].append(first_node.id)
                        
                        # Add the nodes from the false branch
                        for n in node.false_branch.nodes:
                            if n not in self.nodes:
                                self.nodes.append(n)
                        
                        # Merge the edges from the false branch
                        for src, targets in node.false_branch.edges.items():
                            if src not in self.edges:
                                self.edges[src] = []
                            self.edges[src].extend(targets)
        elif isinstance(node, TaskChain):
            if self.nodes and node.nodes:
                last_node = self.nodes[-1]
                first_of_new = node.nodes[0]
                if last_node.id not in self.edges:
                    self.edges[last_node.id] = []
                self.edges[last_node.id].append(first_of_new.id)
                
                # If the last node is a TaskNode, update its next_nodes
                if isinstance(last_node, TaskNode) and isinstance(first_of_new, TaskNode):
                    last_node.next_nodes.append(first_of_new)
            
            # Merge the other chain's edges into this one
            self.edges.update(node.edges)
            self.nodes.extend(node.nodes)
            
        return self

        Adds a node or another chain to this chain.
        
        Args:
            node: The node, task, or chain to add
            
        Returns:
            This chain for method chaining
        
src/upsonic/client/graph.py