From 4fb0aaa4bbc1879dbcbcd315be0cb5b77defd37f Mon Sep 17 00:00:00 2001 From: Immac Date: Sun, 1 Mar 2026 16:38:08 -0600 Subject: [PATCH] Step 1: save plan, clean up old-style node registration and broken tests --- PLAN.md | 58 +++++++++++++++++++++++++++++ src/immac_tools/__init__.py | 40 +------------------- src/immac_tools/forwarding_nodes.py | 5 +-- tests/test_immac_tools.py | 21 ----------- 4 files changed, 61 insertions(+), 63 deletions(-) create mode 100644 PLAN.md delete mode 100644 tests/test_immac_tools.py diff --git a/PLAN.md b/PLAN.md new file mode 100644 index 0000000..c19c8fa --- /dev/null +++ b/PLAN.md @@ -0,0 +1,58 @@ +# Migration Plan: Comfy-Org/ComfyUI-React-Extension-Template + +Repo is being updated to match the `Comfy-Org/ComfyUI-React-Extension-Template` pattern, +adding a React/TypeScript Style Mixer UI alongside the existing custom nodes. + +--- + +## Steps + +### ✅ Step 0 — Save this plan (first order of business) + +### Step 1 — Clean up the Python layer ← *currently here* +- [x] Save plan to `PLAN.md` +- [x] Delete broken tests (`tests/test_immac_tools.py` — asserts old-style class attributes that don't exist on `io.ComfyNode`) +- [x] Remove dead dict registration from `src/immac_tools/__init__.py` (`NODE_CLASS_MAPPINGS`, `NODE_DISPLAY_NAME_MAPPINGS`, `WEB_DIRECTORY`) +- [x] Remove unused `ExampleForwardingExtension` from `src/immac_tools/forwarding_nodes.py` + +### Step 2 — Rewrite root `__init__.py` to match the template pattern +- Remove `WEB_DIRECTORY` re-export +- Set `NODE_CLASS_MAPPINGS = {}` (nodes registered via `comfy_entrypoint`) +- Wire `comfy_entrypoint` to `src/immac_tools/nodes.py` +- Register aiohttp static routes to serve `dist/immac_style_mixer/` at `/immac_style_mixer/` +- Register `nodes.EXTENSION_WEB_DIRS[project_name]` using `comfy_config` (with fallback) + +### Step 3 — Add Style Mixer REST API (`src/immac_tools/api.py`) +- Load/save `style_mixer_data.json` in workspace root +- Schema: `{ "styles": [{ "id", "name", "value", "favorite" }], "mixes": [{ "id", "name", "styles": [{ "style_id", "weight", "enabled" }], "favorite" }], "current_mix_id": null }` +- Routes (registered from `__init__.py`): + - `GET /immac_style_mixer/api/data` → return full data blob + - `POST /immac_style_mixer/api/data` → replace full data blob + +### Step 4 — Update `pyproject.toml` +- Change `includes = []` → `includes = ["dist/"]` +- Remove `[build-system]` / `[tool.setuptools]` blocks (not needed; ComfyUI loads directly) + +### Step 5 — Scaffold `ui/` (React + TypeScript + Vite) +- `ui/package.json` — deps: `react`, `react-dom`, `vite`, `@vitejs/plugin-react`, `typescript`, `@comfyorg/comfyui-frontend-types`; build output → `../dist/immac_style_mixer` +- `ui/vite.config.ts` — output `../dist/immac_style_mixer` +- `ui/tsconfig.json` + `ui/tsconfig.node.json` +- `ui/src/main.tsx` — registers ComfyUI extension; mounts panel as a sidebar tab via `app.extensionManager.registerSidebarTab` + +### Step 6 — Build UI components +- `hooks/useStyleMixerData.ts` — fetch/save via `/immac_style_mixer/api/data` +- `components/StyleCard.tsx` — name (editable), value, favorite star, delete +- `components/MixCard.tsx` — name, radio to activate, list of style entries (name + weight slider + ON/OFF toggle + remove), favorite star +- `components/StyleGallery.tsx` — grid of all styles; "Add Style" inline form +- `components/StyleMixerPanel.tsx` — top-level: **Current Mix** / **Mixes** / **Styles** sections + +### Step 7 — GitHub Actions CI +- `.github/workflows/react-build.yml` — on push to `main`: `npm ci` + `npm run build` inside `ui/` + +--- + +## Key Decisions +- Single `POST /immac_style_mixer/api/data` endpoint for all persistence (minimal backend; expand later) +- Sidebar tab (not floating window) for the panel +- `dist/` tracked in git — required for registry publishing via `includes = ["dist/"]` +- Styles are user-defined strings (prompt text snippets) diff --git a/src/immac_tools/__init__.py b/src/immac_tools/__init__.py index f57bff5..9886b19 100644 --- a/src/immac_tools/__init__.py +++ b/src/immac_tools/__init__.py @@ -1,40 +1,4 @@ -"""ComfyUI-ImmacTools package exports used by ComfyUI. +"""ComfyUI-ImmacTools node package. -This module exposes the node registration mappings and the `WEB_DIRECTORY` -constant expected by ComfyUI web extensions. +Node registration is handled via comfy_entrypoint() in nodes.py. """ -from .nodes import ConcatenateSigmasNode, SpliceSigmasAtNode, ResampleSigmas, SkipEveryNthImages, MatchContrastNode -from .forwarding_nodes import ForwardAnyNode, ForwardConditioningNode, ForwardModelNode - -# Mapping from node_id to node class -NODE_CLASS_MAPPINGS: dict[str, type] = { - "ConcatenateSigmasImmacTools": ConcatenateSigmasNode, - "SpliceSigmasAtImmacTools": SpliceSigmasAtNode, - "ResampleSigmasImmacTools": ResampleSigmas, - "SkipEveryNthImagesImmacTools": SkipEveryNthImages, - "MatchContrastImmacTools": MatchContrastNode, - "ForwardAnyImmacTools": ForwardAnyNode, - "ForwardConditioningImmacTools": ForwardConditioningNode, - "ForwardModelImmacTools": ForwardModelNode, -} - -# Mapping from node_id to human readable display name -NODE_DISPLAY_NAME_MAPPINGS: dict[str, str] = { - "ConcatenateSigmasImmacTools": "Concatenate Sigmas Node", - "SpliceSigmasAtImmacTools": "Splice Sigmas At Node", - "ResampleSigmasImmacTools": "Resample Sigmas", - "SkipEveryNthImagesImmacTools": "Skip Every Nth Image", - "MatchContrastImmacTools": "Match Contrast", - "ForwardAnyImmacTools": "Forward Any", - "ForwardConditioningImmacTools": "Forward Conditioning", - "ForwardModelImmacTools": "Forward Model", -} - -# ComfyUI expects this for web extensions -WEB_DIRECTORY = "./web" - -__all__ = [ - "NODE_CLASS_MAPPINGS", - "NODE_DISPLAY_NAME_MAPPINGS", - "WEB_DIRECTORY", -] diff --git a/src/immac_tools/forwarding_nodes.py b/src/immac_tools/forwarding_nodes.py index 55bf83c..fbf4eda 100644 --- a/src/immac_tools/forwarding_nodes.py +++ b/src/immac_tools/forwarding_nodes.py @@ -109,10 +109,7 @@ class ForwardModelNode(io.ComfyNode): return io.NodeOutput(model) -class ExampleForwardingExtension(ComfyExtension): - @override - async def get_node_list(self) -> list[type[io.ComfyNode]]: - return [ForwardAnyNode, ForwardConditioningNode, ForwardModelNode] + diff --git a/tests/test_immac_tools.py b/tests/test_immac_tools.py deleted file mode 100644 index 3c049b5..0000000 --- a/tests/test_immac_tools.py +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env python - -"""Tests for `immac_tools` package.""" - -import pytest -from src.immac_tools.nodes import ConcatenateSigmasNode - -@pytest.fixture -def example_node(): - """Fixture to create an Example node instance.""" - return ConcatenateSigmasNode() - -def test_example_node_initialization(example_node): - """Test that the node can be instantiated.""" - assert isinstance(example_node, ConcatenateSigmasNode) - -def test_return_types(): - """Test the node's metadata.""" - assert ConcatenateSigmasNode.RETURN_TYPES == ("IMAGE",) - assert ConcatenateSigmasNode.FUNCTION == "test" - assert ConcatenateSigmasNode.CATEGORY == "Example"