# Contributing to ComfyUI-KikoTools We love contributions! ComfyUI-KikoTools is built by the community, for the community. This guide will help you get started with contributing to our collection of essential ComfyUI tools. ## ๐ŸŒŸ Ways to Contribute ### ๐Ÿ› Bug Reports - Found a bug? Please [open an issue](https://github.com/ComfyAssets/ComfyUI-KikoTools/issues) - Include ComfyUI version, tool name, and reproduction steps - Screenshots and error logs are super helpful! ### ๐Ÿ’ก Feature Requests - Have an idea for a new tool? [Start a discussion](https://github.com/ComfyAssets/ComfyUI-KikoTools/discussions) - Describe the use case and expected behavior - Check existing tools to avoid duplication ### ๐Ÿ”ง Code Contributions - Fix bugs, improve performance, add new tools - Follow our development principles (see below) - All contributions must include tests ### ๐Ÿ“š Documentation - Improve README, add examples, write tutorials - Update tool documentation in `examples/documentation/` - Create example workflows in `examples/workflows/` ## ๐Ÿš€ Getting Started ### Prerequisites - Python 3.8+ - ComfyUI installation (for testing) - Git knowledge - Basic understanding of PyTorch tensors ### Development Setup 1. **Fork and Clone** ```bash git clone https://github.com/YOUR_USERNAME/ComfyUI-KikoTools.git cd ComfyUI-KikoTools ``` 2. **Create Virtual Environment** ```bash python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate ``` 3. **Install Dependencies** ```bash pip install -r requirements-dev.txt ``` 4. **Verify Setup** ```bash python -c " import sys, os sys.path.insert(0, os.getcwd()) from kikotools.tools.resolution_calculator.node import ResolutionCalculatorNode import torch node = ResolutionCalculatorNode() result = node.calculate_resolution(2.0, image=torch.randn(1, 512, 512, 3)) print(f'โœ… Setup successful! Test result: {result[0]}x{result[1]}') " ``` ## ๐Ÿ—๏ธ Development Principles We follow these principles to maintain high code quality: ### KISS (Keep It Simple, Stupid) - Single responsibility per tool - Simple, intuitive interfaces - Minimal dependencies ### Separation of Concerns ``` tool_name/ โ”œโ”€โ”€ logic.py # Pure functions, no ComfyUI dependencies โ”œโ”€โ”€ node.py # ComfyUI interface only โ””โ”€โ”€ __init__.py # Module exports ``` ### DRY (Don't Repeat Yourself) - Shared functionality goes in `base/` - Reusable utilities in `base/utils.py` - Common validation patterns ### SOLID Principles - **S**ingle Responsibility: Each class has one reason to change - **O**pen/Closed: Open for extension, closed for modification - **L**iskov Substitution: Subclasses are substitutable for base classes - **I**nterface Segregation: Minimal, focused interfaces - **D**ependency Inversion: Depend on abstractions, not concretions ## ๐Ÿงช Test-Driven Development (TDD) We use TDD for all new features: ### 1. Write Tests First ```python def test_new_feature_behavior(): """Test what the feature should do before implementing it""" # Arrange input_data = create_test_input() expected_output = calculate_expected_result() # Act actual_output = new_feature_function(input_data) # Assert assert actual_output == expected_output ``` ### 2. Run Tests (Should Fail) ```bash python -c "import sys; sys.path.insert(0, '.'); from tests.unit.test_new_feature import *; test_new_feature_behavior()" ``` ### 3. Implement Minimal Code Write just enough code to make the test pass. ### 4. Refactor and Expand - Add error handling - Optimize performance - Add comprehensive validation - Ensure divisible-by-8 constraints ### 5. Integration Testing Test the complete workflow in a ComfyUI-like environment. ## ๐Ÿ› ๏ธ Adding a New Tool Follow this step-by-step process: ### Step 1: Planning 1. **Create Issue**: Describe the tool's purpose and requirements 2. **Update plan.md**: Add detailed specifications 3. **Design Interface**: Define inputs, outputs, and constraints ### Step 2: Project Structure ```bash # Create tool directory mkdir -p kikotools/tools/your_tool_name # Create files touch kikotools/tools/your_tool_name/__init__.py touch kikotools/tools/your_tool_name/logic.py touch kikotools/tools/your_tool_name/node.py # Create tests touch tests/unit/tools/test_your_tool_name.py ``` ### Step 3: Write Tests (TDD) ```python # tests/unit/tools/test_your_tool_name.py import pytest import torch from kikotools.tools.your_tool_name.logic import your_main_function from kikotools.tools.your_tool_name.node import YourToolNode class TestYourToolLogic: def test_basic_functionality(self): # Test core logic here pass def test_error_handling(self): # Test edge cases and errors pass class TestYourToolNode: def test_comfyui_interface(self): # Test ComfyUI integration pass ``` ### Step 4: Implement Logic ```python # kikotools/tools/your_tool_name/logic.py import torch from typing import Tuple, Optional def your_main_function(input_tensor: torch.Tensor, param: float) -> Tuple[int, int]: """ Pure function implementing the core logic Args: input_tensor: Input tensor from ComfyUI param: Tool-specific parameter Returns: Tuple of results Raises: ValueError: If validation fails """ # Implement logic here pass ``` ### Step 5: Create ComfyUI Node ```python # kikotools/tools/your_tool_name/node.py from ...base import ComfyAssetsBaseNode from .logic import your_main_function class YourToolNode(ComfyAssetsBaseNode): """ComfyUI node for Your Tool""" @classmethod def INPUT_TYPES(cls): return { "required": { "param": ("FLOAT", {"default": 1.0, "min": 0.1, "max": 10.0}), }, "optional": { "input_tensor": ("IMAGE",), } } RETURN_TYPES = ("INT", "INT") RETURN_NAMES = ("result1", "result2") FUNCTION = "execute_tool" def execute_tool(self, param, input_tensor=None): try: self.validate_inputs(param=param, input_tensor=input_tensor) return your_main_function(input_tensor, param) except Exception as e: self.handle_error(f"Tool execution failed: {str(e)}", e) ``` ### Step 6: Register Tool ```python # kikotools/tools/your_tool_name/__init__.py from .node import YourToolNode __all__ = ["YourToolNode"] # Update kikotools/__init__.py from .tools.your_tool_name import YourToolNode NODE_CLASS_MAPPINGS = { "YourTool": YourToolNode, } NODE_DISPLAY_NAME_MAPPINGS = { "YourTool": "Your Tool Name", } ``` ### Step 7: Documentation ```markdown # examples/documentation/your_tool_name.md # Your Tool Name ## Overview Brief description of what the tool does. ## Inputs - param (FLOAT): Description of parameter ## Outputs - result1 (INT): Description of first output - result2 (INT): Description of second output ## Use Cases 1. Use case 1 2. Use case 2 ## Examples Example workflows and usage patterns. ``` ### Step 8: Testing and Validation ```bash # Run your tests python -c "import sys; sys.path.insert(0, '.'); [run your test functions]" # Test integration python -c "from kikotools.tools.your_tool_name import YourToolNode; print('โœ… Integration successful')" # Code quality black kikotools/tools/your_tool_name/ flake8 kikotools/tools/your_tool_name/ ``` ## ๐Ÿ“‹ Pull Request Process ### Before Submitting - [ ] All tests pass locally - [ ] Code follows our style guidelines - [ ] Documentation is updated - [ ] Example workflows included (if applicable) ### PR Template ```markdown ## Description Brief description of changes. ## Type of Change - [ ] Bug fix - [ ] New tool - [ ] Enhancement - [ ] Documentation update ## Testing - [ ] Unit tests added/updated - [ ] Integration tests pass - [ ] Manual testing completed ## Checklist - [ ] Code follows project style - [ ] Self-review completed - [ ] Documentation updated - [ ] No breaking changes (or clearly documented) ``` ### Review Process 1. **Automated Checks**: CI runs tests and quality checks 2. **Code Review**: Maintainer reviews code and provides feedback 3. **Testing**: Manual testing in ComfyUI environment 4. **Merge**: After approval, changes are merged to main ## ๐ŸŽจ Code Style Guidelines ### Python Style - **Formatting**: Use `black` (line length: 127) - **Linting**: Follow `flake8` guidelines - **Type Hints**: Use type annotations for all functions - **Docstrings**: Google-style docstrings for all public functions ### Example Code Style ```python from typing import Tuple, Optional import torch def calculate_dimensions( input_tensor: torch.Tensor, scale_factor: float ) -> Tuple[int, int]: """ Calculate scaled dimensions from input tensor. Args: input_tensor: Input image or latent tensor scale_factor: Scaling factor to apply Returns: Tuple of (width, height) as integers Raises: ValueError: If input validation fails """ if scale_factor <= 0: raise ValueError(f"Scale factor must be positive, got {scale_factor}") # Implementation here return width, height ``` ### File Organization ```python # Standard library imports import os import sys from typing import Tuple, Optional # Third-party imports import torch import numpy as np # Local imports from ...base import ComfyAssetsBaseNode from .logic import helper_function ``` ## ๐Ÿ› Debugging Guidelines ### Common Issues 1. **Import Errors**: Check `sys.path` and relative imports 2. **Tensor Shape Issues**: Validate input tensor dimensions 3. **ComfyUI Integration**: Ensure proper INPUT_TYPES format 4. **Memory Issues**: Test with various image sizes ### Debugging Tools ```python # Debug tensor shapes print(f"Tensor shape: {tensor.shape}") print(f"Tensor dtype: {tensor.dtype}") # Debug ComfyUI interface input_types = YourNode.INPUT_TYPES() print(f"Input types: {input_types}") # Debug calculations result = your_function(test_input) print(f"Result: {result}, type: {type(result)}") ``` ## ๐Ÿ“Š Performance Guidelines ### Optimization Priorities 1. **Correctness**: Always prioritize correct results 2. **Memory Efficiency**: Minimize tensor copying 3. **Speed**: Optimize hot paths 4. **Compatibility**: Support various tensor sizes ### Performance Testing ```python import time import torch def benchmark_function(): large_tensor = torch.randn(1, 2048, 2048, 3) start_time = time.time() result = your_function(large_tensor) end_time = time.time() print(f"Processing time: {end_time - start_time:.3f}s") print(f"Memory usage: {torch.cuda.memory_allocated() / 1024**2:.1f}MB") ``` ## ๐Ÿค Community Guidelines ### Be Respectful - Use welcoming and inclusive language - Respect different viewpoints and experiences - Focus on what's best for the community ### Be Constructive - Provide helpful feedback in reviews - Suggest improvements rather than just pointing out problems - Help others learn and grow ### Be Patient - Maintainers are volunteers with limited time - New contributors may need extra guidance - Complex features take time to implement properly ## โ“ Getting Help ### Documentation - **README.md**: Project overview and quick start - **examples/documentation/**: Tool-specific documentation ### Community - **GitHub Issues**: Bug reports and feature requests - **GitHub Discussions**: General questions and ideas - **ComfyUI Discord**: Community chat (mention our tools) ### Maintainers - Review pull requests and issues - Provide guidance on architecture decisions - Help with complex technical problems ## ๐ŸŽ‰ Recognition Contributors are recognized in several ways: - **README.md**: Listed in contributors section - **Release Notes**: Mentioned in relevant releases - **GitHub**: Automatic contribution tracking - **Community**: Recognition in ComfyUI community ## ๐Ÿ“„ License By contributing, you agree that your contributions will be licensed under the MIT License. --- Thank you for contributing to ComfyUI-KikoTools! Together, we're building essential tools that make ComfyUI workflows more powerful and efficient. ๐Ÿš€