5.8 KiB
5.8 KiB
Copilot Instructions for ComfyUI Friendly Pipe
Project Overview
This is a ComfyUI custom node pack called "Friendly Pipe" that provides flexible pipe nodes for bundling and unbundling multiple connections of any type. It allows ComfyUI workflow creators to organize complex workflows by bundling related connections through a single pipe.
- Repository:
logicalor/comfyui_friendly_pipe - Version: 1.2.5
- License: MIT
Architecture
Node Types
The pack provides three custom nodes:
- FriendlyPipeIn - Bundles up to 80 inputs into a single
FRIENDLY_PIPEoutput - FriendlyPipeOut - Unpacks a
FRIENDLY_PIPEback into individual outputs - FriendlyPipeEdit - Extends an existing pipe by adding new slots while preserving original slots
File Structure
comfyui_friendly_pipe/
├── __init__.py # Node registration (NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS)
├── friendly_pipe_in.py # FriendlyPipeIn Python backend
├── friendly_pipe_out.py # FriendlyPipeOut Python backend
├── friendly_pipe_edit.py # FriendlyPipeEdit Python backend
├── any_type.py # AnyType class for universal type compatibility
├── pyproject.toml # ComfyUI Manager metadata
├── README.md # Documentation
└── js/
└── friendly_pipe.js # Frontend JavaScript (~1200 lines) for dynamic UI
Technical Details
AnyType System (any_type.py)
The AnyType class is crucial for type compatibility:
class AnyType(str):
"""A special type class that matches any other type in ComfyUI's type system."""
def __ne__(self, other): return False
def __eq__(self, other): return True
def __hash__(self): return hash("*")
ANY_TYPE = AnyType("*")
- Inherits from
strwith value"*" - Overrides equality operators to match any type
- Enables inputs to accept any ComfyUI data type
- Used by all three node types for their slot definitions
Pipe Data Structure
The FRIENDLY_PIPE type carries a dictionary:
{
"slot_count": int, # Total number of slots
"slots": {int: Any}, # Slot index -> data mapping
"names": {int: str} # Slot index -> label mapping
}
Python Backend Patterns
Each node class follows ComfyUI conventions:
INPUT_TYPES()- Class method returning input definitionsRETURN_TYPES- Tuple of output typesRETURN_NAMES- Tuple of output namesFUNCTION- Name of the execution method (always"execute")CATEGORY- Node category in ComfyUI menu ("utils/pipe")MAX_SLOTS = 80- Maximum slots per node
Hidden inputs are used for UI state:
slot_count(INT) - Number of active slotsslot_names(STRING) - JSON-encoded slot labels
JavaScript Frontend (js/friendly_pipe.js)
The frontend is registered as a ComfyUI extension:
app.registerExtension({
name: "Comfy.FriendlyPipe",
async beforeRegisterNodeDef(nodeType, nodeData, app) { ... }
});
Key concepts:
- Dynamic Slots: Add/remove input slots via button widgets
- Label Widgets: Text widgets for naming each slot
- Auto-Sync: FriendlyPipeOut automatically syncs with connected source
- Subgraph Support: Handles traversal through reroute nodes and subgraphs
Important helper functions:
findOriginalSource()- Traverses backwards through reroutes/subgraphs to find sourcenotifyDownstreamNodes()- Propagates changes to connected output nodesfindSourceThroughParent()- Handles subgraph boundary traversalisPassThroughNode()- Detects reroute/primitive nodes
Serialization
Both Python and JavaScript handle serialization:
onSerialize/onConfigurein JS for graph save/load- Hidden widgets pass state to Python during execution
Development Guidelines
When Adding New Features
- Python Changes: Update the relevant
friendly_pipe_*.pyfile - UI Changes: Modify
js/friendly_pipe.js - Type Changes: Update
any_type.pyif needed - Node Registration: Update
__init__.pyif adding new nodes
Coding Conventions
- Use
forceInput: Truefor slots that should only accept connections - Normalize slot keys to integers when reading from pipe data (handle both int and string keys)
- Use
"*"as the universal type string in LiteGraph - Always notify downstream nodes after changes via
notifyConnectedOutputs()
Testing Considerations
- Test with reroute nodes between pipe nodes
- Test with subgraphs containing pipe nodes
- Test serialization (save/reload workflow)
- Test chaining multiple FriendlyPipeEdit nodes
- Verify type passthrough works with typed inputs
Common Issues
- Slot Sync: If FriendlyPipeOut doesn't update, check
syncWithSource()traversal - Subgraph Issues: Check
findSourceThroughParent()and_subgraph_nodehandling - Type Mismatch: Ensure
ANY_TYPEis used consistently - Widget Order: Label widgets must be inserted before add/remove buttons
ComfyUI Integration
Required Exports (__init__.py)
NODE_CLASS_MAPPINGS = { ... } # Maps node type names to classes
NODE_DISPLAY_NAME_MAPPINGS = { ... } # Maps node type names to display names
WEB_DIRECTORY = "./js" # Frontend JavaScript location
ComfyUI Manager (pyproject.toml)
[tool.comfy]
PublisherId = "logicalor"
DisplayName = "Friendly Pipe"
Key Implementation Notes
- Slot Count: The
MAX_SLOTSconstant (80) is defined in each node class - Type Preservation: Connected types are tracked in
slotTypesdict and passed through the pipe - Input Labels: Slot labels are stored in
slotNamesdict and reflected on input/output ports - FriendlyPipeEdit: Maintains both
incomingSlot*(from upstream pipe) and localslot*properties - Subgraph Traversal: Uses negative
origin_iddetection and_subgraph_nodereferences