Compare commits

..
9 changed files with 1933 additions and 864 deletions
+28
View File
@@ -0,0 +1,28 @@
name: Publish to Comfy registry
on:
workflow_dispatch:
push:
branches:
- main
- master
paths:
- "pyproject.toml"
permissions:
issues: write
jobs:
publish-node:
name: Publish Custom Node to registry
runs-on: ubuntu-latest
if: ${{ github.repository_owner == 'ComfyAssets' }}
steps:
- name: Check out code
uses: actions/checkout@v4
with:
submodules: true
- name: Publish Custom Node
uses: Comfy-Org/publish-node-action@v1
with:
## Add your own personal access token to your Github Repository secrets and reference it here.
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
+45 -25
View File
@@ -2,6 +2,22 @@
.PHONY: help install test test-fast lint format type-check quality-check clean setup dev-test release-test
# Python and virtual environment setup
PYTHON := python3
VENV_DIR := venv
VENV_BIN := $(VENV_DIR)/bin
VENV_PYTHON := $(VENV_BIN)/python
VENV_PIP := $(VENV_BIN)/pip
# Check if we're in a virtual environment, if not use venv
ifeq ($(VIRTUAL_ENV),)
PYTHON_CMD := $(VENV_PYTHON)
PIP_CMD := $(VENV_PIP)
else
PYTHON_CMD := python
PIP_CMD := pip
endif
# Default target
help:
@echo "ComfyUI-KikoTools Development Commands"
@@ -28,44 +44,48 @@ help:
@echo " help - Show this help message"
# Setup and installation
setup:
@echo "Setting up ComfyUI-KikoTools development environment..."
python -m venv venv
@echo "Virtual environment created. Activate with:"
@echo " source venv/bin/activate (Linux/Mac)"
@echo " venv\\Scripts\\activate (Windows)"
@echo "Then run: make install"
setup: $(VENV_DIR)
@echo "✅ ComfyUI-KikoTools development environment ready"
@echo "Virtual environment created. Dependencies installed."
install:
$(VENV_DIR):
@echo "Creating virtual environment..."
$(PYTHON) -m venv $(VENV_DIR)
@echo "Installing development dependencies..."
pip install --upgrade pip
pip install -r requirements-dev.txt
$(VENV_PIP) install --upgrade pip
$(VENV_PIP) install -r requirements-dev.txt
@echo "✅ Virtual environment created and dependencies installed"
install: $(VENV_DIR)
@echo "Installing/updating development dependencies..."
$(PIP_CMD) install --upgrade pip
$(PIP_CMD) install -r requirements-dev.txt
@echo "✅ Dependencies installed"
# Code quality
format:
format: $(VENV_DIR)
@echo "Formatting code with black..."
black .
$(PYTHON_CMD) -m black .
@echo "✅ Code formatted"
lint:
lint: $(VENV_DIR)
@echo "Linting with flake8..."
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
$(PYTHON_CMD) -m flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics --exclude=venv
$(PYTHON_CMD) -m flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --exclude=venv
@echo "✅ Linting completed"
type-check:
type-check: $(VENV_DIR)
@echo "Type checking with mypy..."
mypy kikotools/ --ignore-missing-imports --no-strict-optional || true
$(PYTHON_CMD) -m mypy kikotools/ --ignore-missing-imports --no-strict-optional || true
@echo "✅ Type checking completed"
quality-check: format lint type-check
@echo "✅ All quality checks completed"
# Testing
dev-test:
dev-test: $(VENV_DIR)
@echo "Running quick development test..."
@python -c "\
@$(PYTHON_CMD) -c "\
import sys, os; \
sys.path.insert(0, os.getcwd()); \
from kikotools.tools.resolution_calculator.node import ResolutionCalculatorNode; \
@@ -75,9 +95,9 @@ dev-test:
print(f'✅ Development test passed! Result: {result[0]}x{result[1]}'); \
"
test-fast:
test-fast: $(VENV_DIR)
@echo "Running core functionality tests..."
@python -c "\
@$(PYTHON_CMD) -c "\
import sys, os; \
sys.path.insert(0, os.getcwd()); \
from kikotools.base import ComfyAssetsBaseNode; \
@@ -146,13 +166,13 @@ ci: quality-check test
@echo "✅ CI checks passed!"
# Tool-specific commands (can be extended for new tools)
test-resolution-calculator:
test-resolution-calculator: $(VENV_DIR)
@echo "Testing Resolution Calculator specifically..."
@python -c "import sys, os; sys.path.insert(0, os.getcwd()); from kikotools.tools.resolution_calculator.node import ResolutionCalculatorNode; import torch; node = ResolutionCalculatorNode(); scenarios = [('SDXL Portrait', torch.randn(1, 1216, 832, 3), 1.5), ('FLUX Square', torch.randn(1, 1024, 1024, 3), 2.0), ('User Scenario', torch.randn(1, 1216, 832, 3), 1.53)]; [print(f'✅ {name}: {image.shape[2]}×{image.shape[1]} → {node.calculate_resolution(scale, image=image)[0]}×{node.calculate_resolution(scale, image=image)[1]} ({scale}x)') for name, image, scale in scenarios]; print('🎉 Resolution Calculator tests completed!')"
@$(PYTHON_CMD) -c "import sys, os; sys.path.insert(0, os.getcwd()); from kikotools.tools.resolution_calculator.node import ResolutionCalculatorNode; import torch; node = ResolutionCalculatorNode(); scenarios = [('SDXL Portrait', torch.randn(1, 1216, 832, 3), 1.5), ('FLUX Square', torch.randn(1, 1024, 1024, 3), 2.0), ('User Scenario', torch.randn(1, 1216, 832, 3), 1.53)]; [print(f'✅ {name}: {image.shape[2]}×{image.shape[1]} → {node.calculate_resolution(scale, image=image)[0]}×{node.calculate_resolution(scale, image=image)[1]} ({scale}x)') for name, image, scale in scenarios]; print('🎉 Resolution Calculator tests completed!')"
test-width-height-selector:
test-width-height-selector: $(VENV_DIR)
@echo "Testing Width Height Selector specifically..."
@python -c "\
@$(PYTHON_CMD) -c "\
import sys, os; \
sys.path.insert(0, os.getcwd()); \
from kikotools.tools.width_height_selector.node import WidthHeightSelectorNode; \
+21 -2
View File
@@ -3,15 +3,34 @@ ComfyUI-KikoTools: Modular collection of custom ComfyUI nodes
All nodes are grouped under the "ComfyAssets" category
"""
import os
import re
from pathlib import Path
from .kikotools import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS
# Tell ComfyUI where to find our JavaScript extensions
WEB_DIRECTORY = "./web"
def get_version():
"""Parse version from pyproject.toml"""
try:
pyproject_path = Path(__file__).parent / "pyproject.toml"
if pyproject_path.exists():
content = pyproject_path.read_text()
match = re.search(r'version\s*=\s*["\']([^"\']+)["\']', content)
if match:
return match.group(1)
except Exception:
pass
return "unknown"
# Print startup message with loaded tools
print("\033[94m[ComfyUI-KikoTools]\033[0m")
print(f"\033[94m[ComfyUI-KikoTools] Version:\033[0m {get_version()}")
for node_key, display_name in NODE_DISPLAY_NAME_MAPPINGS.items():
print(f"🫶 \033[94m[Loaded:\033[0m {display_name}")
print(f"🫶 \033[94mLoaded:\033[0m {display_name}")
print(f"\033[94mTotal: {len(NODE_CLASS_MAPPINGS)} tools loaded\033[0m")
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]
@@ -1,47 +1,259 @@
{
"last_node_id": 3,
"last_link_id": 2,
"id": "41469b2d-d616-479d-879a-95cdc6074a37",
"revision": 0,
"last_node_id": 6,
"last_link_id": 5,
"nodes": [
{
"id": 1,
"type": "ResolutionCalculator",
"pos": [100, 100],
"size": {"0": 315, "1": 126},
"pos": [
60,
430
],
"size": [
315,
126
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "image",
"shape": 7,
"type": "IMAGE",
"link": 5
},
{
"name": "latent",
"shape": 7,
"type": "LATENT",
"link": null
}
],
"outputs": [
{
"name": "width",
"type": "INT",
"slot_index": 0,
"links": [
1,
3
]
},
{
"name": "height",
"type": "INT",
"slot_index": 1,
"links": [
2,
4
]
}
],
"properties": {
"aux_id": "ComfyAssets/ComfyUI-KikoTools",
"ver": "965ad60c74d7f25b1acce890d9c06518e46e6d0b",
"Node name for S&R": "ResolutionCalculator",
"widget_ue_connectable": {}
},
"widgets_values": [
2.5
]
},
{
"id": 6,
"type": "LoadImage",
"pos": [
-250,
430
],
"size": [
274.080078125,
314
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [
{"name": "image", "type": "IMAGE", "link": null},
{"name": "latent", "type": "LATENT", "link": null}
],
"inputs": [],
"outputs": [
{"name": "width", "type": "INT", "links": [1], "slot_index": 0},
{"name": "height", "type": "INT", "links": [2], "slot_index": 1}
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
5
]
},
{
"name": "MASK",
"type": "MASK",
"links": null
}
],
"properties": {},
"widgets_values": [2.0],
"category": "ComfyAssets"
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.40",
"widget_ue_connectable": {},
"Node name for S&R": "LoadImage"
},
"widgets_values": [
"image-2025-06-13-105737.jpg",
"image"
]
},
{
"id": 4,
"type": "Display Int (rgthree)",
"pos": [
420,
360
],
"size": [
210,
88
],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [
{
"dir": 3,
"name": "input",
"type": "INT",
"link": 3
}
],
"outputs": [],
"properties": {
"cnr_id": "rgthree-comfy",
"ver": "1.0.2506081210",
"Node name for S&R": "Display Int (rgthree)",
"widget_ue_connectable": {}
},
"widgets_values": [
""
]
},
{
"id": 5,
"type": "Display Int (rgthree)",
"pos": [
430,
530
],
"size": [
210,
88
],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"dir": 3,
"name": "input",
"type": "INT",
"link": 4
}
],
"outputs": [],
"properties": {
"cnr_id": "rgthree-comfy",
"ver": "1.0.2506081210",
"widget_ue_connectable": {},
"Node name for S&R": "Display Int (rgthree)"
},
"widgets_values": [
""
]
},
{
"id": 2,
"type": "Note",
"pos": [450, 100],
"size": {"0": 400, "1": 200},
"pos": [
-150,
170
],
"size": [
400,
200
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [],
"properties": {"text": "Resolution Calculator Example\n\nThis node calculates upscaled dimensions from:\n- IMAGE tensors (connect from image loaders)\n- LATENT tensors (connect from VAE encode/generation)\n\nUse cases:\n- Calculate target dimensions for upscalers\n- Plan memory usage for large generations\n- Ensure dimensions are divisible by 8\n\nScale factors optimized for SDXL and FLUX models."},
"widgets_values": ["Resolution Calculator Example\n\nThis node calculates upscaled dimensions from:\n- IMAGE tensors (connect from image loaders)\n- LATENT tensors (connect from VAE encode/generation)\n\nUse cases:\n- Calculate target dimensions for upscalers\n- Plan memory usage for large generations\n- Ensure dimensions are divisible by 8\n\nScale factors optimized for SDXL and FLUX models."]
"properties": {
"text": "Resolution Calculator Example\n\nThis node calculates upscaled dimensions from:\n- IMAGE tensors (connect from image loaders)\n- LATENT tensors (connect from VAE encode/generation)\n\nUse cases:\n- Calculate target dimensions for upscalers\n- Plan memory usage for large generations\n- Ensure dimensions are divisible by 8\n\nScale factors optimized for SDXL and FLUX models.",
"widget_ue_connectable": {}
},
"widgets_values": [
"Resolution Calculator Example\n\nThis node calculates upscaled dimensions from:\n- IMAGE tensors (connect from image loaders)\n- LATENT tensors (connect from VAE encode/generation)\n\nUse cases:\n- Calculate target dimensions for upscalers\n- Plan memory usage for large generations\n- Ensure dimensions are divisible by 8\n\nScale factors optimized for SDXL and FLUX models."
],
"color": "#432",
"bgcolor": "#653"
}
],
"links": [
[1, 1, 0, 3, 0, "INT"],
[2, 1, 1, 3, 1, "INT"]
[
1,
1,
0,
3,
0,
"INT"
],
[
2,
1,
1,
3,
1,
"INT"
],
[
3,
1,
0,
4,
0,
"INT"
],
[
4,
1,
1,
5,
0,
"INT"
],
[
5,
6,
0,
1,
0,
"IMAGE"
]
],
"groups": [],
"config": {},
"extra": {},
"extra": {
"ue_links": [],
"ds": {
"scale": 0.7972024500000015,
"offset": [
709.6391289161842,
-90.0127389290854
]
},
"links_added_by_ue": [],
"frontendVersion": "1.21.7",
"VHS_latentpreview": true,
"VHS_latentpreviewrate": 0,
"VHS_MetadataImage": true,
"VHS_KeepIntermediate": true
},
"version": 0.4
}
+435 -215
View File
@@ -1,191 +1,98 @@
{
"id": "972425bd-9910-484d-ad09-f142f534fc61",
"revision": 0,
"last_node_id": 10,
"last_link_id": 10,
"last_link_id": 13,
"nodes": [
{
"id": 1,
"type": "SamplerCombo",
"pos": [100, 100],
"size": [300, 200],
"id": 7,
"type": "CLIPTextEncode",
"pos": [
120,
390
],
"size": [
425.27801513671875,
180.6060791015625
],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 5
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
6
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.40",
"Node name for S&R": "CLIPTextEncode",
"widget_ue_connectable": {}
},
"widgets_values": [
"text, watermark"
]
},
{
"id": 5,
"type": "EmptyLatentImage",
"pos": [
180,
610
],
"size": [
315,
106
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "sampler_name",
"type": "COMBO",
"links": [1],
"shape": 3,
"slot_index": 0
},
{
"name": "scheduler",
"type": "COMBO",
"links": [2],
"shape": 3,
"slot_index": 1
},
{
"name": "steps",
"type": "INT",
"links": [3],
"shape": 3,
"slot_index": 2
},
{
"name": "cfg",
"type": "FLOAT",
"links": [4],
"shape": 3,
"slot_index": 3
}
],
"properties": {
"Node name for S&R": "SamplerCombo"
},
"widgets_values": [
"dpmpp_2m",
"karras",
25,
7.5
],
"title": "Sampler Combo"
},
{
"id": 2,
"type": "CheckpointLoaderSimple",
"pos": [100, 350],
"size": [315, 98],
"flags": {},
"order": 1,
"mode": 0,
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [5],
"shape": 3,
"slot_index": 0
},
{
"name": "CLIP",
"type": "CLIP",
"links": [6, 7],
"shape": 3,
"slot_index": 1
},
{
"name": "VAE",
"type": "VAE",
"links": [8],
"shape": 3,
"slot_index": 2
}
],
"properties": {
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": [
"flux1-dev.safetensors"
]
},
{
"id": 3,
"type": "CLIPTextEncode",
"pos": [450, 100],
"size": [400, 200],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 6
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [9],
"shape": 3,
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"A beautiful sunset over mountains, highly detailed, photorealistic"
],
"title": "Positive Prompt"
},
{
"id": 4,
"type": "CLIPTextEncode",
"pos": [450, 350],
"size": [400, 200],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 7
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [10],
"shape": 3,
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"blurry, low quality, distorted"
],
"title": "Negative Prompt"
},
{
"id": 5,
"type": "EmptyLatentImage",
"pos": [100, 500],
"size": [315, 106],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [11],
"shape": 3,
"slot_index": 0
"slot_index": 0,
"links": [
2
]
}
],
"properties": {
"Node name for S&R": "EmptyLatentImage"
"cnr_id": "comfy-core",
"ver": "0.3.40",
"Node name for S&R": "EmptyLatentImage",
"widget_ue_connectable": {}
},
"widgets_values": [
1024,
1024,
512,
512,
1
]
},
{
"id": 6,
"id": 3,
"type": "KSampler",
"pos": [900, 100],
"size": [315, 262],
"pos": [
863,
186
],
"size": [
315,
571
],
"flags": {},
"order": 5,
"mode": 0,
@@ -193,72 +100,94 @@
{
"name": "model",
"type": "MODEL",
"link": 5
"link": 1
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 9
"link": 4
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 10
"link": 6
},
{
"name": "latent_image",
"type": "LATENT",
"link": 11
},
{
"name": "sampler_name",
"type": "COMBO",
"link": 1
},
{
"name": "scheduler",
"type": "COMBO",
"link": 2
},
{
"name": "steps",
"type": "INT",
"link": 3
"widget": {
"name": "steps"
},
"link": 12
},
{
"name": "cfg",
"type": "FLOAT",
"link": 4
"widget": {
"name": "cfg"
},
"link": 13
},
{
"name": "sampler_name",
"type": "COMBO",
"widget": {
"name": "sampler_name"
},
"link": 10
},
{
"name": "scheduler",
"type": "COMBO",
"widget": {
"name": "scheduler"
},
"link": 11
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [12],
"shape": 3,
"slot_index": 0
"slot_index": 0,
"links": [
7
]
}
],
"properties": {
"Node name for S&R": "KSampler"
"cnr_id": "comfy-core",
"ver": "0.3.40",
"Node name for S&R": "KSampler",
"widget_ue_connectable": {}
},
"widgets_values": [
12345,
555950987049067,
"randomize",
20,
7.0,
8,
"euler",
"normal",
1.0
],
"title": "KSampler (using Sampler Combo)"
1,
""
]
},
{
"id": 7,
"id": 8,
"type": "VAEDecode",
"pos": [1250, 100],
"size": [210, 46],
"pos": [
1209,
188
],
"size": [
210,
46
],
"flags": {},
"order": 6,
"mode": 0,
@@ -266,7 +195,7 @@
{
"name": "samples",
"type": "LATENT",
"link": 12
"link": 7
},
{
"name": "vae",
@@ -278,40 +207,331 @@
{
"name": "IMAGE",
"type": "IMAGE",
"links": [],
"shape": 3,
"slot_index": 0
"slot_index": 0,
"links": [
9
]
}
],
"properties": {
"Node name for S&R": "VAEDecode"
}
"cnr_id": "comfy-core",
"ver": "0.3.40",
"Node name for S&R": "VAEDecode",
"widget_ue_connectable": {}
},
"widgets_values": []
},
{
"id": 9,
"type": "SaveImage",
"pos": [
1451,
189
],
"size": [
210,
270
],
"flags": {},
"order": 7,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 9
}
],
"outputs": [],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.40",
"Node name for S&R": "SaveImage",
"widget_ue_connectable": {}
},
"widgets_values": [
"ComfyUI"
]
},
{
"id": 6,
"type": "CLIPTextEncode",
"pos": [
120,
180
],
"size": [
422.84503173828125,
164.31304931640625
],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 3
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
4
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.40",
"Node name for S&R": "CLIPTextEncode",
"widget_ue_connectable": {}
},
"widgets_values": [
"beautiful scenery nature glass bottle landscape, , purple galaxy bottle,"
]
},
{
"id": 10,
"type": "SamplerCombo",
"pos": [
550,
290
],
"size": [
300,
200
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "sampler_name",
"type": "COMBO",
"slot_index": 0,
"links": [
10
]
},
{
"name": "scheduler",
"type": "COMBO",
"slot_index": 1,
"links": [
11
]
},
{
"name": "steps",
"type": "INT",
"slot_index": 2,
"links": [
12
]
},
{
"name": "cfg",
"type": "FLOAT",
"slot_index": 3,
"links": [
13
]
}
],
"properties": {
"aux_id": "ComfyAssets/ComfyUI-KikoTools",
"ver": "dcf2d679c1a1091c54c2aa8cc04724236723227d",
"widget_ue_connectable": {},
"Node name for S&R": "SamplerCombo"
},
"widgets_values": [
"dpmpp_2m",
"karras",
25,
7.5
]
},
{
"id": 4,
"type": "CheckpointLoaderSimple",
"pos": [
-220,
180
],
"size": [
315,
98
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"slot_index": 0,
"links": [
1
]
},
{
"name": "CLIP",
"type": "CLIP",
"slot_index": 1,
"links": [
3,
5
]
},
{
"name": "VAE",
"type": "VAE",
"slot_index": 2,
"links": [
8
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.40",
"Node name for S&R": "CheckpointLoaderSimple",
"widget_ue_connectable": {}
},
"widgets_values": [
"sdxl_ckpt/realvisxlV40_v40LightningBakedvae.safetensors"
]
}
],
"links": [
[1, 1, 0, 6, 4, "COMBO"],
[2, 1, 1, 6, 5, "COMBO"],
[3, 1, 2, 6, 6, "INT"],
[4, 1, 3, 6, 7, "FLOAT"],
[5, 2, 0, 6, 0, "MODEL"],
[6, 2, 1, 3, 0, "CLIP"],
[7, 2, 1, 4, 0, "CLIP"],
[8, 2, 2, 7, 1, "VAE"],
[9, 3, 0, 6, 1, "CONDITIONING"],
[10, 4, 0, 6, 2, "CONDITIONING"],
[11, 5, 0, 6, 3, "LATENT"],
[12, 6, 0, 7, 0, "LATENT"]
[
1,
4,
0,
3,
0,
"MODEL"
],
[
2,
5,
0,
3,
3,
"LATENT"
],
[
3,
4,
1,
6,
0,
"CLIP"
],
[
4,
6,
0,
3,
1,
"CONDITIONING"
],
[
5,
4,
1,
7,
0,
"CLIP"
],
[
6,
7,
0,
3,
2,
"CONDITIONING"
],
[
7,
3,
0,
8,
0,
"LATENT"
],
[
8,
4,
2,
8,
1,
"VAE"
],
[
9,
8,
0,
9,
0,
"IMAGE"
],
[
10,
10,
0,
3,
6,
"COMBO"
],
[
11,
10,
1,
3,
7,
"COMBO"
],
[
12,
10,
2,
3,
4,
"INT"
],
[
13,
10,
3,
3,
5,
"FLOAT"
]
],
"groups": [],
"config": {},
"extra": {
"ue_links": [],
"links_added_by_ue": [],
"ds": {
"scale": 0.8264462809917355,
"scale": 0.9740024562304554,
"offset": [
-49.66116272043009,
-10.826446280991736
75.10666660323399,
-252.18018113111526
]
}
},
"frontendVersion": "1.21.7",
"VHS_latentpreview": true,
"VHS_latentpreviewrate": 0,
"VHS_MetadataImage": true,
"VHS_KeepIntermediate": true
},
"version": 0.4
}
+488 -253
View File
@@ -1,192 +1,111 @@
{
"last_node_id": 8,
"last_link_id": 7,
"id": "972425bd-9910-484d-ad09-f142f534fc61",
"revision": 0,
"last_node_id": 11,
"last_link_id": 14,
"nodes": [
{
"id": 1,
"type": "SeedHistory",
"id": 7,
"type": "CLIPTextEncode",
"pos": [
100,
100
120,
390
],
"size": {
"0": 280,
"1": 320
"size": [
425.27801513671875,
180.6060791015625
],
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 5
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
6
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.40",
"Node name for S&R": "CLIPTextEncode",
"widget_ue_connectable": {}
},
"widgets_values": [
"text, watermark"
]
},
{
"id": 5,
"type": "EmptyLatentImage",
"pos": [
180,
610
],
"size": [
315,
106
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "seed",
"type": "INT",
"links": [
1
],
"shape": 3
}
],
"properties": {
"Node name for S&R": "SeedHistory"
},
"widgets_values": [
12345
],
"color": "#2a363b",
"bgcolor": "#3f5159"
},
{
"id": 2,
"type": "CheckpointLoaderSimple",
"pos": [
100,
450
],
"size": {
"0": 315,
"1": 98
},
"flags": {},
"order": 1,
"mode": 0,
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"name": "LATENT",
"type": "LATENT",
"slot_index": 0,
"links": [
2
],
"shape": 3
},
{
"name": "CLIP",
"type": "CLIP",
"links": [
3
],
"shape": 3
},
{
"name": "VAE",
"type": "VAE",
"links": [
4
],
"shape": 3
]
}
],
"properties": {
"Node name for S&R": "CheckpointLoaderSimple"
"cnr_id": "comfy-core",
"ver": "0.3.40",
"Node name for S&R": "EmptyLatentImage",
"widget_ue_connectable": {}
},
"widgets_values": [
"sd_xl_base_1.0.safetensors"
512,
512,
1
]
},
{
"id": 3,
"type": "CLIPTextEncode",
"pos": [
450,
100
],
"size": {
"0": 400,
"1": 200
},
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 3
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [
5
],
"shape": 3
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"a beautiful landscape with mountains and lakes, sunset, detailed, photorealistic"
],
"color": "#232",
"bgcolor": "#353"
},
{
"id": 4,
"type": "CLIPTextEncode",
"pos": [
450,
350
],
"size": {
"0": 400,
"1": 200
},
"flags": {},
"order": 3,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 3
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"links": [
6
],
"shape": 3
}
],
"properties": {
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"blurry, low quality, distorted, ugly, deformed"
],
"color": "#322",
"bgcolor": "#533"
},
{
"id": 5,
"type": "KSampler",
"pos": [
900,
100
863,
186
],
"size": [
315,
571
],
"size": {
"0": 315,
"1": 262
},
"flags": {},
"order": 4,
"order": 6,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 2
"link": 1
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 5
"link": 4
},
{
"name": "negative",
@@ -196,84 +115,89 @@
{
"name": "latent_image",
"type": "LATENT",
"link": null
"link": 2
},
{
"name": "seed",
"type": "INT",
"link": 1,
"widget": {
"name": "seed"
}
},
"link": 14
},
{
"name": "steps",
"type": "INT",
"widget": {
"name": "steps"
},
"link": 12
},
{
"name": "cfg",
"type": "FLOAT",
"widget": {
"name": "cfg"
},
"link": 13
},
{
"name": "sampler_name",
"type": "COMBO",
"widget": {
"name": "sampler_name"
},
"link": 10
},
{
"name": "scheduler",
"type": "COMBO",
"widget": {
"name": "scheduler"
},
"link": 11
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"slot_index": 0,
"links": [
7
],
"shape": 3
]
}
],
"properties": {
"Node name for S&R": "KSampler"
"cnr_id": "comfy-core",
"ver": "0.3.40",
"Node name for S&R": "KSampler",
"widget_ue_connectable": {}
},
"widgets_values": [
12345,
231413202715030,
"randomize",
20,
8,
"euler",
"normal",
1
1,
""
]
},
{
"id": 6,
"type": "EmptyLatentImage",
"pos": [
900,
400
],
"size": {
"0": 315,
"1": 106
},
"flags": {},
"order": 5,
"mode": 0,
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"links": [],
"shape": 3
}
],
"properties": {
"Node name for S&R": "EmptyLatentImage"
},
"widgets_values": [
1024,
1024,
1
]
},
{
"id": 7,
"id": 8,
"type": "VAEDecode",
"pos": [
1300,
100
1209,
188
],
"size": [
210,
46
],
"size": {
"0": 210,
"1": 46
},
"flags": {},
"order": 6,
"order": 7,
"mode": 0,
"inputs": [
{
@@ -284,126 +208,437 @@
{
"name": "vae",
"type": "VAE",
"link": 4
"link": 8
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [],
"shape": 3
"slot_index": 0,
"links": [
9
]
}
],
"properties": {
"Node name for S&R": "VAEDecode"
}
"cnr_id": "comfy-core",
"ver": "0.3.40",
"Node name for S&R": "VAEDecode",
"widget_ue_connectable": {}
},
"widgets_values": []
},
{
"id": 8,
"id": 9,
"type": "SaveImage",
"pos": [
1300,
200
1451,
189
],
"size": [
210,
270
],
"size": {
"0": 315,
"1": 270
},
"flags": {},
"order": 7,
"order": 8,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": null
"link": 9
}
],
"outputs": [],
"properties": {
"Node name for S&R": "SaveImage"
"cnr_id": "comfy-core",
"ver": "0.3.40",
"Node name for S&R": "SaveImage",
"widget_ue_connectable": {}
},
"widgets_values": [
"ComfyUI"
]
},
{
"id": 6,
"type": "CLIPTextEncode",
"pos": [
120,
180
],
"size": [
422.84503173828125,
164.31304931640625
],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 3
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
4
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.40",
"Node name for S&R": "CLIPTextEncode",
"widget_ue_connectable": {}
},
"widgets_values": [
"beautiful scenery nature glass bottle landscape, , purple galaxy bottle,"
]
},
{
"id": 4,
"type": "CheckpointLoaderSimple",
"pos": [
-220,
180
],
"size": [
315,
98
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"slot_index": 0,
"links": [
1
]
},
{
"name": "CLIP",
"type": "CLIP",
"slot_index": 1,
"links": [
3,
5
]
},
{
"name": "VAE",
"type": "VAE",
"slot_index": 2,
"links": [
8
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.40",
"Node name for S&R": "CheckpointLoaderSimple",
"widget_ue_connectable": {}
},
"widgets_values": [
"sdxl_ckpt/realvisxlV40_v40LightningBakedvae.safetensors"
]
},
{
"id": 10,
"type": "SamplerCombo",
"pos": [
550,
360
],
"size": [
300,
200
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "sampler_name",
"type": "COMBO",
"slot_index": 0,
"links": [
10
]
},
{
"name": "scheduler",
"type": "COMBO",
"slot_index": 1,
"links": [
11
]
},
{
"name": "steps",
"type": "INT",
"slot_index": 2,
"links": [
12
]
},
{
"name": "cfg",
"type": "FLOAT",
"slot_index": 3,
"links": [
13
]
}
],
"properties": {
"aux_id": "ComfyAssets/ComfyUI-KikoTools",
"ver": "dcf2d679c1a1091c54c2aa8cc04724236723227d",
"Node name for S&R": "SamplerCombo",
"widget_ue_connectable": {}
},
"widgets_values": [
"dpmpp_2m",
"karras",
25,
7.5
]
},
{
"id": 11,
"type": "SeedHistory",
"pos": [
550,
100
],
"size": [
290,
220
],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "seed",
"type": "INT",
"links": [
14
]
}
],
"properties": {
"aux_id": "ComfyAssets/ComfyUI-KikoTools",
"ver": "dcf2d679c1a1091c54c2aa8cc04724236723227d",
"widget_ue_connectable": {},
"Node name for S&R": "SeedHistory"
},
"widgets_values": [
893082183398485,
"randomize",
""
],
"color": "#2a363b",
"bgcolor": "#3f5159",
"hasBeenResized": true,
"seedHistory": [
{
"seed": 893082183398485,
"timestamp": 1750032481153,
"dateString": "6/15/2025, 5:08:01 PM"
},
{
"seed": 267914687236135,
"timestamp": 1750014787315,
"dateString": "6/15/2025, 12:13:07 PM"
},
{
"seed": 267914687236134,
"timestamp": 1750014721305,
"dateString": "6/15/2025, 12:12:01 PM"
},
{
"seed": 267914687236133,
"timestamp": 1750012659402,
"dateString": "6/15/2025, 11:37:39 AM"
},
{
"seed": 267914687236132,
"timestamp": 1750011284415,
"dateString": "6/15/2025, 11:14:44 AM"
},
{
"seed": 267914687236131,
"timestamp": 1750011223416,
"dateString": "6/15/2025, 11:13:43 AM"
},
{
"seed": 267914687236130,
"timestamp": 1750011181407,
"dateString": "6/15/2025, 11:13:01 AM"
},
{
"seed": 267914687236129,
"timestamp": 1750005515384,
"dateString": "6/15/2025, 9:38:35 AM"
},
{
"seed": 267914687236128,
"timestamp": 1750005462384,
"dateString": "6/15/2025, 9:37:42 AM"
},
{
"seed": 267914687236127,
"timestamp": 1750005354713,
"dateString": "6/15/2025, 9:35:54 AM"
}
]
}
],
"links": [
[
1,
1,
0,
5,
4,
"INT"
],
[
2,
2,
0,
5,
3,
0,
"MODEL"
],
[
3,
2,
1,
5,
0,
3,
3,
"LATENT"
],
[
3,
4,
1,
6,
0,
"CLIP"
],
[
4,
2,
2,
6,
0,
3,
1,
"CONDITIONING"
],
[
5,
4,
1,
7,
0,
"CLIP"
],
[
6,
7,
0,
3,
2,
"CONDITIONING"
],
[
7,
3,
0,
8,
0,
"LATENT"
],
[
8,
4,
2,
8,
1,
"VAE"
],
[
5,
9,
8,
0,
9,
0,
"IMAGE"
],
[
10,
10,
0,
3,
0,
5,
7,
"COMBO"
],
[
11,
10,
1,
"CONDITIONING"
3,
8,
"COMBO"
],
[
6,
4,
0,
5,
12,
10,
2,
"CONDITIONING"
3,
5,
"INT"
],
[
7,
5,
13,
10,
3,
3,
6,
"FLOAT"
],
[
14,
11,
0,
7,
0,
"LATENT"
3,
4,
"INT"
]
],
"groups": [],
"config": {},
"extra": {
"ue_links": [],
"links_added_by_ue": [],
"ds": {
"scale": 0.9090909090909091,
"scale": 0.9740024562304554,
"offset": [
-45.45454545454545,
-9.090909090909092
2.9611945935278796,
36.50023864466208
]
},
"info": {
"name": "Seed History Example",
"author": "ComfyUI-KikoTools",
"description": "Example workflow demonstrating the Seed History tool for tracking and managing seed values with an interactive UI.",
"version": "1.0",
"created": "2024-06-14",
"modified": "2024-06-14"
}
"frontendVersion": "1.21.7",
"VHS_latentpreview": true,
"VHS_latentpreviewrate": 0,
"VHS_MetadataImage": true,
"VHS_KeepIntermediate": true
},
"version": 0.4
}
File diff suppressed because it is too large Load Diff
+16
View File
@@ -0,0 +1,16 @@
[project]
name = "kikotools"
description = "Simple tools for ComfyUI"
version = "1.0.1"
license = {file = "LICENSE"}
dependencies = ["# Development dependencies for ComfyUI-KikoTools", "# Testing framework", "pytest>=7.0.0", "pytest-cov>=4.0.0", "pytest-mock>=3.10.0", "# Code quality", "black>=23.0.0", "flake8>=6.0.0", "mypy>=1.0.0", "# Development utilities", "pre-commit>=3.0.0", "# ComfyUI testing (mock dependencies for unit tests)", "torch>=2.0.0", "numpy>=1.24.0", "pillow>=9.0.0"]
[project.urls]
Repository = "https://github.com/ComfyAssets/ComfyUI-KikoTools"
# Used by Comfy Registry https://registry.comfy.org
[tool.comfy]
PublisherId = "kiko9"
DisplayName = "ComfyUI-KikoTools"
Icon = "https://avatars.githubusercontent.com/u/213204677?s=200"
includes = []
+19
View File
@@ -0,0 +1,19 @@
# Development dependencies for ComfyUI-KikoTools
# Testing framework
pytest>=7.0.0
pytest-cov>=4.0.0
pytest-mock>=3.10.0
# Code quality
black>=23.0.0
flake8>=6.0.0
mypy>=1.0.0
# Development utilities
pre-commit>=3.0.0
# ComfyUI testing (mock dependencies for unit tests)
torch>=2.0.0
numpy>=1.24.0
pillow>=9.0.0