aliensmn commited on
Commit
0997c23
·
verified ·
1 Parent(s): 92a7bc2

Mirror from https://github.com/sammykumar/ComfyUI-SwissArmyKnife

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .dockerignore +14 -0
  2. .editorconfig +21 -0
  3. .env.example +15 -0
  4. .github/workflows/ci.yml +50 -0
  5. .github/workflows/publish-to-registry.yml +53 -0
  6. .gitignore +159 -0
  7. .pre-commit-config.yaml +10 -0
  8. AGENTS.md +878 -0
  9. CONTRIBUTING.md +320 -0
  10. Dockerfile +55 -0
  11. LICENSE +675 -0
  12. MANIFEST.in +25 -0
  13. README.md +386 -0
  14. __init__.py +106 -0
  15. debug_civitai.py +141 -0
  16. docker-compose.yml +21 -0
  17. docs/CONSOLIDATION_SUMMARY.md +289 -0
  18. docs/DOCUMENTATION_REORGANIZATION.md +297 -0
  19. docs/IMPLEMENTATION_STATUS.md +136 -0
  20. docs/README.md +162 -0
  21. docs/examples/README.md +46 -0
  22. docs/examples/WORKFLOW_DEMO.md +46 -0
  23. docs/examples/example_workflow.json +89 -0
  24. docs/features/ASYNC_EVENT_LOOP_FIX.md +102 -0
  25. docs/features/CHANGE_CLOTHING_COLOR_FEATURE.md +49 -0
  26. docs/features/CLOTHING_TEXT_EXCLUSION.md +77 -0
  27. docs/features/CONFIGURABLE_OPTIONS_GUIDE.md +149 -0
  28. docs/features/CONTROL_PANEL_CHANGES.md +70 -0
  29. docs/features/DECISIVENESS_IMPROVEMENTS.md +83 -0
  30. docs/features/JAVASCRIPT_IMPROVEMENTS.md +320 -0
  31. docs/features/JSON_OUTPUT_FORMAT.md +246 -0
  32. docs/features/ND_SUPER_NODES_FORK_SUMMARY.md +384 -0
  33. docs/features/ND_SUPER_NODES_UPDATE_REMOVAL.md +117 -0
  34. docs/features/README.md +85 -0
  35. docs/features/RESTART_BUTTON.md +73 -0
  36. docs/features/TWERKING_ACTION_REPLACEMENT.md +92 -0
  37. docs/infrastructure/TEMP_DIRECTORY_UTILS.md +147 -0
  38. docs/infrastructure/build-deploy/GET_VERSION_IMPORT_FIX.md +62 -0
  39. docs/infrastructure/build-deploy/PUBLISHING_WORKFLOW.md +190 -0
  40. docs/infrastructure/build-deploy/PYTHON_PACKAGE_BUILD_FIX.md +87 -0
  41. docs/infrastructure/build-deploy/README.md +69 -0
  42. docs/infrastructure/caching/CACHE_BUSTING_SUMMARY.md +179 -0
  43. docs/infrastructure/caching/CACHE_OPTIMIZATION_FIX.md +81 -0
  44. docs/infrastructure/caching/CACHE_VERIFICATION_OCTOBER_2025.md +272 -0
  45. docs/infrastructure/caching/CACHE_VERIFICATION_SUMMARY.md +79 -0
  46. docs/infrastructure/caching/CACHING.md +162 -0
  47. docs/infrastructure/caching/README.md +68 -0
  48. docs/infrastructure/debug/DEBUG_MODE_IMPLEMENTATION.md +288 -0
  49. docs/infrastructure/debug/README.md +81 -0
  50. docs/infrastructure/debug/UNIFIED_DEBUG_SYSTEM.md +293 -0
.dockerignore ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .git
2
+ .github
3
+ .vscode
4
+ .env
5
+ *.md
6
+ ui-react_backup
7
+ web/node_modules
8
+ docs
9
+ *.pyc
10
+ __pycache__
11
+ .pytest_cache
12
+ .coverage
13
+ .mypy_cache
14
+ .ruff_cache
.editorconfig ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # http://editorconfig.org
2
+
3
+ root = true
4
+
5
+ [*]
6
+ indent_style = space
7
+ indent_size = 4
8
+ trim_trailing_whitespace = true
9
+ insert_final_newline = true
10
+ charset = utf-8
11
+ end_of_line = lf
12
+
13
+ [*.bat]
14
+ indent_style = tab
15
+ end_of_line = crlf
16
+
17
+ [LICENSE]
18
+ insert_final_newline = false
19
+
20
+ [Makefile]
21
+ indent_style = tab
.env.example ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ComfyUI-SwissArmyKnife Environment Variables
2
+ # Copy this file to .env and fill in your actual API keys
3
+
4
+ # Debug Mode (optional)
5
+ # Set to "true" to enable verbose debug logging in both Python and JavaScript
6
+ # Default: false
7
+ DEBUG=false
8
+
9
+ # Google Gemini API Key
10
+ # Get your API key from: https://aistudio.google.com/app/apikey
11
+ GEMINI_API_KEY=YOUR_GEMINI_API_KEY_HERE
12
+
13
+ # Optional: ComfyUI Registry Access Token (for publishing)
14
+ # Only needed if you plan to publish to ComfyUI Registry
15
+ REGISTRY_ACCESS_TOKEN=YOUR_REGISTRY_TOKEN_HERE
.github/workflows/ci.yml ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Code Quality Checks
2
+
3
+ on:
4
+ push:
5
+ branches: [master, develop]
6
+ pull_request:
7
+ branches: [master, develop]
8
+
9
+ jobs:
10
+ quality-checks:
11
+ name: Python Code Quality
12
+ runs-on: ubuntu-latest
13
+
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Set up Python 3.11
18
+ uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.11"
21
+
22
+ - name: Install system dependencies
23
+ run: |
24
+ sudo apt-get update
25
+ sudo apt-get install -y ffmpeg
26
+
27
+ - name: Install Python dependencies
28
+ run: |
29
+ python -m pip install --upgrade pip
30
+ pip install -e .
31
+ pip install ruff pytest
32
+
33
+ - name: Lint with ruff
34
+ run: ruff check .
35
+
36
+ - name: Test Python imports and node loading
37
+ run: |
38
+ python -c "from nodes.nodes import NODE_CLASS_MAPPINGS; print('✓ Custom nodes loaded successfully:', list(NODE_CLASS_MAPPINGS.keys()))"
39
+
40
+ - name: Check pyproject.toml validity
41
+ run: |
42
+ python -c "
43
+ import tomllib
44
+ with open('pyproject.toml', 'rb') as f:
45
+ config = tomllib.load(f)
46
+ assert 'project' in config, 'Missing project section'
47
+ assert 'name' in config['project'], 'Missing project name'
48
+ assert 'version' in config['project'], 'Missing project version'
49
+ print('✓ pyproject.toml is valid')
50
+ "
.github/workflows/publish-to-registry.yml ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Publish to ComfyUI Registry
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ push:
6
+ branches:
7
+ - master
8
+ paths:
9
+ - "pyproject.toml"
10
+
11
+ jobs:
12
+ publish-node:
13
+ name: Publish Custom Node to ComfyUI Registry
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - name: Check out code
17
+ uses: actions/checkout@v4
18
+ with:
19
+ fetch-depth: 0 # Fetch full history for tagging
20
+
21
+ - name: Extract version from pyproject.toml
22
+ id: get_version
23
+ run: |
24
+ VERSION=$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/')
25
+ echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
26
+ echo "Extracted version: $VERSION"
27
+
28
+ - name: Check if tag already exists
29
+ id: check_tag
30
+ run: |
31
+ if git tag | grep -q "^v${{ steps.get_version.outputs.VERSION }}$"; then
32
+ echo "Tag v${{ steps.get_version.outputs.VERSION }} already exists"
33
+ echo "TAG_EXISTS=true" >> $GITHUB_OUTPUT
34
+ else
35
+ echo "Tag v${{ steps.get_version.outputs.VERSION }} does not exist"
36
+ echo "TAG_EXISTS=false" >> $GITHUB_OUTPUT
37
+ fi
38
+
39
+ - name: Publish Custom Node to Registry
40
+ uses: Comfy-Org/publish-node-action@main
41
+ with:
42
+ personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
43
+
44
+ - name: Create and push tag
45
+ if: steps.check_tag.outputs.TAG_EXISTS == 'false'
46
+ run: |
47
+ git config user.name "GitHub Actions"
48
+ git config user.email "actions@github.com"
49
+ git tag -a "v${{ steps.get_version.outputs.VERSION }}" -m "Release version ${{ steps.get_version.outputs.VERSION }}"
50
+ git push origin "v${{ steps.get_version.outputs.VERSION }}"
51
+ echo "Created and pushed tag: v${{ steps.get_version.outputs.VERSION }}"
52
+ env:
53
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
.gitignore ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # OSX useful to ignore
7
+ *.DS_Store
8
+ .AppleDouble
9
+ .LSOverride
10
+
11
+ # Thumbnails
12
+ ._*
13
+
14
+ # Files that might appear in the root of a volume
15
+ .DocumentRevisions-V100
16
+ .fseventsd
17
+ .Spotlight-V100
18
+ .TemporaryItems
19
+ .Trashes
20
+ .VolumeIcon.icns
21
+ .com.apple.timemachine.donotpresent
22
+
23
+ # Directories potentially created on remote AFP share
24
+ .AppleDB
25
+ .AppleDesktop
26
+ Network Trash Folder
27
+ Temporary Items
28
+ .apdisk
29
+
30
+ # C extensions
31
+ *.so
32
+
33
+ # Distribution / packaging
34
+ .Python
35
+ env/
36
+ venv/
37
+ build/
38
+ develop-eggs/
39
+ dist/
40
+ downloads/
41
+ eggs/
42
+ .eggs/
43
+ lib/
44
+ lib64/
45
+ parts/
46
+ sdist/
47
+ var/
48
+ *.egg-info/
49
+ .installed.cfg
50
+ *.egg
51
+
52
+ # PyInstaller
53
+ # Usually these files are written by a python script from a template
54
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
55
+ *.manifest
56
+ *.spec
57
+
58
+ # Installer logs
59
+ pip-log.txt
60
+ pip-delete-this-directory.txt
61
+
62
+ # Unit test / coverage reports
63
+ htmlcov/
64
+ .tox/
65
+ .coverage
66
+ .coverage.*
67
+ .cache
68
+ nosetests.xml
69
+ coverage.xml
70
+ *,cover
71
+ .hypothesis/
72
+ .pytest_cache/
73
+
74
+ # Translations
75
+ *.mo
76
+ *.pot
77
+
78
+ # Django stuff:
79
+ *.log
80
+
81
+ # Sphinx documentation
82
+ docs/_build/
83
+
84
+ # IntelliJ Idea
85
+ .idea
86
+ *.iml
87
+ *.ipr
88
+ *.iws
89
+
90
+ # PyBuilder
91
+ target/
92
+
93
+ # Cookiecutter
94
+ output/
95
+ python_boilerplate/
96
+ cookiecutter-pypackage-env/
97
+
98
+ # vscode settings
99
+ .history/
100
+ *.code-workspace
101
+
102
+ # Frontend extension
103
+ node_modules/
104
+ node_modules
105
+ .env
106
+ .env.local
107
+ .env.development.local
108
+ .env.test.local
109
+ .env.production.local
110
+ npm-debug.log*
111
+ yarn-debug.log*
112
+ yarn-error.log*
113
+ node.zip
114
+ .vscode/
115
+ .claude/
116
+
117
+ # Dev container and development files
118
+ .devcontainer/.env
119
+ temp/
120
+ input/
121
+ output/
122
+ models/
123
+ .ruff_cache/
124
+
125
+ # Gemini description cache
126
+ cache/
127
+
128
+ # OS and editor files
129
+ .DS_Store
130
+ Thumbs.db
131
+ *.swp
132
+ *.swo
133
+ *~
134
+
135
+ # Environment variables and API keys - SECURITY
136
+ .env
137
+ .env.local
138
+ .env.development.local
139
+ .env.test.local
140
+ .env.production.local
141
+
142
+ # API keys and secrets - SECURITY
143
+ *.key
144
+ *.pem
145
+ secrets.json
146
+ config.json
147
+ api_keys.txt
148
+ *_secrets.*
149
+
150
+ # Cache directories
151
+ cache/
152
+ .cache/
153
+
154
+ # Cache busting files
155
+ cache_info.json
156
+
157
+ # ComfyUI Local
158
+ .comfyui/
159
+ .comfyui-user/
.pre-commit-config.yaml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ # Ruff version.
4
+ rev: v0.4.9
5
+ hooks:
6
+ # Run the linter.
7
+ - id: ruff
8
+ args: [ --fix ]
9
+ # Run the formatter.
10
+ - id: ruff-format
AGENTS.md ADDED
@@ -0,0 +1,878 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ComfyUI-SwissArmyKnife - ComfyUI Extension Development Guide
2
+
3
+ **ALWAYS reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.**
4
+
5
+ ## Official ComfyUI Documentation
6
+
7
+ For technical implementation details, reference these official ComfyUI custom node development guides:
8
+
9
+ - **Backend (Python) Development**: https://docs.comfy.org/custom-nodes/backend/server_overview
10
+ - **Web Extension (JavaScript) Development**: https://docs.comfy.org/custom-nodes/js/javascript_overview
11
+ - **Lite Graph (ComfyUi is built on top of Lite Graph)**:https://github.com/jagenjo/litegraph.js/tree/master
12
+
13
+ _Note: These are the official JavaScript widget docs, not React-based extensions._
14
+
15
+ ## Project Overview
16
+
17
+ ComfyUI-SwissArmyKnife is a ComfyUI extension that consists of two essential components that work together:
18
+
19
+ ### Backend (Python Custom Nodes)
20
+
21
+ - Python custom nodes in `nodes/*.py` for Gemini AI video analysis and processing
22
+ - Core business logic and AI integration
23
+ - Requires ComfyUI server restart when modified
24
+
25
+ ### Web Extension (JavaScript Widgets)
26
+
27
+ - Plain JavaScript widgets in `./web/js/` for enhanced ComfyUI interaction
28
+ - UI components and client-side functionality
29
+ - Requires browser cache refresh when modified
30
+
31
+ ### Additional Components
32
+
33
+ - ~~React/TypeScript UI extension with internationalization~~ **DISABLED FOR NOW**
34
+ - GitHub Actions for automated building and publishing
35
+ - Playwright tests in `./web/tests/` for testing against hosted ComfyUI server
36
+ - Documentation in `docs/` directory - organized into categorized folders (see Documentation Organization section)
37
+
38
+ **IMPORTANT**: Both backend and web extension components are required for the custom node to function properly. Changes to backend Python files require restarting the ComfyUI server, while changes to web JavaScript files require refreshing the browser cache.
39
+
40
+ **DOCUMENTATION REQUIREMENT**: All documentation, guides, troubleshooting notes, implementation details, and technical specifications must be added to the appropriate folder in the `docs/` directory. The documentation is organized by category - see the "Documentation Organization" section below for the proper folder structure. Never document directly in code comments when a separate documentation file would be more appropriate. Always attempt to update documentation for existing markdown files before creating new ones.
41
+
42
+ **Note: The React UI component (`ui-react_backup/`) is currently disabled and not in active development.**
43
+
44
+ ## Documentation Organization
45
+
46
+ **All project documentation is organized in a hierarchical folder structure:**
47
+
48
+ ```
49
+ docs/
50
+ ├── README.md # Main documentation index and navigation
51
+ ├── IMPLEMENTATION_STATUS.md # Overall project status
52
+ ├── DOCUMENTATION_REORGANIZATION.md # Documentation structure guide
53
+
54
+ ├── nodes/ # Node-specific documentation
55
+ │ ├── video-preview/ # Video Preview node (6 files + README)
56
+ │ ├── video-metadata/ # Video Metadata node (4 files + README)
57
+ │ ├── media-describe/ # Gemini AI Media Description (6 files + README)
58
+ │ ├── lora-loader/ # LoRA Loader node (14 files + README)
59
+ │ └── reddit-media/ # Reddit Media Extraction (6 files + README)
60
+
61
+ ├── infrastructure/ # Infrastructure & system components
62
+ │ ├── caching/ # Caching system (6 files + README)
63
+ │ ├── debug/ # Debug & logging (2 files + README)
64
+ │ ├── docker/ # Docker setup (2 files + README)
65
+ │ └── build-deploy/ # Build & deployment (3 files + README)
66
+
67
+ ├── integrations/ # External service integrations
68
+ │ └── civitai/ # CivitAI API integration (3 files + README)
69
+
70
+ ├── ui-widgets/ # UI widget documentation (10 files + README)
71
+ ├── features/ # Feature implementations (13 files + README)
72
+ └── examples/ # Example workflows (3 files + README)
73
+ ```
74
+
75
+ ### Documentation Rules
76
+
77
+ 1. **Node-specific docs** → `docs/nodes/[node-name]/`
78
+ 2. **Infrastructure docs** → `docs/infrastructure/[category]/`
79
+ 3. **Integration docs** → `docs/integrations/[service]/`
80
+ 4. **Widget docs** → `docs/ui-widgets/`
81
+ 5. **Feature docs** → `docs/features/`
82
+ 6. **Examples** → `docs/examples/`
83
+
84
+ ### Finding Documentation
85
+
86
+ - **Start here**: `docs/README.md` - Main index with links to all categories
87
+ - **Category indexes**: Each folder has a `README.md` listing all files
88
+ - **By node**: `docs/nodes/[node-name]/README.md`
89
+ - **By topic**: Browse appropriate category folder
90
+
91
+ ## Working Effectively
92
+
93
+ ### Virtual Environment Activation
94
+
95
+ **CRITICAL**: Always activate the virtual environment before running any Python commands:
96
+
97
+ ```bash
98
+ # Activate virtual environment (REQUIRED for all Python operations)
99
+ source /Users/samkumar/Development/dev-lab-hq/ai-image-hub/apps/comfyui-swiss-army-knife/.venv/bin/activate
100
+
101
+ # Or use relative path if in project root:
102
+ source .venv/bin/activate
103
+
104
+ # Verify activation (you should see (.venv) in your prompt)
105
+ which python3 # Should show path inside .venv directory
106
+ ```
107
+
108
+ **IMPORTANT**: Run the activation command before:
109
+
110
+ - Installing Python packages (`pip3 install`)
111
+ - Running Python scripts or commands
112
+ - Running tests (`pytest`)
113
+ - Linting Python code (`ruff check`)
114
+ - Any other Python-related terminal operations
115
+
116
+ ### Essential System Dependencies
117
+
118
+ Install these system dependencies first:
119
+
120
+ ```bash
121
+ # FFmpeg is REQUIRED for video processing functionality
122
+ sudo apt-get update && sudo apt-get install -y ffmpeg
123
+
124
+ # Verify installation
125
+ ffmpeg -version # Should show version 6.1.1 or newer
126
+ ```
127
+
128
+ ### Bootstrap React UI Development _(DISABLED)_
129
+
130
+ **⚠️ The React UI component is currently disabled and not in active development.**
131
+
132
+ ```bash
133
+ # THESE COMMANDS ARE CURRENTLY DISABLED
134
+ # Navigate to React UI directory
135
+ # cd ui-react_backup/ui
136
+
137
+ # Install Node.js dependencies - takes ~40 seconds
138
+ # npm install # NEVER CANCEL: Takes 40 seconds. Set timeout to 60+ seconds.
139
+
140
+ # Build React extension - takes ~5 seconds
141
+ # npm run build # NEVER CANCEL: Takes 5 seconds. Set timeout to 30+ seconds.
142
+ ```
143
+
144
+ ### Bootstrap Python Development
145
+
146
+ ```bash
147
+ # ALWAYS activate virtual environment first
148
+ source .venv/bin/activate
149
+
150
+ # Install Python package and dependencies
151
+ pip3 install -e . # Takes ~12 seconds for basic dependencies
152
+
153
+ # Install essential Python dependencies for full functionality
154
+ # NEVER CANCEL: Takes 2-3 minutes for torch/opencv. Set timeout to 300+ seconds.
155
+ pip3 install torch opencv-python
156
+
157
+ # Install development tools
158
+ pip3 install pytest mypy coverage ruff pre-commit
159
+
160
+ # Verify Python modules work
161
+ python3 -c "from nodes.nodes import NODE_CLASS_MAPPINGS; print('Available nodes:', list(NODE_CLASS_MAPPINGS.keys()))"
162
+ # Should output: Available nodes: ['GeminiUtilVideoDescribe']
163
+ ```
164
+
165
+ ## Development Workflows
166
+
167
+ ### Documentation Workflow
168
+
169
+ **Documentation is now organized by category. Always place documentation in the appropriate folder:**
170
+
171
+ ```bash
172
+ # Documentation structure
173
+ docs/
174
+ ├── README.md # Main documentation index
175
+ ├── IMPLEMENTATION_STATUS.md # Overall project status
176
+ ├── nodes/ # Node-specific documentation
177
+ │ ├── video-preview/ # Video Preview node docs
178
+ │ ├── video-metadata/ # Video Metadata node docs
179
+ │ ├── media-describe/ # Gemini AI Media Description docs
180
+ │ ├── lora-loader/ # LoRA Loader node docs
181
+ │ └── reddit-media/ # Reddit Media Extraction docs
182
+ ├── infrastructure/ # Infrastructure components
183
+ │ ├── caching/ # Caching system docs
184
+ │ ├── debug/ # Debug & logging docs
185
+ │ ├── docker/ # Docker setup docs
186
+ │ └── build-deploy/ # Build & deployment docs
187
+ ├── integrations/ # External service integrations
188
+ │ └── civitai/ # CivitAI API integration docs
189
+ ├── ui-widgets/ # UI widget documentation
190
+ ├── features/ # Feature implementations
191
+ └── examples/ # Example workflows
192
+ ```
193
+
194
+ **Adding New Documentation:**
195
+
196
+ ```bash
197
+ # For node-specific documentation
198
+ touch docs/nodes/[node-name]/NEW_FEATURE.md
199
+
200
+ # For infrastructure documentation
201
+ touch docs/infrastructure/[category]/NEW_SYSTEM.md
202
+
203
+ # For UI widgets
204
+ touch docs/ui-widgets/NEW_WIDGET_IMPLEMENTATION.md
205
+
206
+ # For features
207
+ touch docs/features/NEW_FEATURE_GUIDE.md
208
+
209
+ # For integrations
210
+ touch docs/integrations/[service]/NEW_INTEGRATION.md
211
+ ```
212
+
213
+ **Documentation file naming convention:**
214
+
215
+ - Use ALL_CAPS with underscores
216
+ - Be descriptive: `SEED_WIDGET_IMPLEMENTATION.md`
217
+ - Include purpose: `TROUBLESHOOTING_`, `GUIDE_`, `IMPLEMENTATION_`, `_FIX`
218
+ - Node docs go in `docs/nodes/[node-name]/`
219
+ - Infrastructure docs go in `docs/infrastructure/[category]/`
220
+
221
+ **CRITICAL**: Whenever you implement a new feature, fix a bug, or solve a technical problem:
222
+
223
+ 1. Identify the correct documentation folder:
224
+ - Node changes → `docs/nodes/[node-name]/`
225
+ - System changes → `docs/infrastructure/[category]/`
226
+ - Widget changes → `docs/ui-widgets/`
227
+ - Feature additions → `docs/features/`
228
+ - Integration work → `docs/integrations/[service]/`
229
+ 2. Create documentation file with descriptive name
230
+ 3. Include implementation details, gotchas, and future considerations
231
+ 4. Update the folder's `README.md` index if needed
232
+ 5. Reference the documentation file in commit messages
233
+ 6. Cross-reference related documentation in other folders
234
+
235
+ ### React UI Development _(DISABLED)_
236
+
237
+ **⚠️ The React UI component is currently disabled and not in active development.**
238
+
239
+ ```bash
240
+ # THESE COMMANDS ARE CURRENTLY DISABLED
241
+ # cd ui-react_backup/ui
242
+
243
+ # Development with auto-reload (watches for changes)
244
+ # npm run watch
245
+
246
+ # Build for production
247
+ # npm run build # NEVER CANCEL: Takes 5 seconds. Set timeout to 30+ seconds.
248
+
249
+ # TypeScript type checking
250
+ # npm run typecheck
251
+ ```
252
+
253
+ ### Backend (Python) Development
254
+
255
+ ```bash
256
+ # ALWAYS activate virtual environment first
257
+ source .venv/bin/activate
258
+
259
+ # Import and test Python nodes
260
+ python3 -c "from nodes.nodes import NODE_CLASS_MAPPINGS; print(list(NODE_CLASS_MAPPINGS.keys()))"
261
+
262
+ # Run Python linting (fast, < 1 second)
263
+ ruff check .
264
+
265
+ # Fix auto-fixable linting issues
266
+ ruff check --fix .
267
+ ```
268
+
269
+ ### Web Extension (JavaScript) Development
270
+
271
+ ```bash
272
+ # JavaScript widgets are located in ./web/js/
273
+ # No build step required - plain JavaScript files
274
+
275
+ # Verify web extension files exist
276
+ ls -la web/js/gemini_widgets.js
277
+ ls -la web/css/gemini_widgets.css
278
+
279
+ # After making changes to JavaScript widgets:
280
+ # 1. No compilation needed (plain JS)
281
+ # 2. Browser cache refresh required for changes to take effect
282
+ ```
283
+
284
+ ## Testing
285
+
286
+ ### Backend (Python) Testing
287
+
288
+ ```bash
289
+ # ALWAYS activate virtual environment first
290
+ source .venv/bin/activate
291
+
292
+ # Run pytest (currently no tests exist)
293
+ pytest # NEVER CANCEL: Takes < 30 seconds. Set timeout to 60+ seconds.
294
+ # Expected: "no tests ran" - this is normal, no tests exist yet
295
+
296
+ # When adding tests, create them in a tests/ directory
297
+ ```
298
+
299
+ ### Web Extension Testing
300
+
301
+ ```bash
302
+ # Playwright tests for testing against hosted ComfyUI server
303
+ cd web/tests/
304
+
305
+ # Install Playwright dependencies (if not already installed)
306
+ npm install
307
+
308
+ # Run Playwright tests against hosted ComfyUI server
309
+ npm test
310
+
311
+ # Note: Tests require a running ComfyUI server with the custom node installed
312
+ ```
313
+
314
+ ### React UI Testing _(DISABLED)_
315
+
316
+ **⚠️ The React UI component is currently disabled and not in active development.**
317
+
318
+ ```bash
319
+ # THESE COMMANDS ARE CURRENTLY DISABLED
320
+ # cd ui-react_backup/ui
321
+
322
+ # This command WILL FAIL with ES module errors
323
+ # npm test
324
+ # Error: "Jest encountered an unexpected token" - this is a known issue
325
+
326
+ # To add working tests, fix jest.config.js ES module configuration first
327
+ ```
328
+
329
+ ## Linting and Code Quality
330
+
331
+ ### Python Linting (Works)
332
+
333
+ ```bash
334
+ # ALWAYS activate virtual environment first
335
+ source .venv/bin/activate
336
+
337
+ # Fast linting check (< 1 second)
338
+ ruff check .
339
+
340
+ # Fix automatically fixable issues
341
+ ruff check --fix .
342
+
343
+ # Note: Some unused import warnings are expected and can be ignored
344
+ # The code functions correctly despite these warnings
345
+ ```
346
+
347
+ ### React UI Linting _(DISABLED)_
348
+
349
+ **⚠️ The React UI component is currently disabled and not in active development.**
350
+
351
+ ```bash
352
+ # THESE COMMANDS ARE CURRENTLY DISABLED
353
+ # cd ui-react_backup/ui
354
+
355
+ # This will show configuration errors but runs
356
+ # npm run lint # Shows ESLint TypeScript project configuration issues
357
+
358
+ # Auto-fix formatting issues
359
+ # npm run lint:fix
360
+
361
+ # Format code
362
+ # npm run format
363
+ ```
364
+
365
+ ## Build and Publish Workflow
366
+
367
+ ### Local Build Process _(DISABLED)_
368
+
369
+ **⚠️ The React UI component is currently disabled and not in active development.**
370
+
371
+ ```bash
372
+ # THESE COMMANDS ARE CURRENTLY DISABLED
373
+ # Complete build from scratch
374
+ # cd ui-react_backup/ui
375
+ # npm install # 40 seconds
376
+ # npm run build # 5 seconds
377
+
378
+ # Verify built files exist
379
+ # ls -la ../dist/example_ext/ # Should show main.js, main.css, etc.
380
+ ```
381
+
382
+ ### GitHub Actions Publishing
383
+
384
+ The repository includes automated publishing via `.github/workflows/react-build.yml`:
385
+
386
+ - Triggers on `pyproject.toml` changes pushed to main branch
387
+ - Requires `REGISTRY_ACCESS_TOKEN` secret in repository settings
388
+ - Automatically builds React UI and publishes to ComfyUI Registry
389
+
390
+ ## pyproject.toml Specifications
391
+
392
+ Reference: https://docs.comfy.org/registry/specifications
393
+
394
+ The `pyproject.toml` file contains two main sections for ComfyUI custom nodes: `[project]` and `[tool.comfy]`.
395
+
396
+ ### [project] Section
397
+
398
+ #### name (required)
399
+
400
+ The node id uniquely identifies the custom node and will be used in URLs from the registry. Users can install the node by referencing this name:
401
+
402
+ ```bash
403
+ comfy node install <node-id>
404
+ ```
405
+
406
+ **Requirements:**
407
+
408
+ - Must be less than 100 characters
409
+ - Can only contain alphanumeric characters, hyphens, underscores, and periods
410
+ - Cannot have consecutive special characters
411
+ - Cannot start with a number or special character
412
+ - Case-insensitive comparison
413
+
414
+ **Best Practices:**
415
+
416
+ - Use a short, descriptive name
417
+ - Don't include "ComfyUI" in the name
418
+ - Make it memorable and easy to type
419
+
420
+ **Examples:**
421
+
422
+ ```toml
423
+ name = "image-processor" # ✅ Good: Simple and clear
424
+ name = "super-resolution" # ✅ Good: Describes functionality
425
+ name = "ComfyUI-enhancer" # ❌ Bad: Includes ComfyUI
426
+ name = "123-tool" # ❌ Bad: Starts with number
427
+ ```
428
+
429
+ #### version (required)
430
+
431
+ Uses [semantic versioning](https://semver.org/) with a three-digit version number X.Y.Z:
432
+
433
+ - X (MAJOR): Breaking changes
434
+ - Y (MINOR): New features (backwards compatible)
435
+ - Z (PATCH): Bug fixes
436
+
437
+ **Examples:**
438
+
439
+ ```toml
440
+ version = "1.0.0" # Initial release
441
+ version = "1.1.0" # Added new features
442
+ version = "1.1.1" # Bug fix
443
+ version = "2.0.0" # Breaking changes
444
+ ```
445
+
446
+ #### license (optional)
447
+
448
+ Specifies the license for your custom node. Can be specified in two ways:
449
+
450
+ 1. **File Reference:**
451
+
452
+ ```toml
453
+ license = { file = "LICENSE" } # ✅ Points to LICENSE file
454
+ license = { file = "LICENSE.txt" } # ✅ Points to LICENSE.txt
455
+ license = "LICENSE" # ❌ Incorrect format
456
+ ```
457
+
458
+ 2. **License Name:**
459
+
460
+ ```toml
461
+ license = { text = "MIT License" } # ✅ Correct format
462
+ license = { text = "Apache-2.0" } # ✅ Correct format
463
+ license = "MIT LICENSE" # ❌ Incorrect format
464
+ ```
465
+
466
+ Common licenses: [MIT](https://opensource.org/license/mit), [GPL](https://www.gnu.org/licenses/gpl-3.0.en.html), [Apache](https://www.apache.org/licenses/LICENSE-2.0)
467
+
468
+ #### description (recommended)
469
+
470
+ A brief description of what your custom node does.
471
+
472
+ ```toml
473
+ description = "A super resolution node for enhancing image quality"
474
+ ```
475
+
476
+ #### repository (required)
477
+
478
+ Links to the repository:
479
+
480
+ ```toml
481
+ [project.urls]
482
+ Repository = "https://github.com/username/repository"
483
+ ```
484
+
485
+ #### urls (recommended)
486
+
487
+ Links to related resources:
488
+
489
+ ```toml
490
+ [project.urls]
491
+ Documentation = "https://github.com/username/repository/wiki"
492
+ "Bug Tracker" = "https://github.com/username/repository/issues"
493
+ ```
494
+
495
+ #### requires-python (recommended)
496
+
497
+ Specifies the Python versions that your node supports:
498
+
499
+ ```toml
500
+ requires-python = ">=3.8" # Python 3.8 or higher
501
+ requires-python = ">=3.8,<3.11" # Python 3.8 up to (but not including) 3.11
502
+ ```
503
+
504
+ #### Frontend Version Compatibility (optional)
505
+
506
+ If your node has specific requirements for which ComfyUI frontend versions it supports, you can specify this using the `comfyui-frontend-package` dependency. This package is published on [PyPI](https://pypi.org/project/comfyui-frontend-package/).
507
+
508
+ Use this field when:
509
+
510
+ - Your custom node uses frontend APIs that were introduced in a specific version
511
+ - You've identified incompatibilities between your node and certain frontend versions
512
+ - Your node requires specific UI features only available in newer frontend versions
513
+
514
+ ```toml
515
+ [project]
516
+ dependencies = [
517
+ "comfyui-frontend-package>=1.20.0" # Requires frontend 1.20.0 or newer
518
+ "comfyui-frontend-package<=1.21.6" # Restricts to frontend versions up to 1.21.6
519
+ "comfyui-frontend-package>=1.19,<1.22" # Works with frontend 1.19 to 1.21.x
520
+ "comfyui-frontend-package~=1.20.0" # Compatible with 1.20.x but not 1.21.0
521
+ "comfyui-frontend-package!=1.21.3" # Works with any version except 1.21.3
522
+ ]
523
+ ```
524
+
525
+ #### classifiers (recommended)
526
+
527
+ Use classifiers to specify operating system compatibility and GPU accelerators. This information is used to help users find the right node for their system.
528
+
529
+ ```toml
530
+ [project]
531
+ classifiers = [
532
+ # For OS-independent nodes (works on all operating systems)
533
+ "Operating System :: OS Independent",
534
+
535
+ # OR for OS-specific nodes, specify the supported systems:
536
+ "Operating System :: Microsoft :: Windows", # Windows specific
537
+ "Operating System :: POSIX :: Linux", # Linux specific
538
+ "Operating System :: MacOS", # macOS specific
539
+
540
+ # GPU Accelerator support
541
+ "Environment :: GPU :: NVIDIA CUDA", # NVIDIA CUDA support
542
+ "Environment :: GPU :: AMD ROCm", # AMD ROCm support
543
+ "Environment :: GPU :: Intel Arc", # Intel Arc support
544
+ "Environment :: NPU :: Huawei Ascend", # Huawei Ascend support
545
+ "Environment :: GPU :: Apple Metal", # Apple Metal support
546
+ ]
547
+ ```
548
+
549
+ ### [tool.comfy] Section
550
+
551
+ #### PublisherId (required)
552
+
553
+ Your unique publisher identifier, typically matching your GitHub username.
554
+
555
+ **Examples:**
556
+
557
+ ```toml
558
+ PublisherId = "john-doe" # ✅ Matches GitHub username
559
+ PublisherId = "image-wizard" # ✅ Unique identifier
560
+ ```
561
+
562
+ #### DisplayName (optional)
563
+
564
+ A user-friendly name for your custom node.
565
+
566
+ ```toml
567
+ DisplayName = "Super Resolution Node"
568
+ ```
569
+
570
+ #### Icon (optional)
571
+
572
+ URL to your custom node's icon that will be displayed on the ComfyUI Registry and ComfyUI-Manager.
573
+
574
+ **Requirements:**
575
+
576
+ - File types: SVG, PNG, JPG, or GIF
577
+ - Maximum resolution: 400px × 400px
578
+ - Aspect ratio should be square
579
+
580
+ ```toml
581
+ Icon = "https://raw.githubusercontent.com/username/repo/main/icon.png"
582
+ ```
583
+
584
+ #### Banner (optional)
585
+
586
+ URL to a larger banner image that will be displayed on the ComfyUI Registry and ComfyUI-Manager.
587
+
588
+ **Requirements:**
589
+
590
+ - File types: SVG, PNG, JPG, or GIF
591
+ - Aspect ratio: 21:9
592
+
593
+ ```toml
594
+ Banner = "https://raw.githubusercontent.com/username/repo/main/banner.png"
595
+ ```
596
+
597
+ #### requires-comfyui (optional)
598
+
599
+ Specifies which version of ComfyUI your node is compatible with. This helps users ensure they have the correct version of ComfyUI installed.
600
+
601
+ **Supported operators:** `<`, `>`, `<=`, `>=`, `~=`, `<>`, `!=` and ranges
602
+
603
+ **Examples:**
604
+
605
+ ```toml
606
+ requires-comfyui = ">=1.0.0" # ComfyUI 1.0.0 or higher
607
+ requires-comfyui = ">=1.0.0,<2.0.0" # ComfyUI 1.0.0 up to (but not including) 2.0.0
608
+ requires-comfyui = "~=1.0.0" # Compatible release: version 1.0.0 or newer, but not version 2.0.0
609
+ requires-comfyui = "!=1.2.3" # Any version except 1.2.3
610
+ requires-comfyui = ">0.1.3,<1.0.0" # Greater than 0.1.3 and less than 1.0.0
611
+ ```
612
+
613
+ #### includes (optional)
614
+
615
+ Specifies whether to force include certain specific folders. For some situations, such as custom nodes in frontend projects, the final packaged output folder might be included in .gitignore. In such cases, we need to force include it for registry use.
616
+
617
+ ```toml
618
+ includes = ['dist']
619
+ ```
620
+
621
+ ### Complete Example
622
+
623
+ ```toml
624
+ [project]
625
+ name = "super-resolution-node"
626
+ version = "1.0.0"
627
+ description = "Enhance image quality using advanced super resolution techniques"
628
+ license = { file = "LICENSE" }
629
+ requires-python = ">=3.8"
630
+ dependencies = [
631
+ "comfyui-frontend-package<=1.21.6" # Frontend version compatibility
632
+ ]
633
+ classifiers = [
634
+ "Operating System :: OS Independent" # Works on all operating systems
635
+ ]
636
+ dynamic = ["dependencies"]
637
+
638
+ [tool.setuptools.dynamic]
639
+ dependencies = {file = ["requirements.txt"]}
640
+
641
+ [project.urls]
642
+ Repository = "https://github.com/username/super-resolution-node"
643
+ Documentation = "https://github.com/username/super-resolution-node/wiki"
644
+ "Bug Tracker" = "https://github.com/username/super-resolution-node/issues"
645
+
646
+ [tool.comfy]
647
+ PublisherId = "image-wizard"
648
+ DisplayName = "Super Resolution Node"
649
+ Icon = "https://raw.githubusercontent.com/username/super-resolution-node/main/icon.png"
650
+ Banner = "https://raw.githubusercontent.com/username/super-resolution-node/main/banner.png"
651
+ requires-comfyui = ">=1.0.0" # ComfyUI version compatibility
652
+ ```
653
+
654
+ ## Validation Scenarios
655
+
656
+ ### Always validate changes by running these verification steps:
657
+
658
+ #### Documentation Validation
659
+
660
+ ```bash
661
+ # 1. Verify all changes are documented
662
+ ls -la docs/ # Check for relevant documentation files
663
+
664
+ # 2. Ensure documentation is up-to-date
665
+ grep -r "TODO\|FIXME\|OUTDATED" docs/ # Should return no results
666
+
667
+ # 3. Validate markdown formatting
668
+ # (Optional: install markdownlint if available)
669
+ # markdownlint docs/*.md
670
+ ```
671
+
672
+ #### Python Node Validation
673
+
674
+ ```bash
675
+ # ALWAYS activate virtual environment first
676
+ source .venv/bin/activate
677
+
678
+ # 1. Import test
679
+ python3 -c "from nodes.nodes import NODE_CLASS_MAPPINGS; print('✓ Python imports work')"
680
+
681
+ # 2. Linting
682
+ ruff check . # Accept unused import warnings as normal
683
+
684
+ # 3. Verify system dependencies
685
+ ffmpeg -version | head -1 # Should show FFmpeg version
686
+ ```
687
+
688
+ #### React UI Validation _(DISABLED)_
689
+
690
+ **⚠️ The React UI component is currently disabled and not in active development.**
691
+
692
+ ```bash
693
+ # THESE COMMANDS ARE CURRENTLY DISABLED
694
+ # cd ui-react_backup/ui
695
+
696
+ # 1. Build test
697
+ # npm run build # Should complete in ~5 seconds
698
+
699
+ # 2. Verify outputs
700
+ # ls -la ../dist/example_ext/main.js # Should exist
701
+ # ls -la ../dist/locales/ # Should contain en/ and zh/ directories
702
+
703
+ # 3. TypeScript check
704
+ # npm run typecheck # Should pass without errors
705
+ ```
706
+
707
+ #### Full Integration Test _(PARTIALLY DISABLED)_
708
+
709
+ **⚠️ React UI components are disabled, but JavaScript widgets remain active.**
710
+
711
+ ```bash
712
+ # 1. Clean build (DISABLED - React components only)
713
+ # cd ui-react_backup/ui
714
+ # rm -rf ../dist/
715
+ # npm run build
716
+
717
+ # 2. Verify ComfyUI integration files
718
+ # ls -la ../dist/example_ext/ # React build outputs (DISABLED)
719
+ ls -la ../../web/js/ # JavaScript widgets (ACTIVE)
720
+ ls -la ../../__init__.py # Python entry point (ACTIVE)
721
+ ```
722
+
723
+ ## Known Issues and Limitations
724
+
725
+ ### Jest Testing Configuration
726
+
727
+ - Jest tests fail due to ES module configuration issues
728
+ - Example test exists in `src/__tests__/dummy.test.tsx` but won't run
729
+ - Fix requires updating jest.config.js and jest.setup.js for ESM support
730
+
731
+ ### ESLint Configuration
732
+
733
+ - ESLint shows TypeScript project configuration warnings
734
+ - Code builds and runs correctly despite these warnings
735
+ - Focus on functional validation rather than linting perfection
736
+
737
+ ### Python Import Warnings
738
+
739
+ - Ruff reports unused imports in `__init__.py` files
740
+ - These imports are intentional for ComfyUI integration
741
+ - The warnings can be safely ignored
742
+
743
+ ### System Dependencies
744
+
745
+ - FFmpeg is required for video processing features
746
+ - Without FFmpeg, video-related functionality will fail at runtime
747
+ - Always verify FFmpeg is installed in your environment
748
+
749
+ ## Common Tasks
750
+
751
+ ### Documentation Tasks
752
+
753
+ ```bash
754
+ # Create new feature documentation
755
+ touch docs/nodes/[node-name]/NEW_FEATURE.md
756
+ touch docs/features/NEW_FEATURE_IMPLEMENTATION.md
757
+
758
+ # Document a bug fix or implementation detail
759
+ touch docs/nodes/[node-name]/BUG_NAME_FIX.md
760
+ touch docs/infrastructure/[category]/TECHNICAL_IMPLEMENTATION_DETAILS.md
761
+
762
+ # Update existing documentation after changes
763
+ vim docs/nodes/video-preview/EXISTING_FEATURE.md
764
+
765
+ # Search for documentation gaps
766
+ grep -r "TODO\|FIXME\|INCOMPLETE" docs/
767
+
768
+ # Browse documentation by category
769
+ ls -la docs/nodes/ # Node-specific docs
770
+ ls -la docs/infrastructure/ # System/infrastructure docs
771
+ ls -la docs/integrations/ # External service integrations
772
+ ls -la docs/ui-widgets/ # UI widget documentation
773
+ ls -la docs/features/ # Feature implementations
774
+ ls -la docs/examples/ # Example workflows
775
+
776
+ # View category index
777
+ cat docs/nodes/video-preview/README.md # See what docs exist for Video Preview node
778
+
779
+ # Common documentation file types and locations:
780
+ # - docs/nodes/[node-name]/FEATURE_NAME.md - Node feature implementations
781
+ # - docs/nodes/[node-name]/ISSUE_NAME_FIX.md - Node-specific bug fixes
782
+ # - docs/infrastructure/[category]/SYSTEM_NAME.md - Infrastructure documentation
783
+ # - docs/integrations/[service]/INTEGRATION_GUIDE.md - Integration guides
784
+ # - docs/ui-widgets/WIDGET_IMPLEMENTATION.md - UI widget documentation
785
+ # - docs/features/FEATURE_GUIDE.md - Cross-cutting feature documentation
786
+ # - docs/IMPLEMENTATION_STATUS.md - Overall project status (root level)
787
+ ```
788
+
789
+ ### File Structure Overview
790
+
791
+ ```
792
+ comfyui_swissarmyknife/
793
+ ├── .github/workflows/react-build.yml # CI/CD automation
794
+ ├── __init__.py # Python entry point
795
+ ├── pyproject.toml # Project metadata & publishing config
796
+ ├── docs/ # ALL PROJECT DOCUMENTATION (ORGANIZED)
797
+ │ ├── README.md # Main documentation index
798
+ │ ├── IMPLEMENTATION_STATUS.md # Overall project status
799
+ │ ├── DOCUMENTATION_REORGANIZATION.md # Documentation structure guide
800
+ │ ├── nodes/ # Node-specific documentation
801
+ │ │ ├── video-preview/ # Video Preview node docs
802
+ │ │ ├── video-metadata/ # Video Metadata node docs
803
+ │ │ ├── media-describe/ # Gemini AI Media Description docs
804
+ │ │ ├── lora-loader/ # LoRA Loader node docs
805
+ │ │ └── reddit-media/ # Reddit Media Extraction docs
806
+ │ ├── infrastructure/ # Infrastructure components
807
+ │ │ ├── caching/ # Caching system docs
808
+ │ │ ├── debug/ # Debug & logging docs
809
+ │ │ ├── docker/ # Docker setup docs
810
+ │ │ └── build-deploy/ # Build & deployment docs
811
+ │ ├── integrations/ # External service integrations
812
+ │ │ └── civitai/ # CivitAI API integration docs
813
+ │ ├── ui-widgets/ # UI widget documentation
814
+ │ ├── features/ # Feature implementations
815
+ │ └── examples/ # Example workflows
816
+ ├── nodes/nodes.py # Main Python custom nodes
817
+ ├── web/js/ # JavaScript widgets
818
+ │ ├── video_preview/ # Video preview widget
819
+ │ ├── gemini_widgets.js # Gemini widgets
820
+ │ └── ...
821
+ └── ui-react_backup/ # React UI extension (DISABLED)
822
+ ├── ui/src/ # React source code
823
+ ├── ui/package.json # Node.js dependencies
824
+ └── dist/ # Built React outputs
825
+ ```
826
+
827
+ ### Package Management
828
+
829
+ ```bash
830
+ # React dependencies
831
+ cd ui-react_backup/ui
832
+ npm install # Install from package.json
833
+
834
+ # Python dependencies (ALWAYS activate venv first)
835
+ source .venv/bin/activate
836
+ pip3 install -e . # Install from pyproject.toml
837
+ pip3 install torch opencv-python # Additional ML dependencies
838
+ ```
839
+
840
+ ### Environment Verification
841
+
842
+ ```bash
843
+ # Verify tool versions
844
+ node --version # Should be v20.19.4+
845
+ npm --version # Should be 10.8.2+
846
+ python3 --version # Should be 3.12.3+
847
+ ffmpeg -version # Should be 6.1.1+
848
+
849
+ # Verify Python dependencies (activate venv first)
850
+ source .venv/bin/activate
851
+ which python3 # Should point to .venv/bin/python3
852
+ pip3 list | grep -E "(torch|opencv|google-genai)" # Show Python ML deps
853
+
854
+ # Verify Node dependencies
855
+ npm list --prefix ui-react_backup/ui # Show React dependencies
856
+ ```
857
+
858
+ ## Timing Expectations
859
+
860
+ **NEVER CANCEL these operations - they may appear to hang but are working:**
861
+
862
+ - `npm install`: 40 seconds (normal)
863
+ - `npm run build`: 5 seconds (very fast)
864
+ - `pip3 install torch opencv-python`: 2-3 minutes (downloads large binaries)
865
+ - `npm run watch`: Runs continuously until stopped
866
+ - `ruff check`: < 1 second (very fast)
867
+ - `pytest`: < 30 seconds (but no tests exist currently)
868
+
869
+ Set appropriate timeouts: 60+ seconds for npm install, 300+ seconds for Python ML dependencies.
870
+
871
+ ## Development Tips
872
+
873
+ - **Backend changes**: Restart ComfyUI server after modifying Python files in `nodes/`
874
+ - **Web extension changes**: Refresh browser cache after modifying JavaScript files in `web/js/`
875
+ - JavaScript widgets require no build step (plain JS files)
876
+ - Use Playwright tests in `web/tests/` to validate functionality against hosted ComfyUI server
877
+ - Focus on functional testing since automated tests have configuration issues
878
+ - FFmpeg must be available in PATH for video processing features to work
CONTRIBUTING.md ADDED
@@ -0,0 +1,320 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contributing to ComfyUI-SwissArmyKnife
2
+
3
+ Welcome to ComfyUI-SwissArmyKnife! This document provides guidelines for contributors and the Copilot coding agent.
4
+
5
+ ## Development Environment Setup
6
+
7
+ ### Dev Container (Recommended)
8
+
9
+ The easiest way to get started is using the provided dev container with GPU support:
10
+
11
+ 1. **Prerequisites:**
12
+ - Docker with NVIDIA GPU support
13
+ - VS Code with Dev Containers extension
14
+ - NVIDIA GPU drivers
15
+
16
+ 2. **Quick Start:**
17
+
18
+ ```bash
19
+ # Open in VS Code and use "Reopen in Container"
20
+ # OR run directly with Docker:
21
+ docker run --gpus all -v $(pwd):/workspaces/repo -p 8188:8188 mmartial/comfyui-nvidia-docker:ubuntu24_cuda12.8-latest
22
+ ```
23
+
24
+ 3. **Start ComfyUI:**
25
+ ```bash
26
+ ./.devcontainer/run-comfy.sh
27
+ # ComfyUI will be available at http://localhost:8188
28
+ ```
29
+
30
+ ### Manual Setup
31
+
32
+ If you prefer to set up locally:
33
+
34
+ 1. **Install Python dependencies:**
35
+
36
+ ```bash
37
+ pip install -e .
38
+ pip install ruff black mypy pytest opencv-python pillow
39
+ ```
40
+
41
+ 2. **Install JavaScript tooling:**
42
+
43
+ ```bash
44
+ cd web
45
+ npm install
46
+ ```
47
+
48
+ 3. **Install FFmpeg:**
49
+
50
+ ```bash
51
+ # Ubuntu/Debian
52
+ sudo apt-get install ffmpeg
53
+
54
+ # macOS
55
+ brew install ffmpeg
56
+ ```
57
+
58
+ ## Development Workflow
59
+
60
+ ### Python Backend Development
61
+
62
+ The backend nodes are located in `nodes/`:
63
+
64
+ - `nodes/nodes.py` - Main Gemini AI integration nodes
65
+ - `nodes/helper_nodes.py` - Helper/utility nodes
66
+ - `nodes/lora_manager/` - LoRA Manager (forked from nd-super-nodes)
67
+
68
+ **Development commands:**
69
+
70
+ ```bash
71
+ # Lint Python code
72
+ ruff check .
73
+ ruff check --fix . # Auto-fix issues
74
+
75
+ # Format Python code
76
+ black .
77
+
78
+ # Type checking
79
+ mypy .
80
+
81
+ # Run tests
82
+ pytest
83
+
84
+ # Test imports work
85
+ python -c "from nodes.nodes import NODE_CLASS_MAPPINGS; print('Nodes:', list(NODE_CLASS_MAPPINGS.keys()))"
86
+ ```
87
+
88
+ ### JavaScript Web Extension Development
89
+
90
+ The web extension consists of plain JavaScript widgets in `web/`:
91
+
92
+ - `web/js/gemini_widgets.js` - Main widget implementation
93
+ - `web/css/gemini_widgets.css` - Widget styling
94
+
95
+ **No build step required** - files are loaded directly by ComfyUI.
96
+
97
+ **Development commands:**
98
+
99
+ ```bash
100
+ cd web
101
+
102
+ # Lint JavaScript
103
+ npm run lint
104
+ npm run lint:fix # Auto-fix issues
105
+
106
+ # Format code
107
+ npm run format
108
+
109
+ # Test (Playwright tests)
110
+ cd tests
111
+ npm test
112
+ ```
113
+
114
+ **Important:** After making changes to JavaScript files, refresh the browser cache in ComfyUI to see changes.
115
+
116
+ ### Pre-commit Hooks
117
+
118
+ This project uses pre-commit hooks to maintain code quality:
119
+
120
+ ```bash
121
+ # Install hooks
122
+ pre-commit install
123
+
124
+ # Run manually
125
+ pre-commit run --all-files
126
+
127
+ # Skip hooks (for testing)
128
+ git commit --no-verify
129
+ ```
130
+
131
+ ## Testing
132
+
133
+ ### Python Testing
134
+
135
+ ```bash
136
+ pytest # Run all Python tests
137
+ ```
138
+
139
+ ### JavaScript Testing
140
+
141
+ ```bash
142
+ cd web/tests
143
+ npm test # Run Playwright tests against hosted ComfyUI
144
+ ```
145
+
146
+ **Note:** JavaScript tests require a running ComfyUI server with the custom node installed.
147
+
148
+ ## Code Style Guidelines
149
+
150
+ ### Python
151
+
152
+ - Use `ruff` for linting (configured in `pyproject.toml`)
153
+ - Use `black` for formatting
154
+ - Follow type hints with `mypy`
155
+ - Maximum line length: 140 characters
156
+
157
+ ### JavaScript
158
+
159
+ - Use ESLint for linting
160
+ - Use Prettier for formatting
161
+ - Follow ComfyUI widget conventions
162
+ - No build step - plain JavaScript files
163
+
164
+ ## Project Structure
165
+
166
+ ```
167
+ comfyui_swissarmyknife/
168
+ ├── .devcontainer/ # Dev container configuration
169
+ │ ├── devcontainer.json # Main dev container config
170
+ │ ├── postCreate.sh # Setup script
171
+ │ └── run-comfy.sh # ComfyUI start script
172
+ ├── nodes/ # Python backend nodes
173
+ │ ├── nodes.py # Main Gemini AI nodes
174
+ │ ├── helper_nodes.py # Helper nodes
175
+ │ └── lora_manager/ # LoRA Manager (forked from nd-super-nodes)
176
+ │ ├── __init__.py
177
+ │ ├── nd_super_lora_node.py
178
+ │ ├── lora_utils.py
179
+ │ ├── civitai_service.py
180
+ │ ├── template_manager.py
181
+ │ ├── web_api.py
182
+ │ ├── file_api.py
183
+ │ └── version_utils.py
184
+ ├── web/ # JavaScript web extension
185
+ │ ├── js/ # Widget JavaScript files
186
+ │ │ └── lora_manager/ # LoRA Manager web extension
187
+ │ ├── css/ # Widget CSS files
188
+ │ │ └── lora_manager/ # LoRA Manager styles
189
+ │ ├── tests/ # Playwright tests
190
+ │ └── package.json # Node.js dependencies
191
+ ├── docs/ # Project documentation
192
+ │ └── LORA_MANAGER_INTEGRATION.md # LoRA Manager docs
193
+ ├── __init__.py # ComfyUI entry point
194
+ ├── pyproject.toml # Python project configuration
195
+ └── README.md # Project documentation
196
+ ```
197
+
198
+ ## ComfyUI Integration
199
+
200
+ ### Backend Nodes
201
+
202
+ - Exported via `NODE_CLASS_MAPPINGS` and `NODE_DISPLAY_NAME_MAPPINGS` in `__init__.py`
203
+ - Require ComfyUI server restart after changes
204
+
205
+ ### Web Extension
206
+
207
+ - Loaded via `WEB_DIRECTORY = "./web"` in `__init__.py`
208
+ - Changes require browser cache refresh only
209
+
210
+ ## CI/CD
211
+
212
+ ### Continuous Integration
213
+
214
+ - Automated linting and testing via GitHub Actions
215
+ - **No GPU required** for CI - only static analysis
216
+ - Runs on Python and JavaScript code changes
217
+
218
+ ### Publishing
219
+
220
+ - Automatic publishing to ComfyUI Registry via GitHub Actions
221
+ - Triggered by `pyproject.toml` version updates
222
+ - Requires `REGISTRY_ACCESS_TOKEN` secret
223
+
224
+ ## Common Tasks
225
+
226
+ ### Adding a New Python Node
227
+
228
+ 1. Add node class to `nodes/nodes.py` or `nodes/helper_nodes.py`
229
+ 2. Export in `NODE_CLASS_MAPPINGS`
230
+ 3. Add tests in `tests/` directory
231
+ 4. Update documentation
232
+
233
+ ### Adding JavaScript Widgets
234
+
235
+ 1. Add widget code to `web/js/`
236
+ 2. Add styling to `web/css/`
237
+ 3. Register with ComfyUI using `app.registerExtension()`
238
+ 4. Test with browser refresh
239
+
240
+ ### Working with LoRA Manager
241
+
242
+ The LoRA Manager is a forked sub-module from [nd-super-nodes](https://github.com/HenkDz/nd-super-nodes). See [docs/LORA_MANAGER_INTEGRATION.md](docs/LORA_MANAGER_INTEGRATION.md) for detailed information.
243
+
244
+ **Key files:**
245
+
246
+ - Backend: `nodes/lora_manager/*.py`
247
+ - Frontend: `web/js/lora_manager/extension.js`
248
+ - Styles: `web/css/lora_manager/style.css`
249
+
250
+ **Testing lora_manager:**
251
+
252
+ ```bash
253
+ # Test imports
254
+ python -c "from nodes.lora_manager import NODE_CLASS_MAPPINGS; print('LoRA Manager nodes:', list(NODE_CLASS_MAPPINGS.keys()))"
255
+
256
+ # With ComfyUI running, check console for:
257
+ # "Swiss Army Knife LoRA Manager: API routes registered"
258
+ ```
259
+
260
+ ### Running Local Tests
261
+
262
+ ```bash
263
+ # Python
264
+ python -c "from nodes.nodes import NODE_CLASS_MAPPINGS; print('Available nodes:', list(NODE_CLASS_MAPPINGS.keys()))"
265
+ ruff check .
266
+ pytest
267
+
268
+ # JavaScript
269
+ cd web
270
+ npm run lint
271
+ cd tests && npm test # Requires running ComfyUI server
272
+ ```
273
+
274
+ ## Copilot Coding Agent Guidelines
275
+
276
+ For the GitHub Copilot coding agent working on this repository:
277
+
278
+ ### Safe Commands to Run
279
+
280
+ ```bash
281
+ # Linting (fast, safe)
282
+ ruff check .
283
+ ruff check --fix .
284
+
285
+ # Testing imports (fast)
286
+ python -c "from nodes.nodes import NODE_CLASS_MAPPINGS; print(list(NODE_CLASS_MAPPINGS.keys()))"
287
+
288
+ # JavaScript linting
289
+ cd web && npm run lint
290
+
291
+ # Run tests
292
+ pytest
293
+ cd web/tests && npm test
294
+ ```
295
+
296
+ ### Expected Timeouts
297
+
298
+ - `ruff check .`: < 1 second
299
+ - `pip install -e .`: ~12 seconds
300
+ - `pip install opencv-python`: 2-3 minutes (large downloads)
301
+ - `npm install`: ~40 seconds
302
+ - `pytest`: < 30 seconds
303
+
304
+ ### Key Development Points
305
+
306
+ - Backend changes require ComfyUI server restart
307
+ - Web extension changes require browser cache refresh only
308
+ - JavaScript widgets are plain JS files (no build step)
309
+ - Focus on minimal, surgical changes
310
+ - Use pre-commit hooks to maintain quality
311
+
312
+ ## Getting Help
313
+
314
+ - Check existing issues on GitHub
315
+ - Review ComfyUI custom node documentation: https://docs.comfy.org/custom-nodes/overview
316
+ - Check the project's implementation status in `IMPLEMENTATION_STATUS.md`
317
+
318
+ ## License
319
+
320
+ This project is licensed under the GNU General Public License v3. See `LICENSE` for details.
Dockerfile ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+
3
+ # Prevent interactive prompts during package installation
4
+ ENV DEBIAN_FRONTEND=noninteractive
5
+
6
+ # Install system dependencies
7
+ RUN apt-get update && apt-get install -y \
8
+ git \
9
+ wget \
10
+ ffmpeg \
11
+ libglib2.0-0 \
12
+ libsm6 \
13
+ libxext6 \
14
+ libxrender-dev \
15
+ libgomp1 \
16
+ && rm -rf /var/lib/apt/lists/*
17
+
18
+ # Create workspace directory
19
+ WORKDIR /workspace
20
+
21
+ # Clone ComfyUI
22
+ RUN git clone https://github.com/comfyanonymous/ComfyUI.git
23
+
24
+ # Set ComfyUI as working directory
25
+ WORKDIR /workspace/ComfyUI
26
+
27
+ # Install PyTorch CPU version first
28
+ RUN pip install --no-cache-dir \
29
+ torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
30
+
31
+ # Install ComfyUI dependencies from requirements.txt
32
+ RUN pip install --no-cache-dir -r requirements.txt
33
+
34
+ # Install additional dependencies needed for ComfyUI-SwissArmyKnife
35
+ RUN pip install --no-cache-dir \
36
+ google-genai \
37
+ opencv-python \
38
+ requests \
39
+ httpx
40
+
41
+ # Create directories for models and custom nodes if they don't exist
42
+ RUN mkdir -p models custom_nodes input output
43
+
44
+ # Install ComfyUI-Manager
45
+ RUN cd custom_nodes && \
46
+ git clone https://github.com/ltdrdata/ComfyUI-Manager.git comfyui-manager
47
+
48
+ # Install ComfyUI-Manager dependencies (includes GitPython and other required packages)
49
+ RUN pip install --no-cache-dir -r custom_nodes/comfyui-manager/requirements.txt
50
+
51
+ # Expose ComfyUI port
52
+ EXPOSE 8188
53
+
54
+ # Default command (can be overridden in docker-compose.yml)
55
+ CMD ["python", "main.py", "--listen", "0.0.0.0", "--port", "8188", "--cpu", "--base-directory", "/workspace/ComfyUI"]
LICENSE ADDED
@@ -0,0 +1,675 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+ Preamble
9
+
10
+ The GNU General Public License is a free, copyleft license for
11
+ software and other kinds of works.
12
+
13
+ The licenses for most software and other practical works are designed
14
+ to take away your freedom to share and change the works. By contrast,
15
+ the GNU General Public License is intended to guarantee your freedom to
16
+ share and change all versions of a program--to make sure it remains free
17
+ software for all its users. We, the Free Software Foundation, use the
18
+ GNU General Public License for most of our software; it applies also to
19
+ any other work released this way by its authors. You can apply it to
20
+ your programs, too.
21
+
22
+ When we speak of free software, we are referring to freedom, not
23
+ price. Our General Public Licenses are designed to make sure that you
24
+ have the freedom to distribute copies of free software (and charge for
25
+ them if you wish), that you receive source code or can get it if you
26
+ want it, that you can change the software or use pieces of it in new
27
+ free programs, and that you know you can do these things.
28
+
29
+ To protect your rights, we need to prevent others from denying you
30
+ these rights or asking you to surrender the rights. Therefore, you have
31
+ certain responsibilities if you distribute copies of the software, or if
32
+ you modify it: responsibilities to respect the freedom of others.
33
+
34
+ For example, if you distribute copies of such a program, whether
35
+ gratis or for a fee, you must pass on to the recipients the same
36
+ freedoms that you received. You must make sure that they, too, receive
37
+ or can get the source code. And you must show them these terms so they
38
+ know their rights.
39
+
40
+ Developers that use the GNU GPL protect your rights with two steps:
41
+ (1) assert copyright on the software, and (2) offer you this License
42
+ giving you legal permission to copy, distribute and/or modify it.
43
+
44
+ For the developers' and authors' protection, the GPL clearly explains
45
+ that there is no warranty for this free software. For both users' and
46
+ authors' sake, the GPL requires that modified versions be marked as
47
+ changed, so that their problems will not be attributed erroneously to
48
+ authors of previous versions.
49
+
50
+ Some devices are designed to deny users access to install or run
51
+ modified versions of the software inside them, although the manufacturer
52
+ can do so. This is fundamentally incompatible with the aim of
53
+ protecting users' freedom to change the software. The systematic
54
+ pattern of such abuse occurs in the area of products for individuals to
55
+ use, which is precisely where it is most unacceptable. Therefore, we
56
+ have designed this version of the GPL to prohibit the practice for those
57
+ products. If such problems arise substantially in other domains, we
58
+ stand ready to extend this provision to those domains in future versions
59
+ of the GPL, as needed to protect the freedom of users.
60
+
61
+ Finally, every program is threatened constantly by software patents.
62
+ States should not allow patents to restrict development and use of
63
+ software on general-purpose computers, but in those that do, we wish to
64
+ avoid the special danger that patents applied to a free program could
65
+ make it effectively proprietary. To prevent this, the GPL assures that
66
+ patents cannot be used to render the program non-free.
67
+
68
+ The precise terms and conditions for copying, distribution and
69
+ modification follow.
70
+
71
+ TERMS AND CONDITIONS
72
+
73
+ 0. Definitions.
74
+
75
+ "This License" refers to version 3 of the GNU General Public License.
76
+
77
+ "Copyright" also means copyright-like laws that apply to other kinds of
78
+ works, such as semiconductor masks.
79
+
80
+ "The Program" refers to any copyrightable work licensed under this
81
+ License. Each licensee is addressed as "you". "Licensees" and
82
+ "recipients" may be individuals or organizations.
83
+
84
+ To "modify" a work means to copy from or adapt all or part of the work
85
+ in a fashion requiring copyright permission, other than the making of an
86
+ exact copy. The resulting work is called a "modified version" of the
87
+ earlier work or a work "based on" the earlier work.
88
+
89
+ A "covered work" means either the unmodified Program or a work based
90
+ on the Program.
91
+
92
+ To "propagate" a work means to do anything with it that, without
93
+ permission, would make you directly or secondarily liable for
94
+ infringement under applicable copyright law, except executing it on a
95
+ computer or modifying a private copy. Propagation includes copying,
96
+ distribution (with or without modification), making available to the
97
+ public, and in some countries other activities as well.
98
+
99
+ To "convey" a work means any kind of propagation that enables other
100
+ parties to make or receive copies. Mere interaction with a user through
101
+ a computer network, with no transfer of a copy, is not conveying.
102
+
103
+ An interactive user interface displays "Appropriate Legal Notices"
104
+ to the extent that it includes a convenient and prominently visible
105
+ feature that (1) displays an appropriate copyright notice, and (2)
106
+ tells the user that there is no warranty for the work (except to the
107
+ extent that warranties are provided), that licensees may convey the
108
+ work under this License, and how to view a copy of this License. If
109
+ the interface presents a list of user commands or options, such as a
110
+ menu, a prominent item in the list meets this criterion.
111
+
112
+ 1. Source Code.
113
+
114
+ The "source code" for a work means the preferred form of the work
115
+ for making modifications to it. "Object code" means any non-source
116
+ form of a work.
117
+
118
+ A "Standard Interface" means an interface that either is an official
119
+ standard defined by a recognized standards body, or, in the case of
120
+ interfaces specified for a particular programming language, one that
121
+ is widely used among developers working in that language.
122
+
123
+ The "System Libraries" of an executable work include anything, other
124
+ than the work as a whole, that (a) is included in the normal form of
125
+ packaging a Major Component, but which is not part of that Major
126
+ Component, and (b) serves only to enable use of the work with that
127
+ Major Component, or to implement a Standard Interface for which an
128
+ implementation is available to the public in source code form. A
129
+ "Major Component", in this context, means a major essential component
130
+ (kernel, window system, and so on) of the specific operating system
131
+ (if any) on which the executable work runs, or a compiler used to
132
+ produce the work, or an object code interpreter used to run it.
133
+
134
+ The "Corresponding Source" for a work in object code form means all
135
+ the source code needed to generate, install, and (for an executable
136
+ work) run the object code and to modify the work, including scripts to
137
+ control those activities. However, it does not include the work's
138
+ System Libraries, or general-purpose tools or generally available free
139
+ programs which are used unmodified in performing those activities but
140
+ which are not part of the work. For example, Corresponding Source
141
+ includes interface definition files associated with source files for
142
+ the work, and the source code for shared libraries and dynamically
143
+ linked subprograms that the work is specifically designed to require,
144
+ such as by intimate data communication or control flow between those
145
+ subprograms and other parts of the work.
146
+
147
+ The Corresponding Source need not include anything that users
148
+ can regenerate automatically from other parts of the Corresponding
149
+ Source.
150
+
151
+ The Corresponding Source for a work in source code form is that
152
+ same work.
153
+
154
+ 2. Basic Permissions.
155
+
156
+ All rights granted under this License are granted for the term of
157
+ copyright on the Program, and are irrevocable provided the stated
158
+ conditions are met. This License explicitly affirms your unlimited
159
+ permission to run the unmodified Program. The output from running a
160
+ covered work is covered by this License only if the output, given its
161
+ content, constitutes a covered work. This License acknowledges your
162
+ rights of fair use or other equivalent, as provided by copyright law.
163
+
164
+ You may make, run and propagate covered works that you do not
165
+ convey, without conditions so long as your license otherwise remains
166
+ in force. You may convey covered works to others for the sole purpose
167
+ of having them make modifications exclusively for you, or provide you
168
+ with facilities for running those works, provided that you comply with
169
+ the terms of this License in conveying all material for which you do
170
+ not control copyright. Those thus making or running the covered works
171
+ for you must do so exclusively on your behalf, under your direction
172
+ and control, on terms that prohibit them from making any copies of
173
+ your copyrighted material outside their relationship with you.
174
+
175
+ Conveying under any other circumstances is permitted solely under
176
+ the conditions stated below. Sublicensing is not allowed; section 10
177
+ makes it unnecessary.
178
+
179
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180
+
181
+ No covered work shall be deemed part of an effective technological
182
+ measure under any applicable law fulfilling obligations under article
183
+ 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184
+ similar laws prohibiting or restricting circumvention of such
185
+ measures.
186
+
187
+ When you convey a covered work, you waive any legal power to forbid
188
+ circumvention of technological measures to the extent such circumvention
189
+ is effected by exercising rights under this License with respect to
190
+ the covered work, and you disclaim any intention to limit operation or
191
+ modification of the work as a means of enforcing, against the work's
192
+ users, your or third parties' legal rights to forbid circumvention of
193
+ technological measures.
194
+
195
+ 4. Conveying Verbatim Copies.
196
+
197
+ You may convey verbatim copies of the Program's source code as you
198
+ receive it, in any medium, provided that you conspicuously and
199
+ appropriately publish on each copy an appropriate copyright notice;
200
+ keep intact all notices stating that this License and any
201
+ non-permissive terms added in accord with section 7 apply to the code;
202
+ keep intact all notices of the absence of any warranty; and give all
203
+ recipients a copy of this License along with the Program.
204
+
205
+ You may charge any price or no price for each copy that you convey,
206
+ and you may offer support or warranty protection for a fee.
207
+
208
+ 5. Conveying Modified Source Versions.
209
+
210
+ You may convey a work based on the Program, or the modifications to
211
+ produce it from the Program, in the form of source code under the
212
+ terms of section 4, provided that you also meet all of these conditions:
213
+
214
+ a) The work must carry prominent notices stating that you modified
215
+ it, and giving a relevant date.
216
+
217
+ b) The work must carry prominent notices stating that it is
218
+ released under this License and any conditions added under section
219
+ 7. This requirement modifies the requirement in section 4 to
220
+ "keep intact all notices".
221
+
222
+ c) You must license the entire work, as a whole, under this
223
+ License to anyone who comes into possession of a copy. This
224
+ License will therefore apply, along with any applicable section 7
225
+ additional terms, to the whole of the work, and all its parts,
226
+ regardless of how they are packaged. This License gives no
227
+ permission to license the work in any other way, but it does not
228
+ invalidate such permission if you have separately received it.
229
+
230
+ d) If the work has interactive user interfaces, each must display
231
+ Appropriate Legal Notices; however, if the Program has interactive
232
+ interfaces that do not display Appropriate Legal Notices, your
233
+ work need not make them do so.
234
+
235
+ A compilation of a covered work with other separate and independent
236
+ works, which are not by their nature extensions of the covered work,
237
+ and which are not combined with it such as to form a larger program,
238
+ in or on a volume of a storage or distribution medium, is called an
239
+ "aggregate" if the compilation and its resulting copyright are not
240
+ used to limit the access or legal rights of the compilation's users
241
+ beyond what the individual works permit. Inclusion of a covered work
242
+ in an aggregate does not cause this License to apply to the other
243
+ parts of the aggregate.
244
+
245
+ 6. Conveying Non-Source Forms.
246
+
247
+ You may convey a covered work in object code form under the terms
248
+ of sections 4 and 5, provided that you also convey the
249
+ machine-readable Corresponding Source under the terms of this License,
250
+ in one of these ways:
251
+
252
+ a) Convey the object code in, or embodied in, a physical product
253
+ (including a physical distribution medium), accompanied by the
254
+ Corresponding Source fixed on a durable physical medium
255
+ customarily used for software interchange.
256
+
257
+ b) Convey the object code in, or embodied in, a physical product
258
+ (including a physical distribution medium), accompanied by a
259
+ written offer, valid for at least three years and valid for as
260
+ long as you offer spare parts or customer support for that product
261
+ model, to give anyone who possesses the object code either (1) a
262
+ copy of the Corresponding Source for all the software in the
263
+ product that is covered by this License, on a durable physical
264
+ medium customarily used for software interchange, for a price no
265
+ more than your reasonable cost of physically performing this
266
+ conveying of source, or (2) access to copy the
267
+ Corresponding Source from a network server at no charge.
268
+
269
+ c) Convey individual copies of the object code with a copy of the
270
+ written offer to provide the Corresponding Source. This
271
+ alternative is allowed only occasionally and noncommercially, and
272
+ only if you received the object code with such an offer, in accord
273
+ with subsection 6b.
274
+
275
+ d) Convey the object code by offering access from a designated
276
+ place (gratis or for a charge), and offer equivalent access to the
277
+ Corresponding Source in the same way through the same place at no
278
+ further charge. You need not require recipients to copy the
279
+ Corresponding Source along with the object code. If the place to
280
+ copy the object code is a network server, the Corresponding Source
281
+ may be on a different server (operated by you or a third party)
282
+ that supports equivalent copying facilities, provided you maintain
283
+ clear directions next to the object code saying where to find the
284
+ Corresponding Source. Regardless of what server hosts the
285
+ Corresponding Source, you remain obligated to ensure that it is
286
+ available for as long as needed to satisfy these requirements.
287
+
288
+ e) Convey the object code using peer-to-peer transmission, provided
289
+ you inform other peers where the object code and Corresponding
290
+ Source of the work are being offered to the general public at no
291
+ charge under subsection 6d.
292
+
293
+ A separable portion of the object code, whose source code is excluded
294
+ from the Corresponding Source as a System Library, need not be
295
+ included in conveying the object code work.
296
+
297
+ A "User Product" is either (1) a "consumer product", which means any
298
+ tangible personal property which is normally used for personal, family,
299
+ or household purposes, or (2) anything designed or sold for incorporation
300
+ into a dwelling. In determining whether a product is a consumer product,
301
+ doubtful cases shall be resolved in favor of coverage. For a particular
302
+ product received by a particular user, "normally used" refers to a
303
+ typical or common use of that class of product, regardless of the status
304
+ of the particular user or of the way in which the particular user
305
+ actually uses, or expects or is expected to use, the product. A product
306
+ is a consumer product regardless of whether the product has substantial
307
+ commercial, industrial or non-consumer uses, unless such uses represent
308
+ the only significant mode of use of the product.
309
+
310
+ "Installation Information" for a User Product means any methods,
311
+ procedures, authorization keys, or other information required to install
312
+ and execute modified versions of a covered work in that User Product from
313
+ a modified version of its Corresponding Source. The information must
314
+ suffice to ensure that the continued functioning of the modified object
315
+ code is in no case prevented or interfered with solely because
316
+ modification has been made.
317
+
318
+ If you convey an object code work under this section in, or with, or
319
+ specifically for use in, a User Product, and the conveying occurs as
320
+ part of a transaction in which the right of possession and use of the
321
+ User Product is transferred to the recipient in perpetuity or for a
322
+ fixed term (regardless of how the transaction is characterized), the
323
+ Corresponding Source conveyed under this section must be accompanied
324
+ by the Installation Information. But this requirement does not apply
325
+ if neither you nor any third party retains the ability to install
326
+ modified object code on the User Product (for example, the work has
327
+ been installed in ROM).
328
+
329
+ The requirement to provide Installation Information does not include a
330
+ requirement to continue to provide support service, warranty, or updates
331
+ for a work that has been modified or installed by the recipient, or for
332
+ the User Product in which it has been modified or installed. Access to a
333
+ network may be denied when the modification itself materially and
334
+ adversely affects the operation of the network or violates the rules and
335
+ protocols for communication across the network.
336
+
337
+ Corresponding Source conveyed, and Installation Information provided,
338
+ in accord with this section must be in a format that is publicly
339
+ documented (and with an implementation available to the public in
340
+ source code form), and must require no special password or key for
341
+ unpacking, reading or copying.
342
+
343
+ 7. Additional Terms.
344
+
345
+ "Additional permissions" are terms that supplement the terms of this
346
+ License by making exceptions from one or more of its conditions.
347
+ Additional permissions that are applicable to the entire Program shall
348
+ be treated as though they were included in this License, to the extent
349
+ that they are valid under applicable law. If additional permissions
350
+ apply only to part of the Program, that part may be used separately
351
+ under those permissions, but the entire Program remains governed by
352
+ this License without regard to the additional permissions.
353
+
354
+ When you convey a copy of a covered work, you may at your option
355
+ remove any additional permissions from that copy, or from any part of
356
+ it. (Additional permissions may be written to require their own
357
+ removal in certain cases when you modify the work.) You may place
358
+ additional permissions on material, added by you to a covered work,
359
+ for which you have or can give appropriate copyright permission.
360
+
361
+ Notwithstanding any other provision of this License, for material you
362
+ add to a covered work, you may (if authorized by the copyright holders of
363
+ that material) supplement the terms of this License with terms:
364
+
365
+ a) Disclaiming warranty or limiting liability differently from the
366
+ terms of sections 15 and 16 of this License; or
367
+
368
+ b) Requiring preservation of specified reasonable legal notices or
369
+ author attributions in that material or in the Appropriate Legal
370
+ Notices displayed by works containing it; or
371
+
372
+ c) Prohibiting misrepresentation of the origin of that material, or
373
+ requiring that modified versions of such material be marked in
374
+ reasonable ways as different from the original version; or
375
+
376
+ d) Limiting the use for publicity purposes of names of licensors or
377
+ authors of the material; or
378
+
379
+ e) Declining to grant rights under trademark law for use of some
380
+ trade names, trademarks, or service marks; or
381
+
382
+ f) Requiring indemnification of licensors and authors of that
383
+ material by anyone who conveys the material (or modified versions of
384
+ it) with contractual assumptions of liability to the recipient, for
385
+ any liability that these contractual assumptions directly impose on
386
+ those licensors and authors.
387
+
388
+ All other non-permissive additional terms are considered "further
389
+ restrictions" within the meaning of section 10. If the Program as you
390
+ received it, or any part of it, contains a notice stating that it is
391
+ governed by this License along with a term that is a further
392
+ restriction, you may remove that term. If a license document contains
393
+ a further restriction but permits relicensing or conveying under this
394
+ License, you may add to a covered work material governed by the terms
395
+ of that license document, provided that the further restriction does
396
+ not survive such relicensing or conveying.
397
+
398
+ If you add terms to a covered work in accord with this section, you
399
+ must place, in the relevant source files, a statement of the
400
+ additional terms that apply to those files, or a notice indicating
401
+ where to find the applicable terms.
402
+
403
+ Additional terms, permissive or non-permissive, may be stated in the
404
+ form of a separately written license, or stated as exceptions;
405
+ the above requirements apply either way.
406
+
407
+ 8. Termination.
408
+
409
+ You may not propagate or modify a covered work except as expressly
410
+ provided under this License. Any attempt otherwise to propagate or
411
+ modify it is void, and will automatically terminate your rights under
412
+ this License (including any patent licenses granted under the third
413
+ paragraph of section 11).
414
+
415
+ However, if you cease all violation of this License, then your
416
+ license from a particular copyright holder is reinstated (a)
417
+ provisionally, unless and until the copyright holder explicitly and
418
+ finally terminates your license, and (b) permanently, if the copyright
419
+ holder fails to notify you of the violation by some reasonable means
420
+ prior to 60 days after the cessation.
421
+
422
+ Moreover, your license from a particular copyright holder is
423
+ reinstated permanently if the copyright holder notifies you of the
424
+ violation by some reasonable means, this is the first time you have
425
+ received notice of violation of this License (for any work) from that
426
+ copyright holder, and you cure the violation prior to 30 days after
427
+ your receipt of the notice.
428
+
429
+ Termination of your rights under this section does not terminate the
430
+ licenses of parties who have received copies or rights from you under
431
+ this License. If your rights have been terminated and not permanently
432
+ reinstated, you do not qualify to receive new licenses for the same
433
+ material under section 10.
434
+
435
+ 9. Acceptance Not Required for Having Copies.
436
+
437
+ You are not required to accept this License in order to receive or
438
+ run a copy of the Program. Ancillary propagation of a covered work
439
+ occurring solely as a consequence of using peer-to-peer transmission
440
+ to receive a copy likewise does not require acceptance. However,
441
+ nothing other than this License grants you permission to propagate or
442
+ modify any covered work. These actions infringe copyright if you do
443
+ not accept this License. Therefore, by modifying or propagating a
444
+ covered work, you indicate your acceptance of this License to do so.
445
+
446
+ 10. Automatic Licensing of Downstream Recipients.
447
+
448
+ Each time you convey a covered work, the recipient automatically
449
+ receives a license from the original licensors, to run, modify and
450
+ propagate that work, subject to this License. You are not responsible
451
+ for enforcing compliance by third parties with this License.
452
+
453
+ An "entity transaction" is a transaction transferring control of an
454
+ organization, or substantially all assets of one, or subdividing an
455
+ organization, or merging organizations. If propagation of a covered
456
+ work results from an entity transaction, each party to that
457
+ transaction who receives a copy of the work also receives whatever
458
+ licenses to the work the party's predecessor in interest had or could
459
+ give under the previous paragraph, plus a right to possession of the
460
+ Corresponding Source of the work from the predecessor in interest, if
461
+ the predecessor has it or can get it with reasonable efforts.
462
+
463
+ You may not impose any further restrictions on the exercise of the
464
+ rights granted or affirmed under this License. For example, you may
465
+ not impose a license fee, royalty, or other charge for exercise of
466
+ rights granted under this License, and you may not initiate litigation
467
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
468
+ any patent claim is infringed by making, using, selling, offering for
469
+ sale, or importing the Program or any portion of it.
470
+
471
+ 11. Patents.
472
+
473
+ A "contributor" is a copyright holder who authorizes use under this
474
+ License of the Program or a work on which the Program is based. The
475
+ work thus licensed is called the contributor's "contributor version".
476
+
477
+ A contributor's "essential patent claims" are all patent claims
478
+ owned or controlled by the contributor, whether already acquired or
479
+ hereafter acquired, that would be infringed by some manner, permitted
480
+ by this License, of making, using, or selling its contributor version,
481
+ but do not include claims that would be infringed only as a
482
+ consequence of further modification of the contributor version. For
483
+ purposes of this definition, "control" includes the right to grant
484
+ patent sublicenses in a manner consistent with the requirements of
485
+ this License.
486
+
487
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
488
+ patent license under the contributor's essential patent claims, to
489
+ make, use, sell, offer for sale, import and otherwise run, modify and
490
+ propagate the contents of its contributor version.
491
+
492
+ In the following three paragraphs, a "patent license" is any express
493
+ agreement or commitment, however denominated, not to enforce a patent
494
+ (such as an express permission to practice a patent or covenant not to
495
+ sue for patent infringement). To "grant" such a patent license to a
496
+ party means to make such an agreement or commitment not to enforce a
497
+ patent against the party.
498
+
499
+ If you convey a covered work, knowingly relying on a patent license,
500
+ and the Corresponding Source of the work is not available for anyone
501
+ to copy, free of charge and under the terms of this License, through a
502
+ publicly available network server or other readily accessible means,
503
+ then you must either (1) cause the Corresponding Source to be so
504
+ available, or (2) arrange to deprive yourself of the benefit of the
505
+ patent license for this particular work, or (3) arrange, in a manner
506
+ consistent with the requirements of this License, to extend the patent
507
+ license to downstream recipients. "Knowingly relying" means you have
508
+ actual knowledge that, but for the patent license, your conveying the
509
+ covered work in a country, or your recipient's use of the covered work
510
+ in a country, would infringe one or more identifiable patents in that
511
+ country that you have reason to believe are valid.
512
+
513
+ If, pursuant to or in connection with a single transaction or
514
+ arrangement, you convey, or propagate by procuring conveyance of, a
515
+ covered work, and grant a patent license to some of the parties
516
+ receiving the covered work authorizing them to use, propagate, modify
517
+ or convey a specific copy of the covered work, then the patent license
518
+ you grant is automatically extended to all recipients of the covered
519
+ work and works based on it.
520
+
521
+ A patent license is "discriminatory" if it does not include within
522
+ the scope of its coverage, prohibits the exercise of, or is
523
+ conditioned on the non-exercise of one or more of the rights that are
524
+ specifically granted under this License. You may not convey a covered
525
+ work if you are a party to an arrangement with a third party that is
526
+ in the business of distributing software, under which you make payment
527
+ to the third party based on the extent of your activity of conveying
528
+ the work, and under which the third party grants, to any of the
529
+ parties who would receive the covered work from you, a discriminatory
530
+ patent license (a) in connection with copies of the covered work
531
+ conveyed by you (or copies made from those copies), or (b) primarily
532
+ for and in connection with specific products or compilations that
533
+ contain the covered work, unless you entered into that arrangement,
534
+ or that patent license was granted, prior to 28 March 2007.
535
+
536
+ Nothing in this License shall be construed as excluding or limiting
537
+ any implied license or other defenses to infringement that may
538
+ otherwise be available to you under applicable patent law.
539
+
540
+ 12. No Surrender of Others' Freedom.
541
+
542
+ If conditions are imposed on you (whether by court order, agreement or
543
+ otherwise) that contradict the conditions of this License, they do not
544
+ excuse you from the conditions of this License. If you cannot convey a
545
+ covered work so as to satisfy simultaneously your obligations under this
546
+ License and any other pertinent obligations, then as a consequence you may
547
+ not convey it at all. For example, if you agree to terms that obligate you
548
+ to collect a royalty for further conveying from those to whom you convey
549
+ the Program, the only way you could satisfy both those terms and this
550
+ License would be to refrain entirely from conveying the Program.
551
+
552
+ 13. Use with the GNU Affero General Public License.
553
+
554
+ Notwithstanding any other provision of this License, you have
555
+ permission to link or combine any covered work with a work licensed
556
+ under version 3 of the GNU Affero General Public License into a single
557
+ combined work, and to convey the resulting work. The terms of this
558
+ License will continue to apply to the part which is the covered work,
559
+ but the special requirements of the GNU Affero General Public License,
560
+ section 13, concerning interaction through a network will apply to the
561
+ combination as such.
562
+
563
+ 14. Revised Versions of this License.
564
+
565
+ The Free Software Foundation may publish revised and/or new versions of
566
+ the GNU General Public License from time to time. Such new versions will
567
+ be similar in spirit to the present version, but may differ in detail to
568
+ address new problems or concerns.
569
+
570
+ Each version is given a distinguishing version number. If the
571
+ Program specifies that a certain numbered version of the GNU General
572
+ Public License "or any later version" applies to it, you have the
573
+ option of following the terms and conditions either of that numbered
574
+ version or of any later version published by the Free Software
575
+ Foundation. If the Program does not specify a version number of the
576
+ GNU General Public License, you may choose any version ever published
577
+ by the Free Software Foundation.
578
+
579
+ If the Program specifies that a proxy can decide which future
580
+ versions of the GNU General Public License can be used, that proxy's
581
+ public statement of acceptance of a version permanently authorizes you
582
+ to choose that version for the Program.
583
+
584
+ Later license versions may give you additional or different
585
+ permissions. However, no additional obligations are imposed on any
586
+ author or copyright holder as a result of your choosing to follow a
587
+ later version.
588
+
589
+ 15. Disclaimer of Warranty.
590
+
591
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597
+ IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
+
600
+ 16. Limitation of Liability.
601
+
602
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604
+ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606
+ USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609
+ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610
+ SUCH DAMAGES.
611
+
612
+ 17. Interpretation of Sections 15 and 16.
613
+
614
+ If the disclaimer of warranty and limitation of liability provided
615
+ above cannot be given local legal effect according to their terms,
616
+ reviewing courts shall apply local law that most closely approximates
617
+ an absolute waiver of all civil liability in connection with the
618
+ Program, unless a warranty or assumption of liability accompanies a
619
+ copy of the Program in return for a fee.
620
+
621
+ END OF TERMS AND CONDITIONS
622
+
623
+ How to Apply These Terms to Your New Programs
624
+
625
+ If you develop a new program, and you want it to be of the greatest
626
+ possible use to the public, the best way to achieve this is to make it
627
+ free software which everyone can redistribute and change under these terms.
628
+
629
+ To do so, attach the following notices to the program. It is safest
630
+ to attach them to the start of each source file to most effectively
631
+ state the exclusion of warranty; and each file should have at least
632
+ the "copyright" line and a pointer to where the full notice is found.
633
+
634
+ <one line to give the program's name and a brief idea of what it does.>
635
+ Copyright (C) <year> <name of author>
636
+
637
+ This program is free software: you can redistribute it and/or modify
638
+ it under the terms of the GNU General Public License as published by
639
+ the Free Software Foundation, either version 3 of the License, or
640
+ (at your option) any later version.
641
+
642
+ This program is distributed in the hope that it will be useful,
643
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
644
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645
+ GNU General Public License for more details.
646
+
647
+ You should have received a copy of the GNU General Public License
648
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
649
+
650
+ Also add information on how to contact you by electronic and paper mail.
651
+
652
+ If the program does terminal interaction, make it output a short
653
+ notice like this when it starts in an interactive mode:
654
+
655
+ <program> Copyright (C) <year> <name of author>
656
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657
+ This is free software, and you are welcome to redistribute it
658
+ under certain conditions; type `show c' for details.
659
+
660
+ The hypothetical commands `show w' and `show c' should show the appropriate
661
+ parts of the General Public License. Of course, your program's commands
662
+ might be different; for a GUI interface, you would use an "about box".
663
+
664
+ You should also get your employer (if you work as a programmer) or school,
665
+ if any, to sign a "copyright disclaimer" for the program, if necessary.
666
+ For more information on this, and how to apply and follow the GNU GPL, see
667
+ <https://www.gnu.org/licenses/>.
668
+
669
+ The GNU General Public License does not permit incorporating your program
670
+ into proprietary programs. If your program is a subroutine library, you
671
+ may consider it more useful to permit linking proprietary applications with
672
+ the library. If this is what you want to do, use the GNU Lesser General
673
+ Public License instead of this License. But first, please read
674
+ <https://www.gnu.org/licenses/why-not-lgpl.html>.
675
+
MANIFEST.in ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Include the main package files
2
+ include __init__.py
3
+ recursive-include utils *.py
4
+
5
+ # Include web extension files
6
+ include web/js/*.js
7
+
8
+ # Include documentation and metadata
9
+ include README.md
10
+ include LICENSE
11
+ include pyproject.toml
12
+
13
+ # Exclude development and build artifacts
14
+ exclude *.pyc
15
+ recursive-exclude __pycache__ *
16
+ recursive-exclude example_nodes *
17
+ recursive-exclude ui-react_backup *
18
+ recursive-exclude web/tests *
19
+ recursive-exclude web/node_modules *
20
+ recursive-exclude .git *
21
+ exclude .gitignore
22
+ exclude docker-compose.yml
23
+ exclude Dockerfile
24
+ exclude node.zip
25
+ exclude package.json
README.md ADDED
@@ -0,0 +1,386 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ComfyUI-SwissArmyKnife
2
+
3
+ A collection of custom nodes for ComfyUI featuring Gemini AI integration for video and image analysis, with a complete development environment using GPU-accelerated containers.
4
+
5
+ ## Features
6
+
7
+ - **🤖 Gemini AI Integration**: Video, image, and media analysis using Google's Gemini AI
8
+ - **🎨 Super LoRA Loader**: Advanced multi-LoRA management with enhanced UI (forked from nd-super-nodes)
9
+ - **🎮 JavaScript Widgets**: Enhanced ComfyUI interfaces with custom video controls
10
+ - **🐳 Dev Container Support**: GPU-enabled development environment with mmartial/ComfyUI-Nvidia-Docker
11
+ - **🧪 Full Testing Suite**: Python and JavaScript testing with CI/CD integration
12
+ - **⚡ Hot Reload Development**: Instant feedback for both backend and frontend changes
13
+
14
+ ## Quick Start with Dev Container (Recommended)
15
+
16
+ The fastest way to get started is using the provided dev container with GPU support:
17
+
18
+ ### Prerequisites
19
+
20
+ - Docker with NVIDIA Container Toolkit
21
+ - VS Code with Dev Containers extension
22
+ - NVIDIA GPU with drivers installed
23
+
24
+ ### Setup
25
+
26
+ ```bash
27
+ # Clone the repository
28
+ git clone https://github.com/sammykumar/ComfyUI-SwissArmyKnife.git
29
+ cd ComfyUI-SwissArmyKnife
30
+
31
+ # Open in VS Code
32
+ code .
33
+
34
+ # Use "Reopen in Container" from VS Code command palette
35
+ # OR run directly with Docker:
36
+ docker run --gpus all -v $(pwd):/workspaces/repo -p 8188:8188 \
37
+ mmartial/comfyui-nvidia-docker:ubuntu24_cuda12.8-latest
38
+
39
+ # Inside the container, start ComfyUI:
40
+ ./.devcontainer/run-comfy.sh
41
+ ```
42
+
43
+ ComfyUI will be available at **http://localhost:8188** with your custom nodes automatically loaded.
44
+
45
+ ## Manual Installation
46
+
47
+ ### For ComfyUI Users
48
+
49
+ If you want to use the nodes in an existing ComfyUI installation:
50
+
51
+ ```bash
52
+ # Go to your ComfyUI custom_nodes directory
53
+ cd ComfyUI/custom_nodes
54
+
55
+ # Clone the repository
56
+ git clone https://github.com/sammykumar/ComfyUI-SwissArmyKnife.git
57
+
58
+ # Install dependencies
59
+ cd ComfyUI-SwissArmyKnife
60
+ pip install -e .
61
+
62
+ # Restart ComfyUI
63
+ ```
64
+
65
+ ### For Development
66
+
67
+ If you're contributing to the project or want to modify the nodes:
68
+
69
+ ```bash
70
+ # Clone the repository
71
+ git clone https://github.com/sammykumar/ComfyUI-SwissArmyKnife.git
72
+ cd ComfyUI-SwissArmyKnife
73
+
74
+ # Install Python dependencies
75
+ pip install -e .
76
+ pip install ruff black mypy pytest opencv-python pillow
77
+
78
+ # Install JavaScript tooling
79
+ cd web
80
+ npm install
81
+
82
+ # Install pre-commit hooks
83
+ pre-commit install
84
+ ```
85
+
86
+ **System Requirements:**
87
+
88
+ - Python 3.10+
89
+ - Node.js 20+ (for development)
90
+ - FFmpeg (for video processing)
91
+ - NVIDIA GPU (optional, for accelerated inference)
92
+
93
+ ## Available Nodes
94
+
95
+ ### Backend Nodes (Python)
96
+
97
+ - **GeminiUtilVideoDescribe**: Analyze videos using Gemini AI
98
+ - **GeminiUtilImageDescribe**: Analyze images using Gemini AI
99
+ - **GeminiUtilMediaDescribe**: Multi-media analysis functionality
100
+ - **Super LoRA Loader 🔪**: Advanced multi-LoRA loading with UI enhancements (from nd-super-nodes)
101
+ - Load multiple LoRAs in a single node
102
+ - Individual enable/disable controls per LoRA
103
+ - Dual strength support (model and CLIP)
104
+ - Automatic trigger word extraction
105
+ - Template save/load system
106
+ - Enhanced file picker with search
107
+ - See [docs/LORA_MANAGER_INTEGRATION.md](docs/LORA_MANAGER_INTEGRATION.md) for details
108
+
109
+ ### Web Extension (JavaScript)
110
+
111
+ - **Video Controls Widget**: Enhanced video timeline controls with trimming
112
+ - **Custom Styling**: Themed UI components that integrate with ComfyUI
113
+
114
+ ## 🔐 API Key Configuration
115
+
116
+ ### Required: Google Gemini API Key
117
+
118
+ To use the Gemini AI features, you'll need a Google Gemini API key:
119
+
120
+ 1. **Get your API key**: Visit [Google AI Studio](https://aistudio.google.com/app/apikey)
121
+ 2. **Create API key**: Click "Create API Key" and copy the generated key
122
+ 3. **Configure securely**:
123
+
124
+ ```bash
125
+ # Copy the environment template
126
+ cp .env.example .env
127
+
128
+ # Edit .env and add your actual API key
129
+ GEMINI_API_KEY=your_actual_api_key_here
130
+ ```
131
+
132
+ ⚠️ **Security Note**: Never commit your actual API keys to version control. The `.env` file is already included in `.gitignore`.
133
+
134
+ **Alternative**: You can also enter your API key directly in the ComfyUI node interface, but using environment variables is more secure.
135
+
136
+ ## Development Workflow
137
+
138
+ ### Dev Container (Recommended)
139
+
140
+ ```bash
141
+ # Start the development environment
142
+ ./.devcontainer/run-comfy.sh
143
+
144
+ # ComfyUI available at http://localhost:8188
145
+ # Changes are automatically reloaded
146
+ ```
147
+
148
+ ### Local Development
149
+
150
+ ```bash
151
+ # Python backend development
152
+ ruff check . # Lint Python code
153
+ pytest # Run Python tests
154
+ python -c "from nodes.nodes import NODE_CLASS_MAPPINGS; print(list(NODE_CLASS_MAPPINGS.keys()))"
155
+
156
+ # JavaScript web extension development
157
+ cd web
158
+ npm run lint # Lint JavaScript
159
+ npm run format # Format code
160
+ cd tests && npm test # Run Playwright tests (requires running ComfyUI)
161
+ ```
162
+
163
+ **Important Notes:**
164
+
165
+ - Python changes require ComfyUI server restart
166
+ - JavaScript changes require browser cache refresh only
167
+ - JavaScript widgets are plain JS files (no build step required)
168
+
169
+ ## Testing
170
+
171
+ ### Automated Testing
172
+
173
+ The project includes comprehensive CI/CD testing:
174
+
175
+ - **Python**: Linting (ruff), formatting (black), type checking (mypy), unit tests (pytest)
176
+ - **JavaScript**: Linting (eslint), formatting (prettier), integration tests (playwright)
177
+ - **Integration**: ComfyUI node loading, FFmpeg availability, system compatibility
178
+
179
+ ### Manual Testing
180
+
181
+ ```bash
182
+ # Test Python nodes
183
+ python -c "from nodes.nodes import NODE_CLASS_MAPPINGS; print('Nodes:', list(NODE_CLASS_MAPPINGS.keys()))"
184
+
185
+ # Test JavaScript widgets
186
+ # 1. Start ComfyUI with the custom node
187
+ # 2. Add a Gemini node to your workflow
188
+ # 3. Test video controls and interface elements
189
+ ```
190
+
191
+ ## Usage
192
+
193
+ This template includes a simple example extension that displays workflow node statistics. After installation:
194
+
195
+ 1. Look for the "React Example" tab in the ComfyUI sidebar
196
+ 2. Click to open the example UI
197
+
198
+ When developing your own extension, you can:
199
+
200
+ 1. Replace the example UI in App.tsx with your own components
201
+ 2. Update the tab title and icon in main.tsx
202
+ 3. Customize the extension's appearance and behavior
203
+
204
+ ## Development
205
+
206
+ ### Setup Development Environment
207
+
208
+ ```bash
209
+ # Go to the UI directory
210
+ cd ui
211
+
212
+ # Install dependencies
213
+ npm install
214
+
215
+ # Start development mode (watches for changes)
216
+ npm run watch
217
+ ```
218
+
219
+ ### Available ComfyUI Extension APIs
220
+
221
+ This template provides access to ComfyUI's powerful JavaScript APIs through the official type definitions. You can use these APIs to build rich extensions:
222
+
223
+ - **Sidebar Tabs**: Create custom sidebar panels like this template demonstrates
224
+ - **Bottom Bar Panels**: Add panels to the bottom of the UI
225
+ - **Top Menu Items**: Add custom entries to the top menu
226
+ - **Context Menus**: Create custom context menus for the graph
227
+ - **Settings**: Add settings to the ComfyUI settings panel
228
+ - **Toasts**: Display notification messages
229
+ - **Commands**: Create and register custom commands
230
+ - **Hotkeys/Keybindings**: Register custom keyboard shortcuts
231
+ - **About Panel Badges**: Add badges to the about panel
232
+ - **App Events**: Listen to and respond to app events
233
+ - **Graph Manipulation**: Programmatically manipulate the workflow graph
234
+
235
+ For comprehensive documentation on all available APIs, see the [ComfyUI JavaScript Developer Documentation](https://docs.comfy.org/custom-nodes/js/javascript_overview).
236
+
237
+ ### File Structure
238
+
239
+ ```
240
+ ComfyUI-SwissArmyKnife/
241
+ ├── .github/ # GitHub configurations
242
+ │ └── workflows/
243
+ │ └── react-build.yml # Automatic build and publishing workflow
244
+ ├── __init__.py # Python entry point for ComfyUI integration
245
+ ├── pyproject.toml # Project metadata for ComfyUI Registry
246
+ ├── dist/ # Built extension files (generated)
247
+ └── ui/ # React application
248
+ ├── public/
249
+ │ └── locales/ # Internationalization files
250
+ │ ├── en/
251
+ │ │ └── main.json # English translations
252
+ │ └── zh/
253
+ │ └── main.json # Chinese translations
254
+ ├── src/
255
+ │ ├── App.tsx # Main React component with example UI
256
+ │ ├── App.css # Styles for the example UI
257
+ │ ├── index.css # Global styles and theme variables
258
+ │ ├── main.tsx # Entry point for React app
259
+ │ ├── vite-env.d.ts # Vite environment types
260
+ │ ├── setupTests.ts # Testing environment setup
261
+ │ ├── __tests__/ # Unit tests for components
262
+ │ │ └── dummy.test.tsx # Example test
263
+ │ └── nodes/
264
+ │ └── i18n.ts # Internationalization setup
265
+ ├── eslint.config.js # ESLint configuration
266
+ ├── jest.config.js # Jest testing configuration
267
+ ├── jest.setup.js # Jest setup file
268
+ ├── package.json # npm dependencies
269
+ ├── tsconfig.json # TypeScript configuration
270
+ ├── tsconfig.node.json # TypeScript configuration for Node
271
+ └── vite.config.ts # Build configuration
272
+ ```
273
+
274
+ ### TypeScript Support
275
+
276
+ This extension uses the official `@comfyorg/comfyui-frontend-types` package for type-safe interaction with ComfyUI APIs. To install it:
277
+
278
+ ```bash
279
+ cd ui
280
+ npm install -D @comfyorg/comfyui-frontend-types
281
+ ```
282
+
283
+ ## Publishing to ComfyUI Registry
284
+
285
+ ### Prerequisites
286
+
287
+ 1. Set up a [Registry](https://registry.comfy.org) account
288
+ 2. Create an API key at https://registry.comfy.org/nodes
289
+
290
+ ### Steps to Publish
291
+
292
+ 1. Install the comfy-cli tool:
293
+
294
+ ```bash
295
+ pip install comfy-cli
296
+ ```
297
+
298
+ 2. Verify your pyproject.toml has the correct metadata:
299
+
300
+ ```toml
301
+ [project]
302
+ name = "your_extension_name" # Use a unique name for your extension
303
+ description = "Your extension description here."
304
+ version = "0.1.0" # Increment this with each update
305
+
306
+ [tool.comfy]
307
+ PublisherId = "your_publisher_id" # Your Registry publisher ID
308
+ DisplayName = "Your Extension Display Name"
309
+ includes = ["dist/"] # Include built React code (normally ignored by .gitignore)
310
+ ```
311
+
312
+ 3. Publish your extension:
313
+
314
+ ```bash
315
+ comfy-cli publish
316
+ ```
317
+
318
+ 4. When prompted, enter your API key
319
+
320
+ ### Automatic Publishing with GitHub Actions
321
+
322
+ This template includes a GitHub Actions workflow that automatically publishes to the ComfyUI Registry whenever you update the version in pyproject.toml:
323
+
324
+ 1. Go to your repository's Settings > Secrets and variables > Actions
325
+ 2. Create a new repository secret called `REGISTRY_ACCESS_TOKEN` with your API key
326
+ 3. Commit and push an update to pyproject.toml (e.g., increment the version number)
327
+ 4. The GitHub Action will automatically run and publish your extension
328
+
329
+ The workflow configuration is set up in `.github/workflows/react-build.yml` and will trigger when:
330
+
331
+ - The `pyproject.toml` file is modified and pushed to the `main` branch
332
+
333
+ The workflow automatically:
334
+
335
+ 1. Sets up Node.js environment
336
+ 2. Installs dependencies (`npm install`)
337
+ 3. Builds the React extension (`npm run build`)
338
+ 4. Publishes the extension to the ComfyUI Registry
339
+
340
+ ## Unit Testing
341
+
342
+ This template includes a basic setup for unit testing with Jest and React Testing Library:
343
+
344
+ ```bash
345
+ # Run tests
346
+ npm test
347
+
348
+ # Run tests in watch mode during development
349
+ npm run test:watch
350
+ ```
351
+
352
+ Example tests can be found in the `src/__tests__` directory. The setup includes:
353
+
354
+ - Jest for running tests
355
+ - React Testing Library for testing components
356
+ - Mock implementation of the ComfyUI window.app object
357
+
358
+ ## Resources
359
+
360
+ - [ComfyUI JS Extension Documentation](https://docs.comfy.org/custom-nodes/js/javascript_overview) - Official documentation for ComfyUI JavaScript Extensions
361
+ - [ComfyUI Registry Documentation](https://docs.comfy.org/registry/publishing) - Learn how to publish your extension
362
+ - [ComfyUI Frontend Repository](https://github.com/sammykumar/ComfyUI-Frontend) - The main ComfyUI frontend codebase
363
+ - [Official ComfyUI Frontend Types](https://www.npmjs.com/package/@comfyorg/comfyui-frontend-types) - TypeScript definitions for ComfyUI
364
+ - [React Extension Guide](REACT_EXTENSION_GUIDE.md) - Detailed guide for creating React extensions
365
+ - [TypeScript Documentation](https://www.typescriptlang.org/docs/)
366
+ - [React Documentation](https://react.dev/reference/react)
367
+ - [Jest Documentation](https://jestjs.io/docs/getting-started)
368
+ - [React Testing Library](https://testing-library.com/docs/react-testing-library/intro/)
369
+
370
+ ## Contributing
371
+
372
+ Contributions are welcome! Feel free to open issues or submit pull requests to improve this template.
373
+
374
+ ## Credits
375
+
376
+ ### Third-Party Integrations
377
+
378
+ - **LoRA Manager** - Forked from [nd-super-nodes](https://github.com/HenkDz/nd-super-nodes) by HenkDz
379
+ - Super LoRA Loader with multi-LoRA management
380
+ - Enhanced file picker overlay
381
+ - Template management system
382
+ - CivitAI integration for trigger words
383
+
384
+ ## License
385
+
386
+ GNU General Public License v3
__init__.py ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from .nodes.nodes import NODE_CLASS_MAPPINGS as MAIN_NODE_CLASS_MAPPINGS
3
+ from .nodes.nodes import NODE_DISPLAY_NAME_MAPPINGS as MAIN_NODE_DISPLAY_NAME_MAPPINGS
4
+ from .nodes.helper_nodes import HELPER_NODE_CLASS_MAPPINGS
5
+ from .nodes.helper_nodes import HELPER_NODE_DISPLAY_NAME_MAPPINGS
6
+
7
+ # Import control panel node
8
+ try:
9
+ from .nodes.utils.control_panel import CONTROL_PANEL_NODE_CLASS_MAPPINGS
10
+ from .nodes.utils.control_panel import CONTROL_PANEL_NODE_DISPLAY_NAME_MAPPINGS
11
+ except ImportError as e:
12
+ print(f"Warning: Could not import control panel node: {e}")
13
+ CONTROL_PANEL_NODE_CLASS_MAPPINGS = {}
14
+ CONTROL_PANEL_NODE_DISPLAY_NAME_MAPPINGS = {}
15
+
16
+ # Import civit metadata helper node
17
+ try:
18
+ from .nodes.utils.civit_metadata_helper import CIVIT_METADATA_HELPER_NODE_CLASS_MAPPINGS
19
+ from .nodes.utils.civit_metadata_helper import CIVIT_METADATA_HELPER_NODE_DISPLAY_NAME_MAPPINGS
20
+ except ImportError as e:
21
+ print(f"Warning: Could not import civit metadata helper node: {e}")
22
+ CIVIT_METADATA_HELPER_NODE_CLASS_MAPPINGS = {}
23
+ CIVIT_METADATA_HELPER_NODE_DISPLAY_NAME_MAPPINGS = {}
24
+
25
+ # Import lora_manager nodes
26
+ try:
27
+ from .nodes.lora_manager import NODE_CLASS_MAPPINGS as LORA_MANAGER_NODE_CLASS_MAPPINGS
28
+ from .nodes.lora_manager import NODE_DISPLAY_NAME_MAPPINGS as LORA_MANAGER_NODE_DISPLAY_NAME_MAPPINGS
29
+ except ImportError as e:
30
+ print(f"Warning: Could not import lora_manager nodes: {e}")
31
+ LORA_MANAGER_NODE_CLASS_MAPPINGS = {}
32
+ LORA_MANAGER_NODE_DISPLAY_NAME_MAPPINGS = {}
33
+
34
+ # Import media_selection nodes
35
+ try:
36
+ from .nodes.media_selection.media_selection import MediaSelection
37
+ from .nodes.media_selection.frame_extractor import FrameExtractor
38
+ from .nodes.media_selection.multi_caption_combiner import MultiCaptionCombiner
39
+
40
+ MEDIA_SELECTION_NODE_CLASS_MAPPINGS = {
41
+ "MediaSelection": MediaSelection,
42
+ "FrameExtractor": FrameExtractor,
43
+ "MultiCaptionCombiner": MultiCaptionCombiner,
44
+ }
45
+ MEDIA_SELECTION_NODE_DISPLAY_NAME_MAPPINGS = {
46
+ "MediaSelection": "Media Selection",
47
+ "FrameExtractor": "Frame Extractor",
48
+ "MultiCaptionCombiner": "Multi-Caption Combiner",
49
+ }
50
+ except ImportError as e:
51
+ print(f"Warning: Could not import media_selection nodes: {e}")
52
+ MEDIA_SELECTION_NODE_CLASS_MAPPINGS = {}
53
+ MEDIA_SELECTION_NODE_DISPLAY_NAME_MAPPINGS = {}
54
+
55
+ # Register config API routes
56
+ try:
57
+ from .nodes.config_api import register_config_routes
58
+ from .nodes.restart_api import register_restart_routes
59
+ from server import PromptServer
60
+ app = getattr(PromptServer.instance, "app", None) or PromptServer.instance
61
+ if app:
62
+ register_config_routes(app)
63
+ register_restart_routes(app)
64
+ print("Swiss Army Knife: Registered config API routes")
65
+ except Exception as e:
66
+ print(f"Swiss Army Knife: Could not register config API routes: {e}")
67
+
68
+
69
+ # Get version from pyproject.toml for cache busting
70
+ def get_version():
71
+ try:
72
+ import tomllib
73
+ pyproject_path = os.path.join(os.path.dirname(__file__), "pyproject.toml")
74
+ with open(pyproject_path, "rb") as f:
75
+ data = tomllib.load(f)
76
+ return data["project"]["version"]
77
+ except Exception:
78
+ # Fallback to timestamp if version reading fails
79
+ import time
80
+ return str(int(time.time()))
81
+
82
+ # Combine main nodes, helper nodes, control panel, civit metadata helper, lora_manager, and media_selection nodes
83
+ NODE_CLASS_MAPPINGS = {
84
+ **MAIN_NODE_CLASS_MAPPINGS,
85
+ **HELPER_NODE_CLASS_MAPPINGS,
86
+ **CONTROL_PANEL_NODE_CLASS_MAPPINGS,
87
+ **CIVIT_METADATA_HELPER_NODE_CLASS_MAPPINGS,
88
+ **LORA_MANAGER_NODE_CLASS_MAPPINGS,
89
+ **MEDIA_SELECTION_NODE_CLASS_MAPPINGS
90
+ }
91
+ NODE_DISPLAY_NAME_MAPPINGS = {
92
+ **MAIN_NODE_DISPLAY_NAME_MAPPINGS,
93
+ **HELPER_NODE_DISPLAY_NAME_MAPPINGS,
94
+ **CONTROL_PANEL_NODE_DISPLAY_NAME_MAPPINGS,
95
+ **CIVIT_METADATA_HELPER_NODE_DISPLAY_NAME_MAPPINGS,
96
+ **LORA_MANAGER_NODE_DISPLAY_NAME_MAPPINGS,
97
+ **MEDIA_SELECTION_NODE_DISPLAY_NAME_MAPPINGS
98
+ }
99
+
100
+ WEB_DIRECTORY = "./web"
101
+ VERSION = get_version()
102
+
103
+ # Load DEBUG setting from environment
104
+ DEBUG = os.environ.get("DEBUG", "false").lower() in ("true", "1", "yes")
105
+
106
+ __all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY", "VERSION", "DEBUG"]
debug_civitai.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ CivitAI Integration Debug Helper
4
+
5
+ This script helps debug CivitAI integration issues in ComfyUI-SwissArmyKnife.
6
+ """
7
+
8
+ import os
9
+ import sys
10
+ sys.path.append(os.path.dirname(__file__))
11
+
12
+ def check_environment():
13
+ """Check environment setup for CivitAI integration"""
14
+ print("🔍 CivitAI Integration Debug Helper")
15
+ print("=" * 50)
16
+
17
+ # Check current directory
18
+ cwd = os.getcwd()
19
+ print(f"📁 Current directory: {cwd}")
20
+
21
+ # Check for .env files
22
+ env_files = ['.env', '.env.local', '.env.production']
23
+ print("\n📄 Environment Files:")
24
+
25
+ env_file_found = False
26
+ civitai_config_found = False
27
+
28
+ for env_file in env_files:
29
+ if os.path.exists(env_file):
30
+ env_file_found = True
31
+ print(f" ✅ Found: {env_file}")
32
+ try:
33
+ with open(env_file, 'r') as f:
34
+ content = f.read()
35
+ if 'CIVITAI' in content.upper():
36
+ civitai_config_found = True
37
+ print(" ✅ Contains CivitAI configuration")
38
+ # Show the lines with CIVITAI (masked)
39
+ for line_num, line in enumerate(content.split('\n'), 1):
40
+ if 'CIVITAI' in line.upper():
41
+ if '=' in line and not line.strip().startswith('#'):
42
+ key, value = line.split('=', 1)
43
+ masked_value = value[:8] + '...' + value[-4:] if len(value) > 12 else '***'
44
+ print(f" 📝 Line {line_num}: {key}={masked_value}")
45
+ else:
46
+ print(f" 📝 Line {line_num}: {line}")
47
+ else:
48
+ print(" ❌ No CivitAI configuration found")
49
+ except Exception as e:
50
+ print(f" ❌ Error reading file: {e}")
51
+ else:
52
+ print(f" ❌ Not found: {env_file}")
53
+
54
+ # Check environment variables
55
+ print("\n🌍 Environment Variables:")
56
+ civitai_vars = [k for k in os.environ.keys() if 'civit' in k.lower()]
57
+ if civitai_vars:
58
+ print(f" ✅ CivitAI-related variables found: {len(civitai_vars)}")
59
+ for var in civitai_vars:
60
+ value = os.environ[var]
61
+ masked_value = value[:8] + '...' + value[-4:] if len(value) > 12 else '***'
62
+ print(f" 📝 {var}={masked_value}")
63
+ else:
64
+ print(" ❌ No CivitAI-related environment variables found")
65
+
66
+ # Test service initialization
67
+ print("\n🔧 Service Test:")
68
+ try:
69
+ from nodes.civitai_service import CivitAIService
70
+ service = CivitAIService()
71
+ if service.api_key:
72
+ print(" ✅ CivitAI service initialized with API key")
73
+ else:
74
+ print(" ❌ CivitAI service has no API key")
75
+ except Exception as e:
76
+ print(f" ❌ Error initializing service: {e}")
77
+
78
+ # Recommendations
79
+ print("\n💡 Recommendations:")
80
+
81
+ if not env_file_found:
82
+ print(" 1. Create a .env file in your project root:")
83
+ print(" echo 'CIVITAI_API_KEY=your_api_key_here' > .env")
84
+ elif not civitai_config_found:
85
+ print(" 1. Add CivitAI API key to your .env file:")
86
+ print(" echo 'CIVITAI_API_KEY=your_api_key_here' >> .env")
87
+
88
+ if not civitai_vars:
89
+ print(" 2. Get your CivitAI API key from: https://civitai.com/user/account")
90
+ print(" 3. Set the environment variable or add to .env file")
91
+
92
+ print(" 4. Restart ComfyUI after setting the API key")
93
+ print(" 5. Test with a known LoRA file from CivitAI")
94
+
95
+ def test_api_key(api_key):
96
+ """Test a CivitAI API key"""
97
+ if not api_key:
98
+ print("❌ No API key provided")
99
+ return False
100
+
101
+ print(f"🧪 Testing API key: {api_key[:8]}...{api_key[-4:]}")
102
+
103
+ try:
104
+ import requests
105
+ url = "https://civitai.com/api/v1/models"
106
+ headers = {"Authorization": f"Bearer {api_key}"}
107
+
108
+ print("📡 Making test request to CivitAI API...")
109
+ response = requests.get(url, headers=headers, timeout=10, params={"limit": 1})
110
+
111
+ print(f"📊 Response status: {response.status_code}")
112
+
113
+ if response.status_code == 200:
114
+ print("✅ API key is valid!")
115
+ return True
116
+ elif response.status_code == 401:
117
+ print("❌ API key is invalid or expired")
118
+ return False
119
+ else:
120
+ print(f"⚠️ Unexpected response: {response.status_code}")
121
+ print(f"Response: {response.text[:200]}")
122
+ return False
123
+
124
+ except Exception as e:
125
+ print(f"❌ Error testing API key: {e}")
126
+ return False
127
+
128
+ if __name__ == "__main__":
129
+ if len(sys.argv) > 1:
130
+ # Test provided API key
131
+ api_key = sys.argv[1]
132
+ test_api_key(api_key)
133
+ else:
134
+ # Check environment
135
+ check_environment()
136
+
137
+ # Offer to test API key
138
+ api_key = os.environ.get("CIVITAI_API_KEY")
139
+ if api_key:
140
+ print("\n" + "="*50)
141
+ test_api_key(api_key)
docker-compose.yml ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ services:
2
+ comfyui:
3
+ build:
4
+ context: .
5
+ dockerfile: Dockerfile
6
+ ports:
7
+ - "8188:8188"
8
+ volumes:
9
+ # Mount your custom node directory
10
+ - .:/workspace/ComfyUI/custom_nodes/ComfyUI-SwissArmyKnife
11
+ # Mount user settings and workflows for persistence
12
+ - ./.comfyui/user:/workspace/ComfyUI/user
13
+ - ./.comfyui/models/loras:/workspace/ComfyUI/models/loras
14
+ environment:
15
+ # Pass through your Gemini API key
16
+ - GEMINI_API_KEY=${GEMINI_API_KEY}
17
+ - CIVITAI_API_KEY=${CIVITAI_API_KEY}
18
+ working_dir: /workspace/ComfyUI
19
+ command: python main.py --listen 0.0.0.0 --port 8188 --cpu --base-directory /workspace/ComfyUI
20
+ stdin_open: true
21
+ tty: true
docs/CONSOLIDATION_SUMMARY.md ADDED
@@ -0,0 +1,289 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Documentation Consolidation Summary
2
+
3
+ **Date**: October 8, 2025
4
+ **Task**: Consolidate and organize documentation in the `docs` folder
5
+
6
+ ---
7
+
8
+ ## Overview
9
+
10
+ Successfully consolidated fragmented documentation files into comprehensive, well-organized documents. This improves discoverability, reduces redundancy, and makes the documentation easier to maintain.
11
+
12
+ ---
13
+
14
+ ## Consolidations Performed
15
+
16
+ ### 1. Features - JavaScript Improvements
17
+
18
+ **Consolidated into**: `features/JAVASCRIPT_IMPROVEMENTS.md`
19
+
20
+ **Source files removed**:
21
+
22
+ - ✅ `JAVASCRIPT_CACHE_BUSTING.md`
23
+ - ✅ `JAVASCRIPT_ERROR_FIX.md`
24
+ - ✅ `JAVASCRIPT_NODE_NAME_UPDATE.md`
25
+
26
+ **Content includes**:
27
+
28
+ - Cache busting implementation (version-based, hash-based, timestamp-based)
29
+ - Module loading error resolution
30
+ - Node name updates (GeminiUtilMediaDescribe → MediaDescribe)
31
+ - Development utilities and debugging tips
32
+
33
+ ### 2. UI Widgets - Control Panel
34
+
35
+ **Consolidated into**: `ui-widgets/CONTROL_PANEL.md`
36
+
37
+ **Source files removed**:
38
+
39
+ - ✅ `CONTROL_PANEL_IMPLEMENTATION.md`
40
+ - ✅ `CONTROL_PANEL_JSON_DATA_FIX.md`
41
+
42
+ **Content includes**:
43
+
44
+ - Complete implementation details (Python and JavaScript)
45
+ - JSON data format handling
46
+ - Two-column layout system
47
+ - Usage instructions and troubleshooting
48
+ - Known limitations and future enhancements
49
+
50
+ ### 3. UI Widgets - Dimensions Display
51
+
52
+ **Consolidated into**: `ui-widgets/DIMENSIONS_DISPLAY.md`
53
+
54
+ **Source files removed**:
55
+
56
+ - ✅ `DIMENSIONS_DISPLAY_WIDGET.md`
57
+ - ✅ `DIMENSIONS_DISPLAY_TROUBLESHOOTING.md`
58
+
59
+ **Content includes**:
60
+
61
+ - Widget implementation and message structure handling
62
+ - API event handler integration
63
+ - Comprehensive troubleshooting guide
64
+ - Testing procedures and expected behavior
65
+ - Multiple message format support
66
+
67
+ ### 4. UI Widgets - Seed Widget
68
+
69
+ **Consolidated into**: `ui-widgets/SEED_WIDGET.md`
70
+
71
+ **Source files removed**:
72
+
73
+ - ✅ `SEED_WIDGET_IMPLEMENTATION.md`
74
+ - ✅ `SEED_WIDGET_RANDOMIZATION_FIX.md`
75
+
76
+ **Content includes**:
77
+
78
+ - Problem solved (ComfyUI execution caching)
79
+ - Implementation details (Python and JavaScript)
80
+ - Usage instructions for reproducible workflows
81
+ - Technical benefits and seed range information
82
+
83
+ ### 5. UI Widgets - General Widget Fixes
84
+
85
+ **Consolidated into**: `ui-widgets/WIDGET_FIXES.md`
86
+
87
+ **Source files removed**:
88
+
89
+ - ✅ `WIDGET_INVESTIGATION_AND_FIXES.md`
90
+ - ✅ `FINAL_STRING_WIDGET_FIX.md`
91
+ - ✅ `WIDGET_STATE_PERSISTENCE_FIX.md`
92
+
93
+ **Content includes**:
94
+
95
+ - Widget visibility investigation and fixes
96
+ - Final string widget update handling
97
+ - Widget state persistence with onSerialize/onConfigure
98
+ - Upload widget management improvements
99
+
100
+ ---
101
+
102
+ ## README Updates
103
+
104
+ ### Updated Files
105
+
106
+ 1. **`docs/README.md`** - Main documentation index
107
+ - Updated UI Widgets section with consolidated file references
108
+ - Updated Features section with JavaScript Improvements reference
109
+ - Clearer organization and better links
110
+
111
+ 2. **`docs/features/README.md`** - Features index
112
+ - Added JavaScript & Infrastructure category
113
+ - Consolidated JavaScript files into single entry
114
+ - Improved categorization and descriptions
115
+
116
+ 3. **`docs/ui-widgets/README.md`** - UI Widgets index
117
+ - Replaced individual file listings with consolidated references
118
+ - Added detailed feature descriptions for each widget
119
+ - Improved widget categories and implementation patterns
120
+
121
+ ---
122
+
123
+ ## Benefits
124
+
125
+ ### 1. Better Organization
126
+
127
+ - **Before**: 12 fragmented files across features and ui-widgets
128
+ - **After**: 5 comprehensive, well-structured documents
129
+ - **Reduction**: 58% fewer files to maintain
130
+
131
+ ### 2. Improved Discoverability
132
+
133
+ - Related content now in single files
134
+ - Clear table of contents in each document
135
+ - Better cross-references between related topics
136
+
137
+ ### 3. Reduced Redundancy
138
+
139
+ - Eliminated duplicate information across files
140
+ - Consolidated related fixes and improvements
141
+ - Single source of truth for each topic
142
+
143
+ ### 4. Easier Maintenance
144
+
145
+ - Fewer files to keep in sync
146
+ - Comprehensive documents easier to update
147
+ - Clear structure for adding new content
148
+
149
+ ### 5. Better User Experience
150
+
151
+ - One-stop documentation for each topic
152
+ - No need to jump between multiple files
153
+ - Complete context in each document
154
+
155
+ ---
156
+
157
+ ## File Structure Summary
158
+
159
+ ### Before Consolidation
160
+
161
+ ```
162
+ docs/
163
+ ├── features/
164
+ │ ├── JAVASCRIPT_CACHE_BUSTING.md ❌ Removed
165
+ │ ├── JAVASCRIPT_ERROR_FIX.md ❌ Removed
166
+ │ ├── JAVASCRIPT_NODE_NAME_UPDATE.md ❌ Removed
167
+ │ └── [other feature files]
168
+ └── ui-widgets/
169
+ ├── CONTROL_PANEL_IMPLEMENTATION.md ❌ Removed
170
+ ├── CONTROL_PANEL_JSON_DATA_FIX.md ❌ Removed
171
+ ├── DIMENSIONS_DISPLAY_WIDGET.md ❌ Removed
172
+ ├── DIMENSIONS_DISPLAY_TROUBLESHOOTING.md ❌ Removed
173
+ ├── SEED_WIDGET_IMPLEMENTATION.md ❌ Removed
174
+ ├── SEED_WIDGET_RANDOMIZATION_FIX.md ❌ Removed
175
+ ├── WIDGET_INVESTIGATION_AND_FIXES.md ❌ Removed
176
+ ├── FINAL_STRING_WIDGET_FIX.md ❌ Removed
177
+ ├── WIDGET_STATE_PERSISTENCE_FIX.md ❌ Removed
178
+ └── [other widget files]
179
+ ```
180
+
181
+ ### After Consolidation
182
+
183
+ ```
184
+ docs/
185
+ ├── features/
186
+ │ ├── JAVASCRIPT_IMPROVEMENTS.md ✅ New (consolidated)
187
+ │ └── [other feature files]
188
+ └── ui-widgets/
189
+ ├── CONTROL_PANEL.md ✅ New (consolidated)
190
+ ├── DIMENSIONS_DISPLAY.md ✅ New (consolidated)
191
+ ├── SEED_WIDGET.md ✅ New (consolidated)
192
+ ├── WIDGET_FIXES.md ✅ New (consolidated)
193
+ └── [other widget files]
194
+ ```
195
+
196
+ ---
197
+
198
+ ## Document Characteristics
199
+
200
+ All consolidated documents include:
201
+
202
+ 1. **Clear Title and Metadata**
203
+ - Last updated date
204
+ - Related nodes/components
205
+ - Status information
206
+
207
+ 2. **Table of Contents**
208
+ - Easy navigation within document
209
+ - Clear section organization
210
+
211
+ 3. **Comprehensive Coverage**
212
+ - Problem description
213
+ - Solution implementation
214
+ - Usage instructions
215
+ - Troubleshooting guides
216
+ - Technical details
217
+
218
+ 4. **Related Documentation Links**
219
+ - Cross-references to relevant docs
220
+ - Integration guides
221
+ - Related feature documentation
222
+
223
+ 5. **Practical Examples**
224
+ - Code snippets
225
+ - Testing procedures
226
+ - Expected behavior descriptions
227
+
228
+ ---
229
+
230
+ ## Next Steps
231
+
232
+ ### Recommended Future Consolidations
233
+
234
+ Consider consolidating these areas in future:
235
+
236
+ 1. **LoRA Loader Documentation** (16 files)
237
+ - Could be organized into 3-4 comprehensive documents
238
+ - Implementation guide, variants, and integrations
239
+
240
+ 2. **Media Describe Documentation** (20 files)
241
+ - Could consolidate override-related files
242
+ - Prompt breakdown files could be merged
243
+ - API and utility files could be combined
244
+
245
+ 3. **Caching Infrastructure** (6 files)
246
+ - Could merge verification summaries
247
+ - Combine optimization and busting guides
248
+
249
+ ### Maintenance Guidelines
250
+
251
+ 1. **When adding new documentation**:
252
+ - Check if it fits into existing consolidated files
253
+ - Only create new files for distinct new features
254
+ - Update README files to reflect additions
255
+
256
+ 2. **When updating documentation**:
257
+ - Update consolidated files, not individual fragments
258
+ - Keep table of contents current
259
+ - Update cross-references as needed
260
+
261
+ 3. **Regular reviews**:
262
+ - Quarterly review for consolidation opportunities
263
+ - Remove obsolete documentation
264
+ - Update organization as project evolves
265
+
266
+ ---
267
+
268
+ ## Statistics
269
+
270
+ - **Files consolidated**: 12 → 5 (58% reduction)
271
+ - **Updated README files**: 3
272
+ - **New comprehensive documents**: 5
273
+ - **Improved cross-references**: 15+
274
+ - **Better organization**: ✅
275
+
276
+ ---
277
+
278
+ ## Conclusion
279
+
280
+ The documentation consolidation successfully:
281
+
282
+ ✅ Reduced file count by 58%
283
+ ✅ Improved discoverability and navigation
284
+ ✅ Eliminated redundancy and duplication
285
+ ✅ Created comprehensive, well-structured documents
286
+ ✅ Updated all README files for consistency
287
+ ✅ Established better documentation patterns
288
+
289
+ The documentation is now more organized, easier to maintain, and provides a better experience for developers and users alike.
docs/DOCUMENTATION_REORGANIZATION.md ADDED
@@ -0,0 +1,297 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Documentation Reorganization Summary
2
+
3
+ **Date**: October 2, 2025
4
+ **Version**: 2.0
5
+
6
+ ## Overview
7
+
8
+ Reorganized the documentation structure from a flat list of 70+ markdown files into a well-organized hierarchical structure with dedicated folders for each major component.
9
+
10
+ ## New Structure
11
+
12
+ ```
13
+ docs/
14
+ ├── README.md # Main documentation index (NEW)
15
+ ├── IMPLEMENTATION_STATUS.md # Overall project status (ROOT)
16
+
17
+ ├── nodes/ # Node-specific documentation
18
+ │ ├── video-preview/ # Video Preview node (6 files)
19
+ │ │ ├── README.md
20
+ │ │ ├── VIDEO_PREVIEW_NODE.md
21
+ │ │ ├── VIDEO_PREVIEW_IMPLEMENTATION_SUMMARY.md
22
+ │ │ ├── VIDEO_PREVIEW_JS_MIGRATION.md
23
+ │ │ ├── VIDEO_PREVIEW_PROGRESSIVE_LOADING.md
24
+ │ │ ├── VIDEO_PREVIEW_TYPEERROR_FIX.md
25
+ │ │ └── CLEAR_VIDEO_PREVIEW_FUNCTION_ORDER_FIX.md
26
+ │ │
27
+ │ ├── video-metadata/ # Video Metadata node (3 files)
28
+ │ │ ├── README.md
29
+ │ │ ├── VIDEO_METADATA_NODE.md
30
+ │ │ ├── VIDEO_METADATA_JSON_INTEGRATION.md
31
+ │ │ ├── UPDATE_VIDEO_METADATA_APPEND_FUNCTIONALITY.md
32
+ │ │ └── VHS_VIDEOCOMBINE_COMPATIBILITY_FIX.md
33
+ │ │
34
+ │ ├── media-describe/ # Gemini AI Media Description (6 files)
35
+ │ │ ├── README.md
36
+ │ │ ├── gemini-prompts.md
37
+ │ │ ├── ALL_MEDIA_DESCRIBE_DATA_OUTPUT.md
38
+ │ │ ├── CLASS_RENAME_MEDIADESCRIBE.md
39
+ │ │ ├── GEMINI_API_500_ERROR_FIX.md
40
+ │ │ ├── GEMINI_API_RETRY_LOGIC.md
41
+ │ │ └── GEMINI_UTILS_REFACTORING_PLAN.md
42
+ │ │
43
+ │ ├── lora-loader/ # LoRA Loader node (14 files)
44
+ │ │ ├── README.md
45
+ │ │ ├── SUPERLORA_IMPLEMENTATION_GUIDE.md
46
+ │ │ ├── SUPERLORA_CLARIFICATION.md
47
+ │ │ ├── SUPER_LORA_LOADER_VARIANTS.md
48
+ │ │ ├── DUAL_LORA_PANEL_IMPLEMENTATION.md
49
+ │ │ ├── SUPERLORA_SINGLE_PANEL_IMPLEMENTATION.md
50
+ │ │ ├── SUPERLORA_SINGLE_STREAM_IMPLEMENTATION.md
51
+ │ │ ├── LORA_METADATA_INTEGRATION.md
52
+ │ │ ├── LORA_MANAGER_INTEGRATION.md
53
+ │ │ ├── LORA_STACK_METADATA_ENHANCEMENT.md
54
+ │ │ ├── LORA_JSON_CLEANUP.md
55
+ │ │ ├── LORA_JSON_WORKFLOW_SERIALIZATION.md
56
+ │ │ ├── MULTIPLE_LORA_SUPPORT.md
57
+ │ │ ├── SUPERLORA_WANVIDLORA_UPDATE.md
58
+ │ │ ├── WAN_MODEL_TYPE_SELECTION.md
59
+ │ │ └── SUPERLORA_PLUS_BUTTON_FIX.md
60
+ │ │
61
+ │ └── reddit-media/ # Reddit Media Extraction (6 files)
62
+ │ ├── README.md
63
+ │ ├── REDDIT_POST_MEDIA_SOURCE.md
64
+ │ ├── REDDIT_URL_WIDGET_PERSISTENCE_BUG_FIX.md
65
+ │ ├── REDDIT_URL_WIDGET_VISIBILITY_FIX.md
66
+ │ ├── REDGIFS_EXTRACTION_FIX.md
67
+ │ ├── VIDEO_TRIMMING_REDGIFS_FIX.md
68
+ │ └── JAVASCRIPT_REDDIT_POST_FIX.md
69
+
70
+ ├── infrastructure/ # Infrastructure & System Components
71
+ │ ├── caching/ # Caching system (6 files)
72
+ │ │ ├── README.md
73
+ │ │ ├── CACHING.md
74
+ │ │ ├── CACHE_OPTIMIZATION_FIX.md
75
+ │ │ ├── CACHE_BUSTING_SUMMARY.md
76
+ │ │ ├── CACHE_VERIFICATION_OCTOBER_2025.md
77
+ │ │ └── CACHE_VERIFICATION_SUMMARY.md
78
+ │ │
79
+ │ ├── debug/ # Debug & Logging (2 files)
80
+ │ │ ├── README.md
81
+ │ │ ├── DEBUG_MODE_IMPLEMENTATION.md
82
+ │ │ └── UNIFIED_DEBUG_SYSTEM.md
83
+ │ │
84
+ │ ├── docker/ # Docker setup (2 files)
85
+ │ │ ├── README.md
86
+ │ │ ├── DOCKER_DEVELOPMENT_SETUP.md
87
+ │ │ └── DOCKER_COMFYUI_MANAGER_FIX.md
88
+ │ │
89
+ │ └── build-deploy/ # Build & Publishing (3 files)
90
+ │ ├── README.md
91
+ │ ├── PUBLISHING_WORKFLOW.md
92
+ │ ├── PYTHON_PACKAGE_BUILD_FIX.md
93
+ │ └── GET_VERSION_IMPORT_FIX.md
94
+
95
+ ├── integrations/ # External Service Integrations
96
+ │ └── civitai/ # CivitAI API (3 files)
97
+ │ ├── README.md
98
+ │ ├── CIVITAI_API_KEY_WIDGET.md
99
+ │ ├── CIVITAI_SERVICE_CONSOLIDATION.md
100
+ │ └── MULTIPLE_HASH_TYPES_CIVITAI_INTEGRATION.md
101
+
102
+ ├── ui-widgets/ # UI Components (9 files)
103
+ │ ├── README.md
104
+ │ ├── CONTROL_PANEL_IMPLEMENTATION.md
105
+ │ ├── CONTROL_PANEL_JSON_DATA_FIX.md
106
+ │ ├── DIMENSIONS_DISPLAY_WIDGET.md
107
+ │ ├── DIMENSIONS_DISPLAY_TROUBLESHOOTING.md
108
+ │ ├── SEED_WIDGET_IMPLEMENTATION.md
109
+ │ ├── SEED_WIDGET_RANDOMIZATION_FIX.md
110
+ │ ├── FINAL_STRING_WIDGET_FIX.md
111
+ │ ├── WIDGET_INVESTIGATION_AND_FIXES.md
112
+ │ └── WIDGET_STATE_PERSISTENCE_FIX.md
113
+
114
+ ├── features/ # Feature Implementations (13 files)
115
+ │ ├── README.md
116
+ │ ├── CHANGE_CLOTHING_COLOR_FEATURE.md
117
+ │ ├── CLOTHING_TEXT_EXCLUSION.md
118
+ │ ├── TWERKING_ACTION_REPLACEMENT.md
119
+ │ ├── DECISIVENESS_IMPROVEMENTS.md
120
+ │ ├── CONFIGURABLE_OPTIONS_GUIDE.md
121
+ │ ├── JSON_OUTPUT_FORMAT.md
122
+ │ ├── ND_SUPER_NODES_FORK_SUMMARY.md
123
+ │ ├── ND_SUPER_NODES_UPDATE_REMOVAL.md
124
+ │ ├── ASYNC_EVENT_LOOP_FIX.md
125
+ │ ├── JAVASCRIPT_CACHE_BUSTING.md
126
+ │ ├── JAVASCRIPT_ERROR_FIX.md
127
+ │ ├── JAVASCRIPT_NODE_NAME_UPDATE.md
128
+ │ └── JAVASCRIPT_CACHE_BUSTING.md
129
+
130
+ └── examples/ # Examples & Workflows (2 files)
131
+ ├── README.md
132
+ ├── example_workflow.json
133
+ └── WORKFLOW_DEMO.md
134
+ ```
135
+
136
+ ## Files Organized
137
+
138
+ ### Total Count
139
+
140
+ - **70+ documentation files** organized into **7 major categories**
141
+ - **11 index README.md files** created for navigation
142
+ - **1 main README.md** for the docs directory
143
+
144
+ ### By Category
145
+
146
+ 1. **Nodes** (35 files across 5 node types)
147
+ - Video Preview: 6 files
148
+ - Video Metadata: 4 files
149
+ - Media Describe: 6 files
150
+ - LoRA Loader: 14 files
151
+ - Reddit Media: 6 files
152
+
153
+ 2. **Infrastructure** (13 files across 4 categories)
154
+ - Caching: 6 files
155
+ - Debug: 2 files
156
+ - Docker: 2 files
157
+ - Build/Deploy: 3 files
158
+
159
+ 3. **Integrations** (3 files)
160
+ - CivitAI: 3 files
161
+
162
+ 4. **UI Widgets** (9 files)
163
+
164
+ 5. **Features** (13 files)
165
+
166
+ 6. **Examples** (2 files)
167
+
168
+ ## Benefits
169
+
170
+ ### Improved Navigation
171
+
172
+ - **Before**: Scroll through 70+ files in a single directory
173
+ - **After**: Browse by category, then specific component
174
+
175
+ ### Better Discoverability
176
+
177
+ - Index README in each folder explains what's inside
178
+ - Cross-references between related documentation
179
+ - Clear naming hierarchy
180
+
181
+ ### Maintainability
182
+
183
+ - New docs go in the appropriate folder
184
+ - Related docs are co-located
185
+ - Easier to identify outdated or duplicate content
186
+
187
+ ### Developer Experience
188
+
189
+ - Find node-specific docs quickly
190
+ - Understand system architecture from folder structure
191
+ - Clear separation of concerns
192
+
193
+ ## Migration Notes
194
+
195
+ ### What Changed
196
+
197
+ - **70+ files moved** from flat structure to categorized folders
198
+ - **11 index files created** for navigation
199
+ - **1 main README** provides documentation overview
200
+ - **No files deleted** - all original content preserved
201
+
202
+ ### What Stayed the Same
203
+
204
+ - **File names unchanged** - easier to find moved files
205
+ - **File content unchanged** - no content modifications
206
+ - **Links may need updating** - internal cross-references may need path updates
207
+
208
+ ## Next Steps
209
+
210
+ ### Recommended Actions
211
+
212
+ 1. **Update Internal Links**: Many docs have cross-references that need path updates
213
+ - Example: Change `[Doc](DOC.md)` to `[Doc](../category/DOC.md)`
214
+
215
+ 2. **Consolidate Related Docs**: Some files could be merged
216
+ - Video Preview files could be consolidated
217
+ - LoRA Loader documentation could be streamlined
218
+
219
+ 3. **Create Node Guides**: Each node should have:
220
+ - Implementation guide
221
+ - User guide
222
+ - API reference
223
+ - Troubleshooting guide
224
+
225
+ 4. **Add Visual Aids**: Consider adding:
226
+ - Architecture diagrams
227
+ - Flow charts
228
+ - Screenshot examples
229
+ - Code snippets
230
+
231
+ 5. **Version Control**: Track documentation versions alongside code versions
232
+
233
+ ## Finding Documents
234
+
235
+ ### By Topic
236
+
237
+ - **Node documentation**: `docs/nodes/[node-name]/`
238
+ - **System infrastructure**: `docs/infrastructure/[category]/`
239
+ - **External integrations**: `docs/integrations/[service]/`
240
+ - **UI components**: `docs/ui-widgets/`
241
+ - **Features**: `docs/features/`
242
+
243
+ ### By Type
244
+
245
+ - **Implementation guides**: Look for `*_IMPLEMENTATION.md`
246
+ - **Bug fixes**: Look for `*_FIX.md`
247
+ - **Troubleshooting**: Look for `*_TROUBLESHOOTING.md`
248
+ - **Integration guides**: Look for `*_INTEGRATION.md`
249
+
250
+ ### Quick Access
251
+
252
+ 1. Start at `docs/README.md`
253
+ 2. Browse to appropriate category
254
+ 3. Check category's `README.md` for file list
255
+ 4. Open specific documentation file
256
+
257
+ ## Documentation Standards
258
+
259
+ ### File Naming
260
+
261
+ - Keep existing ALL_CAPS_WITH_UNDERSCORES format
262
+ - Use descriptive names
263
+ - Include type suffix (`_FIX`, `_IMPLEMENTATION`, etc.)
264
+
265
+ ### Folder Naming
266
+
267
+ - Use lowercase-with-dashes
268
+ - Clear, descriptive names
269
+ - Group by functionality, not file type
270
+
271
+ ### README Files
272
+
273
+ Each folder should have a `README.md` that includes:
274
+
275
+ - Overview of folder contents
276
+ - List of documentation files with descriptions
277
+ - Quick reference guide
278
+ - Related documentation links
279
+ - Status and category information
280
+
281
+ ## Conclusion
282
+
283
+ The documentation is now organized in a logical, hierarchical structure that makes it easier to:
284
+
285
+ - Find relevant documentation
286
+ - Understand the project architecture
287
+ - Contribute new documentation
288
+ - Maintain existing documentation
289
+
290
+ The reorganization preserves all existing content while providing a much better navigation and discovery experience.
291
+
292
+ ---
293
+
294
+ **Reorganization Date**: October 2, 2025
295
+ **Files Reorganized**: 70+
296
+ **New Structure Version**: 2.0
297
+ **Status**: Complete
docs/IMPLEMENTATION_STATUS.md ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # MediaDescribe Implementation Summary
2
+
3
+ ## ✅ COMPLETED SUCCESSFULLY
4
+
5
+ ### 1. Python Backend Implementation
6
+
7
+ - **File**: `nodes/nodes.py`
8
+ - **Status**: ✅ Working correctly
9
+ - **Features**:
10
+ - Clean MediaDescribe class with proper INPUT_TYPES structure
11
+ - Support for media_source: "Upload Media" vs "Randomize Media from Path"
12
+ - Support for media_type: "image" vs "video"
13
+ - Proper error handling for missing inputs
14
+ - File randomization logic using glob patterns
15
+ - All existing GeminiVideoDescribe and GeminiImageDescribe classes preserved
16
+
17
+ ### 2. JavaScript Frontend Implementation
18
+
19
+ - **File**: `web/js/gemini_widgets.js`
20
+ - **Status**: ✅ Working correctly
21
+ - **Features**:
22
+ - Dynamic UI widgets that show/hide based on media_source selection
23
+ - Upload widgets appear when "Upload Media" is selected
24
+ - Path input appears when "Randomize Media from Path" is selected
25
+ - Proper widget management and event handling
26
+
27
+ ### 3. Input Parameters Structure
28
+
29
+ ```javascript
30
+ Required:
31
+ - gemini_api_key (STRING)
32
+ - gemini_model (["models/gemini-2.5-flash", "models/gemini-2.5-flash-lite", "models/gemini-2.5-pro"])
33
+ - model_type (["Text2Image", "ImageEdit"])
34
+ - description_mode (["Describe without clothing", "Describe with clothing", ...])
35
+ - prefix_text (STRING, multiline)
36
+ - media_source (["Upload Media", "Randomize Media from Path"]) ⭐ NEW
37
+ - media_type (["image", "video"]) ⭐ NEW
38
+
39
+ Optional:
40
+ - image (IMAGE tensor)
41
+ - media_path (STRING) ⭐ NEW
42
+ - uploaded_image_file (STRING) ⭐ NEW
43
+ - uploaded_video_file (STRING) ⭐ NEW
44
+ ```
45
+
46
+ ### 4. Functionality Tests
47
+
48
+ - ✅ Python imports work correctly
49
+ - ✅ Node class definitions are valid
50
+ - ✅ INPUT_TYPES structure is properly formatted
51
+ - ✅ Error handling works for missing inputs
52
+ - ✅ Function calls execute without syntax errors
53
+ - ✅ Package initialization still works
54
+
55
+ ### 5. Return Values
56
+
57
+ The node returns 3 outputs:
58
+
59
+ 1. **description**: The generated description or error message
60
+ 2. **gemini_status**: Detailed status information with emoji indicators
61
+ 3. **final_string**: Concatenated prefix_text + description
62
+
63
+ ## 🎯 CURRENT STATUS: READY FOR TESTING
64
+
65
+ The consolidated MediaDescribe node (GeminiUtilMediaDescribe) is now fully implemented and ready for UI testing in ComfyUI. The implementation supports:
66
+
67
+ 1. **Upload Media Mode**: Users can upload images/videos via widgets
68
+ 2. **Randomize Media from Path Mode**: Users can specify a directory path and the node will randomly select a file
69
+ 3. **Dynamic UI**: The interface adapts based on user selections
70
+ 4. **Proper Error Handling**: Clear error messages for missing inputs or invalid paths
71
+ 5. **Testing Framework**: Basic validation returns test responses
72
+
73
+ ## 🔜 NEXT STEPS
74
+
75
+ 1. Test the node in ComfyUI interface to verify widget behavior
76
+ 2. Implement actual Gemini API processing (currently returns test responses)
77
+ 3. Add file validation and additional media format support
78
+ 4. Test random file selection with actual media directories
79
+
80
+ ---
81
+
82
+ # VERSION 1.3.0 STATUS - LoRA INTEGRATION & VHS COMPATIBILITY
83
+
84
+ ## ✅ COMPLETED FEATURES (Version 1.3.0)
85
+
86
+ ### Multiple LoRA Support & JSON Integration
87
+
88
+ - **Status**: ✅ **COMPLETE** - Production Ready
89
+ - **Implementation**: Enhanced LoRAInfoExtractor to process WANVIDLORA list format from WanVideo Lora Select Multi node
90
+ - **Features**:
91
+ - Multiple LoRA processing with structured JSON output
92
+ - VideoMetadataNode integration with LoRA JSON input
93
+ - Automatic metadata generation from LoRA data
94
+ - CivitAI API integration for LoRA metadata lookup
95
+ - **Testing**: ✅ Comprehensive end-to-end testing completed
96
+ - **Documentation**: ✅ Complete in `MULTIPLE_LORA_SUPPORT.md`, `JSON_OUTPUT_FORMAT.md`, `VIDEO_METADATA_JSON_INTEGRATION.md`
97
+
98
+ ### VHS VideoCombine Compatibility
99
+
100
+ - **Status**: ✅ **COMPLETE** - Production Ready
101
+ - **Implementation**: Updated VideoMetadataNode to use VHS_FILENAMES type for full VHS ecosystem compatibility
102
+ - **Solution**: Fixed input/output types to match VHS VideoCombine (VHS_FILENAMES → VHS_FILENAMES)
103
+ - **Testing**: ✅ All integration tests passed - complete workflow verified
104
+ - **Documentation**: ✅ Complete in `VHS_VIDEOCOMBINE_COMPATIBILITY_FIX.md`
105
+
106
+ ### Complete Workflow Chain Verified
107
+
108
+ ```
109
+ WAN Video Lora Select Multi → WANVIDLORA list
110
+
111
+ LoRAInfoExtractor → (JSON_STRING, info_text, passthrough)
112
+
113
+ VHS VideoCombine → VHS_FILENAMES
114
+
115
+ VideoMetadataNode → VHS_FILENAMES
116
+
117
+ [Other VHS nodes] → Compatible chaining
118
+ ```
119
+
120
+ ## 🎯 VERSION 1.3.0 READY FOR RELEASE
121
+
122
+ All features tested and documented. Full compatibility achieved with:
123
+
124
+ - ✅ Multiple LoRA processing from WANVIDLORA
125
+ - ✅ Structured JSON output with metadata
126
+ - ✅ VideoMetadataNode simplified inputs
127
+ - ✅ VHS VideoCombine compatibility (VHS_FILENAMES type)
128
+ - ✅ FFmpeg metadata embedding
129
+ - ✅ Full workflow integration
130
+
131
+ ## 📁 Files Modified
132
+
133
+ - `nodes/nodes.py` - Clean implementation with all three node classes
134
+ - `web/js/gemini_widgets.js` - Dynamic UI widgets (already working)
135
+ - `nodes/nodes_corrupted_backup.py` - Backup of broken version
136
+ - `nodes/nodes_clean.py` - Clean working version (used to restore nodes.py)
docs/README.md ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ComfyUI-SwissArmyKnife Documentation
2
+
3
+ Welcome to the ComfyUI-SwissArmyKnife documentation! This directory contains comprehensive documentation for all nodes, features, integrations, and infrastructure components.
4
+
5
+ ## 📁 Documentation Structure
6
+
7
+ ### 🎬 Nodes (`/nodes`)
8
+
9
+ Core custom nodes that extend ComfyUI functionality:
10
+
11
+ - **[video-preview](nodes/video-preview/)** - Video preview widget for comparing multiple videos side-by-side
12
+ - **[video-metadata](nodes/video-metadata/)** - Video metadata extraction and manipulation
13
+ - **[media-describe](nodes/media-describe/)** - AI-powered media description using Gemini API
14
+ - **[lora-loader](nodes/lora-loader/)** - Advanced LoRA loading with metadata integration
15
+ - **[reddit-media](nodes/reddit-media/)** - Reddit and RedGifs media extraction and processing
16
+
17
+ ### 🏗️ Infrastructure (`/infrastructure`)
18
+
19
+ Core system components and development tools:
20
+
21
+ - **[caching](infrastructure/caching/)** - Caching strategies and optimization
22
+ - **[debug](infrastructure/debug/)** - Debug mode and logging systems
23
+ - **[docker](infrastructure/docker/)** - Docker setup and container configuration
24
+ - **[build-deploy](infrastructure/build-deploy/)** - Build processes and publishing workflows
25
+
26
+ ### 🔌 Integrations (`/integrations`)
27
+
28
+ External service integrations:
29
+
30
+ - **[civitai](integrations/civitai/)** - CivitAI API integration for model metadata
31
+ - **[reddit](integrations/reddit/)** - Reddit API integration (see also nodes/reddit-media)
32
+
33
+ ### 🎨 UI Widgets (`/ui-widgets`)
34
+
35
+ Reusable UI components and widgets:
36
+
37
+ - **[Control Panel](ui-widgets/CONTROL_PANEL.md)** - Dashboard widget with JSON data handling and two-column layout
38
+ - **[Dimensions Display](ui-widgets/DIMENSIONS_DISPLAY.md)** - Automatic media dimension display with troubleshooting
39
+ - **[Seed Widget](ui-widgets/SEED_WIDGET.md)** - Randomization seed for reproducible workflows
40
+ - **[Widget Fixes](ui-widgets/WIDGET_FIXES.md)** - Visibility management, state persistence, and general fixes
41
+
42
+ ### ✨ Features (`/features`)
43
+
44
+ Feature implementations and enhancements:
45
+
46
+ - **[JavaScript Improvements](features/JAVASCRIPT_IMPROVEMENTS.md)** - Cache busting, module fixes, and node naming updates
47
+ - Clothing color modification and text exclusion
48
+ - Text exclusion and filtering
49
+ - Prompt improvements and decisiveness
50
+ - External integrations (ND Super Nodes)
51
+
52
+ ### 📚 Examples (`/examples`)
53
+
54
+ Example workflows and demonstrations:
55
+
56
+ - Sample workflow JSON files
57
+ - Usage demonstrations
58
+ - Integration examples
59
+
60
+ ## 🚀 Quick Start
61
+
62
+ ### For Developers
63
+
64
+ 1. **Node Development**: See individual node documentation in `/nodes/[node-name]/`
65
+ 2. **Adding Features**: Check `/features/` for implementation patterns
66
+ 3. **Integration**: Review `/integrations/` for external API integration guides
67
+ 4. **Infrastructure**: Consult `/infrastructure/` for system-level changes
68
+
69
+ ### For Users
70
+
71
+ 1. **Node Usage**: Each node folder contains usage guides and examples
72
+ 2. **Troubleshooting**: Look for `*_FIX.md` or `*_TROUBLESHOOTING.md` files
73
+ 3. **Examples**: Check `/examples/` for workflow demonstrations
74
+
75
+ ## 📖 Documentation Conventions
76
+
77
+ ### File Naming
78
+
79
+ - **Implementation Guides**: `[FEATURE]_IMPLEMENTATION.md` or `[NODE]_NODE.md`
80
+ - **Bug Fixes**: `[ISSUE]_FIX.md`
81
+ - **Troubleshooting**: `[FEATURE]_TROUBLESHOOTING.md`
82
+ - **Integration Guides**: `[SERVICE]_INTEGRATION.md`
83
+ - **API Documentation**: `[FEATURE]_API.md`
84
+
85
+ ### Document Structure
86
+
87
+ Each documentation file should include:
88
+
89
+ 1. **Problem Statement** - What issue does this address?
90
+ 2. **Solution** - How was it solved?
91
+ 3. **Implementation Details** - Technical specifics
92
+ 4. **Usage/Testing** - How to use or test the feature
93
+ 5. **Related Files** - Links to relevant code files
94
+ 6. **Implementation Date** - When was this implemented?
95
+
96
+ ## 🔍 Finding Documentation
97
+
98
+ ### By Topic
99
+
100
+ - **Video Processing**: Check `/nodes/video-preview/` and `/nodes/video-metadata/`
101
+ - **AI/ML Features**: See `/nodes/media-describe/` and `/nodes/lora-loader/`
102
+ - **External APIs**: Look in `/integrations/`
103
+ - **Performance**: Check `/infrastructure/caching/`
104
+ - **Debugging**: See `/infrastructure/debug/`
105
+
106
+ ### By Issue Type
107
+
108
+ - **Bugs/Fixes**: Search for `*_FIX.md` files
109
+ - **New Features**: Look for `*_IMPLEMENTATION.md` files
110
+ - **API Changes**: Check `*_INTEGRATION.md` or `*_API.md` files
111
+ - **Performance**: See `/infrastructure/caching/` and optimization docs
112
+
113
+ ## 📝 Contributing Documentation
114
+
115
+ When adding new documentation:
116
+
117
+ 1. **Choose the Right Location**:
118
+ - Node-specific → `/nodes/[node-name]/`
119
+ - Infrastructure → `/infrastructure/[category]/`
120
+ - Integration → `/integrations/[service]/`
121
+ - UI widget → `/ui-widgets/`
122
+ - Feature → `/features/`
123
+
124
+ 2. **Follow Naming Conventions**: Use clear, descriptive names with appropriate suffixes
125
+
126
+ 3. **Update Index Files**: Add your documentation to the relevant `README.md` in the subdirectory
127
+
128
+ 4. **Cross-Reference**: Link to related documentation files
129
+
130
+ 5. **Include Examples**: Add code snippets and usage examples
131
+
132
+ ## 🗂️ Index Files
133
+
134
+ Each subdirectory contains a `README.md` that:
135
+
136
+ - Lists all documentation files in that directory
137
+ - Provides brief descriptions of each document
138
+ - Links to related documentation in other directories
139
+ - Includes quick reference guides when applicable
140
+
141
+ ## 📊 Project Status
142
+
143
+ See [IMPLEMENTATION_STATUS.md](IMPLEMENTATION_STATUS.md) for overall project status and feature completion tracking.
144
+
145
+ ## 🆘 Need Help?
146
+
147
+ 1. **Search**: Use your editor's search to find keywords across all docs
148
+ 2. **Index Files**: Check the `README.md` in each subdirectory
149
+ 3. **Status**: Review `IMPLEMENTATION_STATUS.md` for current project state
150
+ 4. **Examples**: Look in `/examples/` for working implementations
151
+
152
+ ## 📅 Documentation Maintenance
153
+
154
+ - **Regular Updates**: Documentation should be updated when code changes
155
+ - **Version Tracking**: Include implementation dates in documentation
156
+ - **Consolidation**: Related documents should be merged when appropriate
157
+ - **Cleanup**: Outdated documentation should be archived or removed
158
+
159
+ ---
160
+
161
+ **Last Updated**: October 2, 2025
162
+ **Documentation Structure Version**: 2.0
docs/examples/README.md ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Examples & Workflows
2
+
3
+ Example workflows and demonstrations for ComfyUI-SwissArmyKnife nodes.
4
+
5
+ ## 📄 Files
6
+
7
+ - **[example_workflow.json](example_workflow.json)** - Sample workflow JSON
8
+ - **[WORKFLOW_DEMO.md](WORKFLOW_DEMO.md)** - Workflow demonstration guide
9
+
10
+ ## 🎯 Example Workflows
11
+
12
+ ### Basic Media Processing
13
+
14
+ - Load media from Reddit
15
+ - Describe with Gemini AI
16
+ - Process and output
17
+
18
+ ### Video Comparison
19
+
20
+ - Load multiple video versions
21
+ - Display in Video Preview node
22
+ - Compare side-by-side
23
+
24
+ ### LoRA Workflow
25
+
26
+ - Load LoRA from CivitAI
27
+ - Apply to model
28
+ - Generate with metadata
29
+
30
+ ## 🔧 Using Examples
31
+
32
+ 1. **Import Workflow**: Drag JSON file into ComfyUI
33
+ 2. **Configure Nodes**: Set API keys and paths
34
+ 3. **Run Workflow**: Execute to see results
35
+ 4. **Modify**: Customize for your needs
36
+
37
+ ## 📚 Related Documentation
38
+
39
+ - All node documentation in [nodes/](../nodes/)
40
+ - Integration guides in [integrations/](../integrations/)
41
+ - Feature documentation in [features/](../features/)
42
+
43
+ ---
44
+
45
+ **Category**: Examples
46
+ **Status**: In Progress
docs/examples/WORKFLOW_DEMO.md ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Final String Widget Demo Workflow
2
+
3
+ This shows how to set up a workflow to test the final_string widget functionality:
4
+
5
+ ```
6
+ ┌─────────────┐ ┌─────────────────────────┐ ┌─────────────┐
7
+ │ Load Image │ │ Gemini Image Describe │ │ Show Text │
8
+ │ │────▶│ │────▶│ │
9
+ │ [Load your │ │ - API Key: [your key] │ │ Displays │
10
+ │ test image]│ │ - Model: gemini-2.5- │ │ final │
11
+ │ │ │ flash │ │ generated │
12
+ └─────────────┘ │ - System Prompt: [...] │ │ prompt │
13
+ │ - User Prompt: [...] │ └─────────────┘
14
+ │ │
15
+ │ ┌─────────────────────┐ │
16
+ │ │ final_string widget │ │ ← This widget will
17
+ │ │ (will auto-update) │ │ populate after
18
+ │ └─────────────────────┘ │ execution!
19
+ └─────────────────────────┘
20
+ ```
21
+
22
+ ### Step-by-step Instructions:
23
+
24
+ 1. **Import the workflow**:
25
+ - Copy the contents of `example_workflow.json`
26
+ - In ComfyUI, go to "Load" → "Load (from file)" or drag the JSON file
27
+
28
+ 2. **Set up the nodes**:
29
+ - Load Image: Choose any test image
30
+ - Gemini Image Describe: Enter your valid Gemini API key
31
+ - Show Text: This will display the final output
32
+
33
+ 3. **Execute the workflow**:
34
+ - Click "Queue Prompt" to run the workflow
35
+ - Wait for the Gemini API to process the image
36
+
37
+ 4. **Check the results**:
38
+ - The `final_string` widget on the Gemini node should populate with generated text
39
+ - The Show Text node should display the same text
40
+ - Browser console should show "Updated final_string widget with:" message
41
+
42
+ ### What was fixed:
43
+ - ❌ Before: final_string widget showed placeholder text
44
+ - ✅ After: final_string widget shows actual generated description
45
+
46
+ The widget update happens automatically when the node execution completes!
docs/examples/example_workflow.json ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "last_node_id": 4,
3
+ "last_link_id": 3,
4
+ "nodes": [
5
+ {
6
+ "id": 1,
7
+ "type": "LoadImage",
8
+ "pos": [100, 100],
9
+ "size": { "0": 315, "1": 314 },
10
+ "flags": {},
11
+ "order": 0,
12
+ "mode": 0,
13
+ "outputs": [
14
+ {
15
+ "name": "IMAGE",
16
+ "type": "IMAGE",
17
+ "links": [1],
18
+ "shape": 3,
19
+ "slot_index": 0
20
+ },
21
+ { "name": "MASK", "type": "MASK", "links": null, "shape": 3 }
22
+ ],
23
+ "properties": { "Node name for S&R": "LoadImage" },
24
+ "widgets_values": ["example.jpg", "image"]
25
+ },
26
+ {
27
+ "id": 2,
28
+ "type": "GeminiUtilImageDescribe",
29
+ "pos": [500, 100],
30
+ "size": { "0": 400, "1": 500 },
31
+ "flags": {},
32
+ "order": 1,
33
+ "mode": 0,
34
+ "inputs": [{ "name": "image", "type": "IMAGE", "link": 1 }],
35
+ "outputs": [
36
+ {
37
+ "name": "description",
38
+ "type": "STRING",
39
+ "links": null,
40
+ "shape": 3
41
+ },
42
+ {
43
+ "name": "gemini_status",
44
+ "type": "STRING",
45
+ "links": null,
46
+ "shape": 3
47
+ },
48
+ {
49
+ "name": "final_string",
50
+ "type": "STRING",
51
+ "links": [2],
52
+ "shape": 3,
53
+ "slot_index": 2
54
+ }
55
+ ],
56
+ "properties": { "Node name for S&R": "GeminiUtilImageDescribe" },
57
+ "widgets_values": [
58
+ "YOUR_GEMINI_API_KEY_HERE",
59
+ "models/gemini-2.5-flash",
60
+ "Generate a detailed image description...",
61
+ "Please analyze this image...",
62
+ ""
63
+ ]
64
+ },
65
+ {
66
+ "id": 3,
67
+ "type": "ShowText",
68
+ "pos": [1000, 100],
69
+ "size": { "0": 300, "1": 200 },
70
+ "flags": {},
71
+ "order": 2,
72
+ "mode": 0,
73
+ "inputs": [{ "name": "text", "type": "STRING", "link": 2 }],
74
+ "outputs": [
75
+ { "name": "text", "type": "STRING", "links": null, "shape": 3 }
76
+ ],
77
+ "properties": { "Node name for S&R": "ShowText" },
78
+ "widgets_values": [""]
79
+ }
80
+ ],
81
+ "links": [
82
+ [1, 1, 0, 2, 0, "IMAGE"],
83
+ [2, 2, 2, 3, 0, "STRING"]
84
+ ],
85
+ "groups": [],
86
+ "config": {},
87
+ "extra": {},
88
+ "version": 0.4
89
+ }
docs/features/ASYNC_EVENT_LOOP_FIX.md ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Async Event Loop Fix for ComfyUI Integration
2
+
3
+ ## Issue Description
4
+
5
+ When running the LoRA Info Extractor in ComfyUI, users encountered this error:
6
+
7
+ ```
8
+ Error fetching CivitAI data for /path/to/lora.safetensors: Cannot run the event loop while another loop is running
9
+ ```
10
+
11
+ ## Root Cause
12
+
13
+ ComfyUI runs its own asyncio event loop, and our CivitAI service was attempting to create a new event loop using `asyncio.run()` or `new_event_loop().run_until_complete()`. This created a conflict because:
14
+
15
+ 1. ComfyUI's main thread already has an active event loop
16
+ 2. You cannot run `asyncio.run()` when an event loop is already running
17
+ 3. Creating a new event loop in the same thread causes synchronization issues
18
+
19
+ ## Solution Implemented
20
+
21
+ Updated the `_run_async()` method in `CivitAIService` to use thread-based async handling:
22
+
23
+ ### Before (Problematic)
24
+
25
+ ```python
26
+ def _run_async(self, coro):
27
+ try:
28
+ loop = asyncio.get_running_loop()
29
+ except RuntimeError:
30
+ return asyncio.run(coro)
31
+
32
+ # This approach failed in ComfyUI
33
+ new_loop = asyncio.new_event_loop()
34
+ try:
35
+ return new_loop.run_until_complete(coro)
36
+ finally:
37
+ new_loop.close()
38
+ ```
39
+
40
+ ### After (Fixed)
41
+
42
+ ```python
43
+ def _run_async(self, coro):
44
+ import concurrent.futures
45
+
46
+ try:
47
+ # Check if we're in an event loop
48
+ loop = asyncio.get_running_loop()
49
+ # If we are, run the coroutine in a separate thread
50
+ with concurrent.futures.ThreadPoolExecutor() as executor:
51
+ future = executor.submit(self._run_in_thread, coro)
52
+ return future.result()
53
+ except RuntimeError:
54
+ # No event loop running, use asyncio.run directly
55
+ return asyncio.run(coro)
56
+
57
+ def _run_in_thread(self, coro):
58
+ """Run coroutine in a new event loop in the current thread."""
59
+ new_loop = asyncio.new_event_loop()
60
+ asyncio.set_event_loop(new_loop)
61
+ try:
62
+ return new_loop.run_until_complete(coro)
63
+ finally:
64
+ new_loop.close()
65
+ asyncio.set_event_loop(None)
66
+ ```
67
+
68
+ ## How It Works
69
+
70
+ 1. **Detection**: Check if an event loop is already running using `asyncio.get_running_loop()`
71
+ 2. **Thread Isolation**: If a loop exists, run the async operation in a separate thread
72
+ 3. **Clean Execution**: Create a new event loop in the thread, run the coroutine, then clean up
73
+ 4. **Fallback**: If no loop is running, use standard `asyncio.run()`
74
+
75
+ ## Benefits
76
+
77
+ - ✅ **Compatible with ComfyUI**: Works seamlessly within ComfyUI's event loop
78
+ - ✅ **Thread Safe**: Isolates async operations to prevent conflicts
79
+ - ✅ **Backward Compatible**: Still works in non-event-loop environments
80
+ - ✅ **Clean Resource Management**: Properly closes event loops and threads
81
+
82
+ ## Testing
83
+
84
+ The fix was validated with:
85
+
86
+ - Service initialization outside event loops
87
+ - Service calls within active event loops (ComfyUI simulation)
88
+ - Multiple hash type API calls
89
+ - Error handling for 404 responses
90
+
91
+ ## Impact
92
+
93
+ This fix resolves the blocking issue that prevented the LoRA Info Extractor from working in ComfyUI environments while maintaining compatibility with other usage scenarios.
94
+
95
+ ## Related Files
96
+
97
+ - `nodes/civitai_service.py` - Main implementation
98
+ - `docs/MULTIPLE_HASH_TYPES_CIVITAI_INTEGRATION.md` - Comprehensive documentation
99
+
100
+ ## Date Fixed
101
+
102
+ September 26, 2025
docs/features/CHANGE_CLOTHING_COLOR_FEATURE.md ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # CHANGE_CLOTHING_COLOR_FEATURE
2
+
3
+ Purpose: Add a boolean option to the Gemini Util - Options node to instruct Gemini to change clothing colors in descriptions to new, scene-harmonized hues that differ from the original colors.
4
+
5
+ ## What changed
6
+
7
+ - New option in `Gemini Util - Options`:
8
+ - Name: `change_clothing_color`
9
+ - Type: Boolean (Yes/No)
10
+ - Default: No
11
+ - Location: `nodes/nodes.py` under `GeminiUtilOptions.INPUT_TYPES`
12
+ - Propagated through the options object as `change_clothing_color: bool`.
13
+ - Used by both image and video prompts to adjust clothing color language when clothing descriptions are enabled.
14
+ - Included in caching options to avoid stale results when toggled.
15
+
16
+ ## Behavior
17
+
18
+ - When `describe_clothing` is Yes AND `change_clothing_color` is Yes:
19
+ - Text2Image prompt: In the CLOTHING paragraph, the model is instructed to state NEW clothing colors that harmonize with the scene (complementary/analogous/neutral), explicitly different from the original. The prompt forbids mentioning or comparing to the original color.
20
+ - ImageEdit prompt: Adds a clause to change all clothing colors to NEW, scene-harmonized hues, explicitly different from the original; do not mention or reuse the original colors.
21
+ - Video prompt: Same as image—CLOTHING paragraph instructs changing to NEW scene-harmonized hues and never referencing the original.
22
+
23
+ - When `describe_clothing` is No: The color-change logic is ignored.
24
+
25
+ ## Files touched
26
+
27
+ - `nodes/nodes.py`
28
+ - Added `change_clothing_color` to `GeminiUtilOptions.INPUT_TYPES`
29
+ - Updated `GeminiUtilOptions.create_options` signature and returned options
30
+ - Propagated option into `MediaDescribe.describe_media`
31
+ - Updated `_process_image` and `_process_video` prompts and cache keys
32
+ - No changes needed in `web/js/swiss-army-knife.js` because ComfyUI auto-renders standard widgets for Python-defined inputs for the Options node.
33
+
34
+ ## Validation
35
+
36
+ - Import check: `from nodes.nodes import NODE_CLASS_MAPPINGS` loads successfully
37
+ - Expected available nodes include `GeminiUtilVideoDescribe` or `GeminiUtilMediaDescribe` depending on current implementation; in this repo: `GeminiUtilMediaDescribe`, `GeminiUtilOptions`, `FilenameGenerator`.
38
+
39
+ ## Usage
40
+
41
+ 1. Add `Gemini Util - Options` node to your workflow.
42
+ 2. Enable `Describe clothing` and toggle `Change clothing color` to `Yes`.
43
+ 3. Connect the options to `Gemini Util - Media Describe` and run.
44
+ 4. For image workflows, the `final_string` will include updated clothing colors; for video, the description will reflect new scene-harmonized clothing colors.
45
+
46
+ ## Notes and future considerations
47
+
48
+ - Color selection is model-driven guidance; ensure the downstream model uses the prompt accordingly.
49
+ - If you want to force a particular palette family (e.g., warm neutrals), a future enhancement could expose a `clothing_color_palette_hint` string.
docs/features/CLOTHING_TEXT_EXCLUSION.md ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Clothing Text and Typography Exclusion Enhancement
2
+
3
+ ## Overview
4
+
5
+ Enhanced the Gemini clothing description prompts to exclude any text, typography, words, letters, logos, brand names, or written content visible on clothing or accessories. This addresses the issue where brand names like "PSD" on shorts would be included in descriptions.
6
+
7
+ ## Changes Made
8
+
9
+ ### Before
10
+
11
+ The clothing description prompts only excluded "logos or brand names":
12
+
13
+ ```
14
+ Do not describe logos or brand names. Exclude tattoos, glasses, and other prohibited attributes.
15
+ ```
16
+
17
+ ### After
18
+
19
+ Enhanced exclusion to cover all forms of text and typography:
20
+
21
+ ```
22
+ Do not describe any text, typography, words, letters, logos, brand names, or written content visible on clothing or accessories. Exclude tattoos, glasses, and other prohibited attributes.
23
+ ```
24
+
25
+ ## Implementation Details
26
+
27
+ The changes were applied to both image and video processing in `nodes/nodes.py`:
28
+
29
+ 1. **Image Processing** (Line ~174): Updated the CLOTHING paragraph prompt in the `_process_image` method
30
+ 2. **Video Processing** (Line ~416): Updated the CLOTHING paragraph prompt in the `_process_video` method
31
+
32
+ Both instances now use the comprehensive text exclusion language.
33
+
34
+ ## Examples of Exclusions
35
+
36
+ ### What Gets Excluded Now ✅
37
+
38
+ - Brand names: "PSD", "Nike", "Adidas", "Supreme"
39
+ - Typography: Stylized fonts, decorative lettering
40
+ - Words/Text: Any readable text on clothing
41
+ - Letters: Individual letters or monograms
42
+ - Written content: Printed messages, slogans, quotes
43
+ - Logos: Company logos, symbols with text components
44
+
45
+ ### What Still Gets Described ✅
46
+
47
+ - Garment type and style
48
+ - Colors and materials
49
+ - Fit and silhouette
50
+ - Construction details (seams, straps, waistbands)
51
+ - Fabric texture and behavior
52
+ - Overall design elements (excluding text)
53
+
54
+ ## Benefits
55
+
56
+ 1. **Cleaner Descriptions**: No unwanted brand references in generated prompts
57
+ 2. **Copyright Compliance**: Avoids reproducing trademarked brand names
58
+ 3. **Focus on Style**: Emphasizes actual clothing design over commercial messaging
59
+ 4. **Consistent Exclusion**: Comprehensive coverage of all text-related elements
60
+
61
+ ## Technical Notes
62
+
63
+ - Changes maintain all existing functionality
64
+ - No breaking changes to API or node structure
65
+ - Applies to both Text2Image and Video processing modes
66
+ - Works with all configurable options (describe_clothing enabled)
67
+ - Backward compatible with existing workflows
68
+
69
+ ## Usage
70
+
71
+ This enhancement automatically applies when:
72
+
73
+ - Using `MediaDescribe` node (GeminiUtilMediaDescribe) with clothing descriptions enabled
74
+ - Processing images or videos with visible text on clothing
75
+ - Any workflow where clothing description is part of the output
76
+
77
+ No configuration changes needed - the improvement is applied automatically to all clothing descriptions.
docs/features/CONFIGURABLE_OPTIONS_GUIDE.md ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Gemini Util - Configurable Options Guide
2
+
3
+ ## Overview
4
+
5
+ The Gemini Describe functionality has been enhanced with configurable options through two nodes:
6
+
7
+ 1. **Gemini Util - Options**: Configuration node that defines how descriptions should be generated
8
+ 2. **Gemini Util - Media Describe**: Processing node that accepts media and optional configuration
9
+
10
+ ## New Gemini Util - Options Node
11
+
12
+ ### Purpose
13
+
14
+ This node provides granular control over description generation by separating configuration from media processing. Connect this node's output to the `gemini_options` input of the Media Describe node.
15
+
16
+ ### Configuration Options
17
+
18
+ #### API & Model Settings
19
+
20
+ - **Gemini API Key**: Your Google Gemini API key
21
+ - **Gemini Model**: Choose from available models (2.5-flash, 2.5-flash-lite, 2.5-pro)
22
+ - **Model Type**: Text2Image or ImageEdit workflow type
23
+
24
+ #### Description Control (New Boolean Options)
25
+
26
+ - **Describe Clothing?** [Yes/No]: Include detailed clothing and accessory descriptions
27
+ - **Describe Hair Style?** [Yes/No]: Include hair texture and motion (but not color/length)
28
+ - **Describe Bokeh?** [Yes/No]: Allow depth of field effects and blur descriptions
29
+ - **Replace Action with Twerking?** [Yes/No]: Replace video movement description with twerking content
30
+
31
+ #### Text Options
32
+
33
+ - **Prefix Text**: Text to prepend to generated descriptions
34
+
35
+ ## Updated Media Describe Node
36
+
37
+ ### Changes
38
+
39
+ - **Removed**: API key, model selection, description mode combo box, prefix text
40
+ - **Added**: Optional `gemini_options` input that accepts configuration from Options node
41
+ - **Maintained**: All media handling capabilities (upload, random selection, image/video support)
42
+
43
+ ### Backward Compatibility
44
+
45
+ When no Options node is connected, the Media Describe node uses these defaults:
46
+
47
+ - Describe Clothing: No
48
+ - Describe Hair Style: Yes
49
+ - Describe Bokeh: Yes
50
+ - Replace Action with Twerking: No
51
+ - API Key: Default development key
52
+ - Model: gemini-2.5-flash
53
+
54
+ ## Usage Examples
55
+
56
+ ### Basic Usage
57
+
58
+ 1. Add "Gemini Util - Options" node to workflow
59
+ 2. Configure desired settings
60
+ 3. Add "Gemini Util - Media Describe" node
61
+ 4. Connect Options node output to Media Describe `gemini_options` input
62
+ 5. Provide media input (image tensor or upload)
63
+
64
+ ### Option Combinations
65
+
66
+ #### For Minimal Descriptions (No Clothing, No Hair, No Bokeh)
67
+
68
+ - Clean, simple descriptions focusing on core elements
69
+ - Results in 3-paragraph structure: Subject, Cinematic, Style
70
+
71
+ #### For Detailed Fashion Analysis (Clothing + Hair)
72
+
73
+ - Comprehensive descriptions including garments and hairstyles
74
+ - Results in 4-paragraph structure when clothing enabled
75
+
76
+ #### For Sharp Focus Photography (No Bokeh)
77
+
78
+ - Explicitly prevents depth-of-field language
79
+ - Useful for product photography or architectural scenes
80
+
81
+ ### System Prompt Improvements
82
+
83
+ #### Enhanced Decisiveness
84
+
85
+ All prompts now include instructions to avoid uncertain language:
86
+
87
+ - ❌ "She appears to be wearing either lace tights or leggings"
88
+ - ✅ "She wears black lace tights"
89
+
90
+ #### Hair Style Option
91
+
92
+ New granular control over hair descriptions:
93
+
94
+ - When enabled: Includes texture and movement
95
+ - When disabled: Completely omits hair references
96
+ - Always excludes: Color and length (as before)
97
+
98
+ #### Dynamic Paragraph Structure
99
+
100
+ - 3 paragraphs: Subject, Cinematic, Style (no clothing)
101
+ - 4 paragraphs: Subject, Cinematic, Style, Clothing (with clothing)
102
+ - 5-6 paragraphs for video: Adds Scene and Movement sections
103
+
104
+ ## Migration Guide
105
+
106
+ ### For Existing Workflows
107
+
108
+ Existing Media Describe nodes will continue working with default settings. To use new features:
109
+
110
+ 1. Add Options node to workflow
111
+ 2. Configure desired settings
112
+ 3. Connect to Media Describe node
113
+ 4. Remove any hardcoded API keys from Media Describe node
114
+
115
+ ### Option Mapping
116
+
117
+ Old combo box "Description Mode" maps to new options as follows:
118
+
119
+ - "Describe without clothing" → Clothing: No, Hair: Yes, Bokeh: Yes
120
+ - "Describe with clothing" → Clothing: Yes, Hair: Yes, Bokeh: Yes
121
+ - "Describe without clothing (No bokeh)" → Clothing: No, Hair: Yes, Bokeh: No
122
+ - "Describe with clothing (No bokeh)" → Clothing: Yes, Hair: Yes, Bokeh: No
123
+
124
+ ## Benefits
125
+
126
+ 1. **Modularity**: Configure once, use with multiple media nodes
127
+ 2. **Flexibility**: Mix and match options as needed
128
+ 3. **Clarity**: Each option has a clear purpose
129
+ 4. **Extensibility**: Easy to add new options in the future
130
+ 5. **Precision**: More deterministic descriptions without uncertainty
131
+
132
+ ## Troubleshooting
133
+
134
+ ### No Description Generated
135
+
136
+ - Verify Options node is connected to Media Describe
137
+ - Check API key is valid
138
+ - Ensure media input is provided
139
+
140
+ ### Unexpected Content
141
+
142
+ - Review individual option settings
143
+ - Check if hair/clothing/bokeh options match expectations
144
+ - Verify model type (Text2Image vs ImageEdit) is appropriate
145
+
146
+ ### Backward Compatibility Issues
147
+
148
+ - Media Describe works standalone with defaults
149
+ - Only connect Options node if you need custom configuration
docs/features/CONTROL_PANEL_CHANGES.md ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Control Panel Simplification Changes
2
+
3
+ ## Summary
4
+
5
+ Simplified the Control Panel node to only accept `all_media_describe_data` as input and populate the three-column display from the parsed JSON data.
6
+
7
+ ## Changes Made
8
+
9
+ ### Python Backend (`nodes/utils/control_panel.py`)
10
+
11
+ 1. **Removed individual inputs**: Removed `final_prompt`, `gemini_status`, `media_info`, `height`, and `width` from INPUT_TYPES
12
+ 2. **Single input**: Now only accepts `all_media_describe_data` (STRING, optional)
13
+ 3. **JSON parsing**: The `display_info` method now:
14
+ - Parses the JSON from `all_media_describe_data`
15
+ - Logs the parsed data to console
16
+ - Returns the data in the UI format for JavaScript to consume
17
+
18
+ ### JavaScript Frontend (`web/js/swiss-army-knife.js`)
19
+
20
+ 1. **Removed dynamic input functionality**:
21
+ - Removed context menu options to add inputs
22
+ - Removed `updateControlPanelSummary` function
23
+ - Removed connection change handlers
24
+ - Removed input counter logic
25
+
26
+ 2. **Updated `updateControlPanelData` function**:
27
+ - Now extracts and parses `all_media_describe_data` from the execution output
28
+ - Parses JSON string into an object
29
+ - Populates three columns from the parsed data:
30
+ - **Left column**: `final_prompt` field
31
+ - **Middle column**: `gemini_status` field
32
+ - **Right column**: `media_info`, `height`, `width`, and any other fields
33
+
34
+ 3. **Better error handling**:
35
+ - Shows error messages if JSON parsing fails
36
+ - Shows appropriate messages when data fields are missing
37
+ - Logs debug information for troubleshooting
38
+
39
+ ## Data Flow
40
+
41
+ ```
42
+ Media Describe Node
43
+
44
+ [all_media_describe_data JSON output]
45
+
46
+ Control Panel Node (Python)
47
+
48
+ [Parses JSON and returns to UI]
49
+
50
+ Control Panel Widget (JavaScript)
51
+
52
+ [Displays in 3-column layout]
53
+ ```
54
+
55
+ ## Expected JSON Format
56
+
57
+ The `all_media_describe_data` should be a JSON string containing:
58
+
59
+ ```json
60
+ {
61
+ "final_prompt": "...",
62
+ "gemini_status": "...",
63
+ "media_info": "...",
64
+ "height": 1024,
65
+ "width": 768,
66
+ "other_field": "..."
67
+ }
68
+ ```
69
+
70
+ Any additional fields beyond the core ones will be displayed in the right column.
docs/features/DECISIVENESS_IMPROVEMENTS.md ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Gemini Prompt Decisiveness Improvements
2
+
3
+ ## Overview
4
+
5
+ Enhanced the Gemini prompts to eliminate uncertainty language and provide more decisive, confident descriptions. The changes address the issue where Gemini would respond with uncertain phrases like "holding a black folder or book" instead of making a definitive choice.
6
+
7
+ ## Changes Made
8
+
9
+ ### 1. Text2Image Prompts (Image Processing)
10
+
11
+ **Added prominent decisiveness requirement early in system prompt:**
12
+
13
+ ```
14
+ DECISIVENESS REQUIREMENT: Always provide definitive, certain descriptions. When you see something that could be described multiple ways, make a confident choice and state it as fact. Never use uncertain language like "appears to be", "seems to be", "might be", "possibly", "likely", or "or". Instead of "holding a black folder or book", write "holding a black folder". Instead of "wearing what appears to be denim", write "wearing dark blue denim jeans".
15
+ ```
16
+
17
+ **Enhanced critical note to be more explicit:**
18
+
19
+ - Added comprehensive list of uncertainty phrases to avoid
20
+ - Added instruction to "confidently choose one and state it as absolute fact"
21
+
22
+ ### 2. ImageEdit Prompts
23
+
24
+ **Added decisiveness requirement to single-sentence ImageEdit instructions:**
25
+
26
+ ```
27
+ Always be completely decisive and definitive - when you see something that could be described multiple ways, make a confident choice and state it as fact. Never use uncertain language like "appears to be", "seems to be", "might be", "possibly", "likely", or "or". Instead of "holding a black folder or book", write "holding a black folder".
28
+ ```
29
+
30
+ ### 3. Video Processing Prompts
31
+
32
+ **Added same decisiveness requirement to video analysis:**
33
+
34
+ - Includes the same prominent decisiveness section as Text2Image
35
+ - Enhanced critical note with comprehensive uncertainty language elimination
36
+ - Improved clothing descriptions to be more definitive
37
+
38
+ ### 4. Clothing Descriptions
39
+
40
+ **Enhanced clothing description sections for both image and video:**
41
+
42
+ - Added "with confidence" and "definitiveness" language
43
+ - Included instruction to "Make decisive choices when multiple interpretations are possible"
44
+ - Emphasized choosing "one specific description and state it as fact"
45
+
46
+ ## Examples of Improvements
47
+
48
+ ### Before (Uncertain Language)
49
+
50
+ - ❌ "She appears to be wearing either lace tights or leggings"
51
+ - ❌ "holding what might be a black folder or book"
52
+ - ❌ "seems to be wearing denim, possibly jeans"
53
+ - ❌ "likely has curly hair texture"
54
+
55
+ ### After (Decisive Language)
56
+
57
+ - ✅ "She wears black lace tights"
58
+ - ✅ "holding a black folder"
59
+ - ✅ "wearing dark blue denim jeans"
60
+ - ✅ "has curly hair texture"
61
+
62
+ ## Benefits
63
+
64
+ 1. **Eliminates Ambiguity**: No more "either/or" constructions
65
+ 2. **Improves Prompt Quality**: More specific descriptions for better AI generation
66
+ 3. **Reduces Uncertainty**: Confident descriptions lead to better results
67
+ 4. **Better User Experience**: Clear, definitive outputs instead of wishy-washy descriptions
68
+
69
+ ## Technical Implementation
70
+
71
+ - Changes applied to `nodes/media_describe/mediia_describe.py` in the `MediaDescribe` class
72
+ - Affects all three processing modes: Text2Image, ImageEdit, and Video
73
+ - Maintains backward compatibility with existing options
74
+ - No breaking changes to API or node structure
75
+
76
+ ## Validation
77
+
78
+ - ✅ Python syntax validation passed
79
+ - ✅ Node class mappings intact
80
+ - ✅ All functionality preserved
81
+ - ✅ Enhanced decisiveness implemented across all prompt types
82
+
83
+ The prompts now consistently guide Gemini to make confident, definitive choices rather than expressing uncertainty through hedging language.
docs/features/JAVASCRIPT_IMPROVEMENTS.md ADDED
@@ -0,0 +1,320 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # JavaScript Improvements and Fixes
2
+
3
+ **Last Updated**: October 8, 2025
4
+
5
+ This document consolidates JavaScript-related improvements, fixes, and infrastructure enhancements for ComfyUI-SwissArmyKnife.
6
+
7
+ ---
8
+
9
+ ## Table of Contents
10
+
11
+ 1. [Cache Busting Implementation](#cache-busting-implementation)
12
+ 2. [Module Loading Error Resolution](#module-loading-error-resolution)
13
+ 3. [Node Name Updates](#node-name-updates)
14
+
15
+ ---
16
+
17
+ ## Cache Busting Implementation
18
+
19
+ ### Problem
20
+
21
+ Browsers cache JavaScript files aggressively, which can prevent users from seeing updates to ComfyUI custom node JavaScript widgets after code changes. This is particularly problematic during development and after publishing updates.
22
+
23
+ ### Solution Options
24
+
25
+ #### Option 1: Version-Based Query Parameters (Recommended)
26
+
27
+ Add version query parameters to JavaScript file URLs to force browser cache invalidation.
28
+
29
+ **Implementation in `__init__.py`:**
30
+
31
+ ```python
32
+ import os
33
+ from .nodes.nodes import NODE_CLASS_MAPPINGS as MAIN_NODE_CLASS_MAPPINGS
34
+ from .nodes.nodes import NODE_DISPLAY_NAME_MAPPINGS as MAIN_NODE_DISPLAY_NAME_MAPPINGS
35
+ from .nodes.helper_nodes import HELPER_NODE_CLASS_MAPPINGS
36
+ from .nodes.helper_nodes import HELPER_NODE_DISPLAY_NAME_MAPPINGS
37
+
38
+ # Get version from pyproject.toml for cache busting
39
+ def get_version():
40
+ try:
41
+ import tomllib
42
+ pyproject_path = os.path.join(os.path.dirname(__file__), "pyproject.toml")
43
+ with open(pyproject_path, "rb") as f:
44
+ data = tomllib.load(f)
45
+ return data["project"]["version"]
46
+ except Exception:
47
+ # Fallback to timestamp if version reading fails
48
+ import time
49
+ return str(int(time.time()))
50
+
51
+ # Combine main nodes and helper nodes
52
+ NODE_CLASS_MAPPINGS = {**MAIN_NODE_CLASS_MAPPINGS, **HELPER_NODE_CLASS_MAPPINGS}
53
+ NODE_DISPLAY_NAME_MAPPINGS = {**MAIN_NODE_DISPLAY_NAME_MAPPINGS, **HELPER_NODE_DISPLAY_NAME_MAPPINGS}
54
+
55
+ WEB_DIRECTORY = "./web"
56
+ VERSION = get_version()
57
+
58
+ __all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY", "VERSION"]
59
+ ```
60
+
61
+ **JavaScript Version Tracking:**
62
+
63
+ ```javascript
64
+ // Version and cache busting info
65
+ const EXTENSION_VERSION = '1.4.0'; // Should match pyproject.toml version
66
+ const LOAD_TIMESTAMP = new Date().toISOString();
67
+
68
+ console.log(
69
+ `Loading swiss-army-knife.js extension v${EXTENSION_VERSION} at ${LOAD_TIMESTAMP}`,
70
+ );
71
+ ```
72
+
73
+ #### Option 2: File Hash-Based Cache Busting
74
+
75
+ ```python
76
+ import hashlib
77
+ import os
78
+
79
+ def get_file_hash(filepath):
80
+ """Generate SHA256 hash of file content for cache busting"""
81
+ try:
82
+ with open(filepath, 'rb') as f:
83
+ return hashlib.sha256(f.read()).hexdigest()[:8]
84
+ except Exception:
85
+ return "default"
86
+
87
+ # In __init__.py
88
+ js_file_path = os.path.join(os.path.dirname(__file__), "web/js/swiss-army-knife.js")
89
+ JS_FILE_HASH = get_file_hash(js_file_path)
90
+ ```
91
+
92
+ #### Option 3: Timestamp-Based Cache Busting
93
+
94
+ ```python
95
+ import os
96
+
97
+ def get_file_timestamp(filepath):
98
+ """Get file modification timestamp for cache busting"""
99
+ try:
100
+ return str(int(os.path.getmtime(filepath)))
101
+ except Exception:
102
+ import time
103
+ return str(int(time.time()))
104
+
105
+ # In __init__.py
106
+ js_file_path = os.path.join(os.path.dirname(__file__), "web/js/swiss-army-knife.js")
107
+ JS_TIMESTAMP = get_file_timestamp(js_file_path)
108
+ ```
109
+
110
+ ### Current Implementation
111
+
112
+ The project includes a comprehensive cache busting solution:
113
+
114
+ 1. **Version-Based Cache Busting** - Uses `pyproject.toml` version with timestamp fallback
115
+ 2. **Cache Busting Script** - `scripts/cache_bust.sh` for automatic version syncing
116
+ 3. **Development Utilities** - Browser console commands for cache clearing
117
+ 4. **Automatic Version Detection** - Notifies users when extension updates
118
+
119
+ ### Usage
120
+
121
+ #### For Developers
122
+
123
+ 1. Make changes to JavaScript files
124
+ 2. Run cache busting script:
125
+ ```bash
126
+ ./scripts/cache_bust.sh
127
+ ```
128
+ 3. Restart ComfyUI server (Python changes only)
129
+ 4. Hard refresh browser (`Ctrl+F5` / `Cmd+Shift+R`)
130
+
131
+ #### For Users Experiencing Cache Issues
132
+
133
+ **Browser console commands** (development only):
134
+
135
+ ```javascript
136
+ clearSwissArmyKnifeCache(); // Clear cache and reload
137
+ reloadSwissArmyKnife(); // Force reload with cache bypass
138
+ ```
139
+
140
+ **Manual browser cache clearing**:
141
+
142
+ - Hard refresh: `Ctrl+F5` (Windows/Linux) or `Cmd+Shift+R` (Mac)
143
+ - Developer Tools → Network tab → "Disable cache"
144
+ - Settings → Clear browsing data
145
+
146
+ ### Related Files
147
+
148
+ - `__init__.py` - Web directory registration and version management
149
+ - `web/js/swiss-army-knife.js` - Main JavaScript extension
150
+ - `pyproject.toml` - Version source for cache busting
151
+ - `scripts/cache_bust.sh` - Automated cache busting script
152
+
153
+ ---
154
+
155
+ ## Module Loading Error Resolution
156
+
157
+ ### Problem
158
+
159
+ ComfyUI was showing JavaScript errors when trying to load modules from non-existent paths:
160
+
161
+ ```
162
+ Error loading extension /extensions/comfyui_swissarmyknife/node_modules/ajv/lib/dotjs/allOf.js
163
+ Error loading extension /extensions/comfyui_swissarmyknife/node_modules/ajv/lib/dotjs/multipleOf.js
164
+ Error loading extension /extensions/comfyui_swissarmyknife/node_modules/ajv/lib/dotjs/dependencies.js
165
+ ...
166
+ ```
167
+
168
+ ### Root Cause
169
+
170
+ The `web/node_modules` directory contained development dependencies (ESLint, Prettier, etc.) that were accidentally being served by ComfyUI as part of the web extension. ComfyUI was attempting to load these Node.js modules as browser JavaScript files, which is incorrect.
171
+
172
+ ### Solution Applied
173
+
174
+ 1. **Removed `web/node_modules`** - Development dependencies shouldn't be exposed to ComfyUI
175
+ 2. **Removed `web/package-lock.json`** - No longer needed without dependencies in web directory
176
+ 3. **Kept `web/package.json`** - Still useful for development tool configuration
177
+
178
+ ### Architecture Clarification
179
+
180
+ **Active Files:**
181
+
182
+ - ✅ `web/js/gemini_widgets.js` - Plain JavaScript widgets for ComfyUI
183
+ - ✅ `web/css/gemini_widgets.css` - CSS for widgets
184
+
185
+ **Disabled/Development Only:**
186
+
187
+ - ⚠️ `ui-react_backup/` - React UI extension (disabled)
188
+
189
+ **Node Modules Locations:**
190
+
191
+ - Root directory (`node_modules/`) - Playwright tests
192
+ - React UI directory (`ui-react_backup/ui/node_modules/`) - React build
193
+ - Test directory (`web/tests/node_modules/`) - Playwright web tests
194
+
195
+ ### Expected Result
196
+
197
+ ComfyUI no longer attempts to load development dependencies as web assets. Plain JavaScript widgets continue to work normally without errors.
198
+
199
+ ### Files Affected
200
+
201
+ - ❌ Removed: `/web/node_modules/` (entire directory)
202
+ - ❌ Removed: `/web/package-lock.json`
203
+ - ✅ Kept: `/web/package.json` (for development tools only)
204
+ - ✅ Kept: `/web/js/gemini_widgets.js` (main widget functionality)
205
+ - ✅ Kept: `/web/css/gemini_widgets.css` (widget styling)
206
+
207
+ ### Verification
208
+
209
+ To verify the fix:
210
+
211
+ 1. Restart ComfyUI server
212
+ 2. Clear browser cache
213
+ 3. Check browser console for JavaScript errors
214
+ 4. Confirm that nodes load and function correctly
215
+
216
+ ---
217
+
218
+ ## Node Name Updates
219
+
220
+ ### Overview
221
+
222
+ Updated all JavaScript references from `GeminiUtilMediaDescribe` to `MediaDescribe` to match the Python node ID change in `NODE_CLASS_MAPPINGS`.
223
+
224
+ ### Problem
225
+
226
+ The Python backend had already renamed the node ID from `"GeminiUtilMediaDescribe"` to `"MediaDescribe"` in the `NODE_CLASS_MAPPINGS`, but the JavaScript code in `web/js/swiss-army-knife.js` was still using the old name, causing JavaScript widgets and event handlers to fail to attach to the node.
227
+
228
+ ### Changes Made
229
+
230
+ Updated all 9 occurrences of `GeminiUtilMediaDescribe` to `MediaDescribe` in `/web/js/swiss-army-knife.js`:
231
+
232
+ #### 1. Node Registration
233
+
234
+ ```javascript
235
+ // Before
236
+ else if (nodeData.name === "GeminiUtilMediaDescribe") {
237
+ debugLog("Registering GeminiUtilMediaDescribe node with dynamic media widgets");
238
+
239
+ // After
240
+ else if (nodeData.name === "MediaDescribe") {
241
+ debugLog("Registering MediaDescribe node with dynamic media widgets");
242
+ ```
243
+
244
+ #### 2. Workflow Loading Hook
245
+
246
+ ```javascript
247
+ // Before
248
+ if (node.comfyClass === "GeminiUtilMediaDescribe") {
249
+ debugLog("[LOADED] loadedGraphNode called for GeminiUtilMediaDescribe");
250
+
251
+ // After
252
+ if (node.comfyClass === "MediaDescribe") {
253
+ debugLog("[LOADED] loadedGraphNode called for MediaDescribe");
254
+ ```
255
+
256
+ #### 3. Execution Event Handler
257
+
258
+ ```javascript
259
+ // Before
260
+ if (node && node.comfyClass === "GeminiUtilMediaDescribe") {
261
+ debugLog("[API] ✅ Found GeminiUtilMediaDescribe execution result");
262
+
263
+ // After
264
+ if (node && node.comfyClass === "MediaDescribe") {
265
+ debugLog("[API] ✅ Found MediaDescribe execution result");
266
+ ```
267
+
268
+ ### Impact
269
+
270
+ **Fixed Functionality:**
271
+
272
+ - ✅ JavaScript widgets properly attach to the MediaDescribe node
273
+ - ✅ Dynamic media upload widgets (image/video) work correctly
274
+ - ✅ Reddit URL widget visibility toggling works
275
+ - ✅ Seed widget for randomization works
276
+ - ✅ Dimensions display widget shows correct height/width
277
+ - ✅ File persistence on workflow save/load works
278
+
279
+ **Backward Compatibility:**
280
+
281
+ - ⚠️ **Breaking Change**: Existing workflows using the old node need updating
282
+ - Users with saved workflows containing the old node ID will need to:
283
+ 1. Open the workflow JSON
284
+ 2. Find and replace `"GeminiUtilMediaDescribe"` with `"MediaDescribe"`
285
+ 3. Or recreate the node in ComfyUI
286
+
287
+ ### Testing Checklist
288
+
289
+ After these changes, verify:
290
+
291
+ 1. ✅ MediaDescribe node appears in the node menu
292
+ 2. ✅ Dynamic widgets appear based on media_source selection:
293
+ - Upload Media → Shows image/video upload buttons
294
+ - Randomize from Path → Shows media_path and seed inputs
295
+ - Reddit Post → Shows reddit_url input
296
+ 3. ✅ File uploads work and persist across workflow save/load
297
+ 4. ✅ Dimensions display widget shows after execution
298
+ 5. ✅ Video/image previews work correctly
299
+
300
+ ### Related Files
301
+
302
+ - `/web/js/swiss-army-knife.js` - JavaScript widgets and event handlers (updated)
303
+ - `/nodes/nodes.py` - Python node definitions (already updated)
304
+ - `/nodes/media_describe/mediia_describe.py` - MediaDescribe class implementation
305
+
306
+ ---
307
+
308
+ ## Summary
309
+
310
+ These JavaScript improvements ensure:
311
+
312
+ 1. **Reliable Cache Management** - Users always see the latest code updates
313
+ 2. **Clean Module Loading** - No spurious errors from development dependencies
314
+ 3. **Consistent Naming** - JavaScript and Python node IDs are synchronized
315
+
316
+ For related documentation, see:
317
+
318
+ - [Media Describe Node](../nodes/media-describe/) - AI content analysis
319
+ - [Debug System](../infrastructure/debug/) - For JavaScript debugging
320
+ - [UI Widgets](../ui-widgets/) - Widget implementation details
docs/features/JSON_OUTPUT_FORMAT.md ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # LoRAInfoExtractor JSON Output Format
2
+
3
+ ## Overview
4
+
5
+ The `LoRAInfoExtractor` node now outputs structured JSON data instead of concatenated strings, providing better data handling and parsing capabilities for downstream processing.
6
+
7
+ ## Implementation Details
8
+
9
+ ### Return Types and Names
10
+
11
+ - **RETURN_TYPES**: `("STRING", "STRING", "WANVIDLORA")`
12
+ - **RETURN_NAMES**: `("lora_json", "lora_info", "lora_passthrough")`
13
+
14
+ ### Output Structure
15
+
16
+ The first output (`lora_json`) contains a JSON string with the following structure:
17
+
18
+ ```json
19
+ {
20
+ "loras": [
21
+ {
22
+ "index": 0,
23
+ "name": "LoRA Name",
24
+ "info": "Detailed info string",
25
+ "path": "/path/to/lora.safetensors",
26
+ "strength": 1.0,
27
+ "has_civitai_data": true
28
+ }
29
+ ],
30
+ "count": 1,
31
+ "combined_display": "LoRA Name + Another LoRA"
32
+ }
33
+ ```
34
+
35
+ ### JSON Fields Description
36
+
37
+ #### Root Level Fields
38
+
39
+ - **`loras`**: Array of LoRA objects containing detailed metadata for each processed LoRA
40
+ - **`count`**: Integer representing the total number of valid LoRAs processed
41
+ - **`combined_display`**: String with " + " separated LoRA names for easy display (maintains backward compatibility)
42
+
43
+ #### LoRA Object Fields
44
+
45
+ - **`index`**: Zero-based index of the LoRA in the processing order
46
+ - **`name`**: Clean LoRA name (from CivitAI or extracted from filename)
47
+ - **`info`**: Human-readable information string including source (CivitAI/Local) and strength
48
+ - **`path`**: Full file path to the LoRA file
49
+ - **`strength`**: Numeric strength value from the WANVIDLORA configuration
50
+ - **`has_civitai_data`**: Boolean indicating whether CivitAI metadata was successfully retrieved
51
+
52
+ ## Example Outputs
53
+
54
+ ### Multiple LoRAs with Mixed Sources
55
+
56
+ ```json
57
+ {
58
+ "loras": [
59
+ {
60
+ "index": 0,
61
+ "name": "Realistic Vision",
62
+ "info": "CivitAI: Realistic Vision (v5.1) by SomeCreator",
63
+ "path": "/ComfyUI/models/loras/realistic_vision.safetensors",
64
+ "strength": 1.0,
65
+ "has_civitai_data": true
66
+ },
67
+ {
68
+ "index": 1,
69
+ "name": "CustomStyle",
70
+ "info": "Local: CustomStyle (strength: 0.8)",
71
+ "path": "/ComfyUI/models/loras/custom_style.safetensors",
72
+ "strength": 0.8,
73
+ "has_civitai_data": false
74
+ }
75
+ ],
76
+ "count": 2,
77
+ "combined_display": "Realistic Vision + CustomStyle"
78
+ }
79
+ ```
80
+
81
+ ### No Valid LoRAs (Error Case)
82
+
83
+ ```json
84
+ {
85
+ "loras": [],
86
+ "count": 0,
87
+ "combined_display": "No Valid LoRAs",
88
+ "error": "No valid LoRAs found"
89
+ }
90
+ ```
91
+
92
+ ### Exception Handling
93
+
94
+ ```json
95
+ {
96
+ "loras": [],
97
+ "count": 0,
98
+ "combined_display": "Error Extracting LoRA",
99
+ "error": "Specific error message"
100
+ }
101
+ ```
102
+
103
+ ## Processing Logic
104
+
105
+ ### Multiple LoRA Processing
106
+
107
+ 1. **Input Validation**: Check if input is WANVIDLORA list structure
108
+ 2. **LoRA Filtering**: Skip entries with `path: 'none'` or empty paths
109
+ 3. **CivitAI Lookup**: Query CivitAI API for each valid LoRA (if enabled)
110
+ 4. **Name Extraction**: Use CivitAI name or extract from filename
111
+ 5. **JSON Construction**: Build structured JSON with all metadata
112
+ 6. **Return**: JSON string, human-readable info, and original passthrough
113
+
114
+ ### Single LoRA Processing (Compatibility)
115
+
116
+ - Maintains backward compatibility with non-list inputs
117
+ - Returns same JSON structure with single LoRA in array
118
+ - Handles both CivitAI and local extraction methods
119
+
120
+ ## Usage Examples
121
+
122
+ ### Parsing JSON Output in Python
123
+
124
+ ```python
125
+ import json
126
+
127
+ # From ComfyUI workflow
128
+ lora_json, lora_info, lora_passthrough = lora_extractor_node_output
129
+
130
+ # Parse JSON
131
+ lora_data = json.loads(lora_json)
132
+
133
+ # Access data
134
+ total_loras = lora_data["count"]
135
+ display_name = lora_data["combined_display"]
136
+
137
+ # Iterate through LoRAs
138
+ for lora in lora_data["loras"]:
139
+ print(f"LoRA: {lora['name']} (strength: {lora['strength']})")
140
+ if lora["has_civitai_data"]:
141
+ print(" Has CivitAI metadata")
142
+ else:
143
+ print(" Local metadata only")
144
+ ```
145
+
146
+ ### JavaScript Processing
147
+
148
+ ```javascript
149
+ // Parse JSON output
150
+ const loraData = JSON.parse(loraJsonOutput);
151
+
152
+ // Access combined display for UI
153
+ document.getElementById('lora-display').textContent = loraData.combined_display;
154
+
155
+ // Process individual LoRAs
156
+ loraData.loras.forEach((lora, index) => {
157
+ console.log(`LoRA ${index + 1}: ${lora.name} at ${lora.strength} strength`);
158
+ });
159
+ ```
160
+
161
+ ## Benefits of JSON Format
162
+
163
+ ### Structured Data Access
164
+
165
+ - **Programmatic Processing**: Easy to parse and process in any language
166
+ - **Type Safety**: Clear data types for each field
167
+ - **Extensibility**: Easy to add new fields without breaking existing code
168
+
169
+ ### Backward Compatibility
170
+
171
+ - **Combined Display**: `combined_display` field maintains the " + " separated format
172
+ - **Info String**: Second output still provides human-readable information
173
+ - **Passthrough**: Third output preserves original WANVIDLORA data
174
+
175
+ ### Enhanced Metadata
176
+
177
+ - **Strength Values**: Individual strength values for each LoRA
178
+ - **Source Information**: Clear indication of CivitAI vs local metadata
179
+ - **File Paths**: Full paths available for further processing
180
+ - **Processing Status**: Error handling and success indicators
181
+
182
+ ## Migration Guide
183
+
184
+ ### From String Format
185
+
186
+ **Old Usage** (string concatenation):
187
+
188
+ ```python
189
+ # Old format returned: "LoRA1 + LoRA2"
190
+ lora_names = old_output[0]
191
+ names_list = lora_names.split(" + ")
192
+ ```
193
+
194
+ **New Usage** (JSON parsing):
195
+
196
+ ```python
197
+ # New format returns structured JSON
198
+ lora_json = json.loads(new_output[0])
199
+ names_list = [lora["name"] for lora in lora_json["loras"]]
200
+ combined_display = lora_json["combined_display"] # Same as old format
201
+ ```
202
+
203
+ ### Accessing Additional Data
204
+
205
+ With JSON format, you now have access to:
206
+
207
+ - Individual LoRA strength values
208
+ - Full file paths
209
+ - CivitAI metadata indicators
210
+ - Processing error information
211
+ - Structured arrays for iteration
212
+
213
+ ## Implementation Status
214
+
215
+ - ✅ **JSON Structure**: Complete with all metadata fields
216
+ - ✅ **Multiple LoRA Support**: Handles WANVIDLORA list structure
217
+ - ✅ **Single LoRA Compatibility**: Backward compatibility maintained
218
+ - ✅ **Error Handling**: Proper JSON error responses
219
+ - ✅ **CivitAI Integration**: Preserves CivitAI metadata detection
220
+ - ✅ **Testing**: Validated with mock data and real WANVIDLORA structures
221
+
222
+ ## Technical Notes
223
+
224
+ ### JSON Library
225
+
226
+ Uses Python's built-in `json` module for serialization:
227
+
228
+ - **Consistency**: Standard JSON formatting with 2-space indentation
229
+ - **Reliability**: Built-in error handling and validation
230
+ - **Performance**: Efficient serialization and parsing
231
+
232
+ ### Memory Considerations
233
+
234
+ - JSON strings are larger than simple concatenated strings
235
+ - Rich metadata provides more value than storage overhead
236
+ - Structured data enables better caching and processing optimization
237
+
238
+ ### Future Enhancements
239
+
240
+ Potential additions to JSON structure:
241
+
242
+ - **Model Hash**: File hash for verification
243
+ - **File Size**: LoRA file size information
244
+ - **Last Modified**: File timestamp data
245
+ - **Tags**: CivitAI tag information
246
+ - **Ratings**: CivitAI popularity/rating data
docs/features/ND_SUPER_NODES_FORK_SUMMARY.md ADDED
@@ -0,0 +1,384 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ND Super Nodes Fork - Implementation Summary
2
+
3
+ ## Overview
4
+
5
+ Successfully forked [nd-super-nodes](https://github.com/HenkDz/nd-super-nodes) by HenkDz into ComfyUI-SwissArmyKnife under `nodes/lora_manager/` with full integration into the Swiss Army Knife ecosystem.
6
+
7
+ ## Date
8
+
9
+ October 1, 2024
10
+
11
+ ## Files Added
12
+
13
+ ### Backend Python Files (8 files)
14
+
15
+ ```
16
+ nodes/lora_manager/
17
+ ├── __init__.py # Module initialization and node registration
18
+ ├── nd_super_lora_node.py # Main Super LoRA Loader node implementation
19
+ ├── lora_utils.py # LoRA file discovery and metadata extraction
20
+ ├── civitai_service.py # CivitAI API integration for trigger words
21
+ ├── template_manager.py # Template save/load/delete operations
22
+ ├── web_api.py # HTTP API endpoints for frontend
23
+ ├── file_api.py # Enhanced file listing API
24
+ ├── version_utils.py # Version checking and updates
25
+ └── README.md # Module documentation
26
+ ```
27
+
28
+ ### Web Extension Files (3 files)
29
+
30
+ ```
31
+ web/
32
+ ├── js/lora_manager/
33
+ │ ├── extension.js # Frontend JavaScript (5,983 lines)
34
+ │ └── README.md # Web extension documentation
35
+ └── css/lora_manager/
36
+ └── style.css # Custom styling for LoRA Manager UI
37
+ ```
38
+
39
+ ### Documentation Files (3 files)
40
+
41
+ ```
42
+ docs/
43
+ └── LORA_MANAGER_INTEGRATION.md # Comprehensive integration guide (8.4KB)
44
+ ```
45
+
46
+ ## Files Modified
47
+
48
+ ### Core Integration Files
49
+
50
+ 1. **`__init__.py`** (root)
51
+ - Added lora_manager node imports
52
+ - Integrated NODE_CLASS_MAPPINGS
53
+ - Added error handling for missing dependencies
54
+
55
+ 2. **`pyproject.toml`**
56
+ - Added `aiohttp>=3.8.0` dependency
57
+
58
+ 3. **`CONTRIBUTING.md`**
59
+ - Added lora_manager section
60
+ - Updated project structure diagram
61
+ - Added testing instructions
62
+
63
+ 4. **`README.md`**
64
+ - Added LoRA Manager to features list
65
+ - Updated available nodes section
66
+ - Added credits section
67
+
68
+ ### Branding Updates in Forked Code
69
+
70
+ Updated the following in forked files to match Swiss Army Knife branding:
71
+
72
+ 1. **`nodes/lora_manager/__init__.py`**
73
+ - Changed header comment to reference fork origin
74
+ - Updated NODE_DISPLAY_NAME_MAPPINGS: "Super LoRA Loader 🔪"
75
+ - Updated print statements: "Swiss Army Knife LoRA Manager"
76
+
77
+ 2. **`nodes/lora_manager/nd_super_lora_node.py`**
78
+ - Changed CATEGORY from "loaders" to "Swiss Army Knife 🔪"
79
+
80
+ ## Integration Details
81
+
82
+ ### Node Registration
83
+
84
+ The lora_manager nodes are integrated into the main node mappings:
85
+
86
+ ```python
87
+ # In __init__.py
88
+ from .nodes.lora_manager import NODE_CLASS_MAPPINGS as LORA_MANAGER_NODE_CLASS_MAPPINGS
89
+ from .nodes.lora_manager import NODE_DISPLAY_NAME_MAPPINGS as LORA_MANAGER_NODE_DISPLAY_NAME_MAPPINGS
90
+
91
+ NODE_CLASS_MAPPINGS = {
92
+ **MAIN_NODE_CLASS_MAPPINGS,
93
+ **HELPER_NODE_CLASS_MAPPINGS,
94
+ **LORA_MANAGER_NODE_CLASS_MAPPINGS # ← New integration
95
+ }
96
+ ```
97
+
98
+ ### API Routes Registration
99
+
100
+ The lora_manager automatically registers HTTP API routes when ComfyUI's PromptServer is available:
101
+
102
+ **LoRA Operations:**
103
+
104
+ - `GET /super_lora/loras` - List available LoRAs
105
+ - `GET /super_lora/files?folder_name=loras` - List files
106
+ - `POST /super_lora/civitai_info` - Fetch CivitAI metadata
107
+
108
+ **Template Operations:**
109
+
110
+ - `GET /super_lora/templates` - List all templates
111
+ - `POST /super_lora/templates` - Save template
112
+ - `DELETE /super_lora/templates/{name}` - Delete template
113
+
114
+ **File Picker:**
115
+
116
+ - `GET /superlora/files` - Enhanced file listing
117
+ - `GET /superlora/folders` - Folder information
118
+ - `GET /superlora/search` - File search
119
+
120
+ ### Web Extension Loading
121
+
122
+ The web extension is automatically loaded by ComfyUI from the `web/js/lora_manager/` directory through ComfyUI's standard web directory loading mechanism.
123
+
124
+ ## Features Integrated
125
+
126
+ ### 1. Super LoRA Loader Node
127
+
128
+ - **Category**: "Swiss Army Knife 🔪"
129
+ - **Display Name**: "Super LoRA Loader 🔪"
130
+ - **Inputs**: MODEL (required), CLIP (optional), lora_bundle (JSON)
131
+ - **Outputs**: MODEL, CLIP, TRIGGER_WORDS (string)
132
+
133
+ **Capabilities:**
134
+
135
+ - Load multiple LoRAs in a single node
136
+ - Individual enable/disable toggles per LoRA
137
+ - Dual strength controls (model and CLIP)
138
+ - Automatic trigger word extraction from safetensors metadata
139
+ - Tag-based organization with collapsible groups
140
+ - Duplicate detection
141
+ - Drag-and-drop reordering
142
+
143
+ ### 2. Template Management
144
+
145
+ - Save current LoRA configurations with custom names
146
+ - Load previously saved templates
147
+ - Rename existing templates
148
+ - Delete unwanted templates
149
+ - Templates stored in ComfyUI user directory
150
+ - Persistent across sessions
151
+
152
+ ### 3. Enhanced File Picker (ND Super Selector)
153
+
154
+ - Advanced file browser overlay
155
+ - Folder navigation with breadcrumbs
156
+ - Search functionality
157
+ - Multi-select support
158
+ - Per-node enable/disable via right-click menu
159
+ - Visual indicators (golden border, lightning icon ⚡)
160
+ - Supports: CheckpointLoader, VAELoader, LoraLoader, UNETLoader, CLIPLoader, ControlNetLoader, UpscaleModelLoader, GGUF variants
161
+
162
+ ### 4. CivitAI Integration
163
+
164
+ - Automatic trigger word fetching from CivitAI API
165
+ - Model metadata retrieval
166
+ - Fallback to local safetensors metadata
167
+ - Smart caching to reduce API calls
168
+ - Hash-based model identification
169
+
170
+ ## Testing Results
171
+
172
+ ### Python Import Tests
173
+
174
+ ```bash
175
+ ✓ lora_utils imports successfully
176
+ ✓ validate_lora_config works: True
177
+ ✓ lora_manager imports successfully
178
+ ✓ Nodes available: ['NdSuperLoraLoader']
179
+ ✓ Display names: ['Super LoRA Loader 🔪']
180
+ ✓ Category: Swiss Army Knife 🔪
181
+ ✓ Return types: ('MODEL', 'CLIP', 'STRING')
182
+ ```
183
+
184
+ ### Expected Console Output
185
+
186
+ When ComfyUI loads with lora_manager:
187
+
188
+ ```
189
+ ND Super Nodes: ComfyUI modules not available (this is normal during development)
190
+ Super LoRA Loader: ComfyUI folder_paths not available
191
+ Swiss Army Knife LoRA Manager: API routes registered
192
+ ```
193
+
194
+ ## Dependencies Added
195
+
196
+ ### Python Dependencies (pyproject.toml)
197
+
198
+ ```toml
199
+ dependencies = [
200
+ # ... existing dependencies
201
+ "aiohttp>=3.8.0", # ← New dependency for lora_manager
202
+ ]
203
+ ```
204
+
205
+ ### Optional Dependencies
206
+
207
+ The lora_manager works best with:
208
+
209
+ - `safetensors` - For reading LoRA metadata (usually included with ComfyUI)
210
+ - Internet connection - For CivitAI API integration (optional)
211
+
212
+ ## Directory Structure Changes
213
+
214
+ ### Before
215
+
216
+ ```
217
+ nodes/
218
+ ├── __init__.py
219
+ ├── cache.py
220
+ ├── civitai_service.py
221
+ ├── helper_nodes.py
222
+ ├── lora_hash_cache.py
223
+ └── nodes.py
224
+
225
+ web/
226
+ ├── js/
227
+ │ └── swiss-army-knife.js
228
+ └── tests/
229
+ ```
230
+
231
+ ### After
232
+
233
+ ```
234
+ nodes/
235
+ ├── __init__.py
236
+ ├── cache.py
237
+ ├── civitai_service.py
238
+ ├── helper_nodes.py
239
+ ├── lora_hash_cache.py
240
+ ├── lora_manager/ # ← NEW MODULE
241
+ │ ├── __init__.py
242
+ │ ├── nd_super_lora_node.py
243
+ │ ├── lora_utils.py
244
+ │ ├── civitai_service.py
245
+ │ ├── template_manager.py
246
+ │ ├── web_api.py
247
+ │ ├── file_api.py
248
+ │ ├── version_utils.py
249
+ │ └── README.md
250
+ └── nodes.py
251
+
252
+ web/
253
+ ├── css/ # ← NEW DIRECTORY
254
+ │ └── lora_manager/
255
+ │ └── style.css
256
+ ├── js/
257
+ │ ├── lora_manager/ # ← NEW DIRECTORY
258
+ │ │ ├── extension.js
259
+ │ │ └── README.md
260
+ │ └── swiss-army-knife.js
261
+ └── tests/
262
+ ```
263
+
264
+ ## Code Changes Summary
265
+
266
+ ### Minimal Changes Philosophy
267
+
268
+ Following the directive to make "smallest possible changes", only essential modifications were made:
269
+
270
+ 1. **Category Update**: Changed from "loaders" to "Swiss Army Knife 🔪" (1 line)
271
+ 2. **Display Name**: Added 🔪 emoji to node name (1 line)
272
+ 3. **Print Statements**: Updated branding in print statements (2 lines)
273
+ 4. **Documentation Headers**: Updated module docstrings (3 locations)
274
+
275
+ All other code from nd-super-nodes remains unchanged to maintain compatibility and ease of future updates.
276
+
277
+ ## Documentation
278
+
279
+ ### Created Documentation
280
+
281
+ 1. **`docs/LORA_MANAGER_INTEGRATION.md`** (8,432 bytes)
282
+ - Comprehensive integration guide
283
+ - Feature descriptions
284
+ - Architecture overview
285
+ - API routes documentation
286
+ - Usage examples
287
+ - Troubleshooting guide
288
+ - Credits and license information
289
+
290
+ 2. **`nodes/lora_manager/README.md`** (2,480 bytes)
291
+ - Backend module overview
292
+ - File descriptions
293
+ - Integration details
294
+ - Development guidelines
295
+
296
+ 3. **`web/js/lora_manager/README.md`** (2,743 bytes)
297
+ - Web extension overview
298
+ - Features description
299
+ - API integration details
300
+ - Testing and debugging guide
301
+
302
+ ### Updated Documentation
303
+
304
+ 1. **`README.md`**
305
+ - Added LoRA Manager to features list
306
+ - Updated available nodes section
307
+ - Added credits for nd-super-nodes fork
308
+
309
+ 2. **`CONTRIBUTING.md`**
310
+ - Added lora_manager section
311
+ - Updated project structure diagram
312
+ - Added testing instructions
313
+
314
+ ## Compatibility Notes
315
+
316
+ ### ComfyUI Compatibility
317
+
318
+ The lora_manager is designed to work with:
319
+
320
+ - ComfyUI's standard LoraLoader node API
321
+ - ComfyUI's folder_paths system
322
+ - ComfyUI's PromptServer for API routes
323
+ - ComfyUI's web extension system
324
+
325
+ ### Graceful Degradation
326
+
327
+ The module handles missing dependencies gracefully:
328
+
329
+ - Works without ComfyUI (for testing)
330
+ - Works without CivitAI API (falls back to local metadata)
331
+ - Works without safetensors library (with reduced functionality)
332
+
333
+ ## Future Considerations
334
+
335
+ ### Maintenance
336
+
337
+ When updating from nd-super-nodes upstream:
338
+
339
+ 1. Copy new files to `nodes/lora_manager/`
340
+ 2. Re-apply branding changes:
341
+ - Category: "Swiss Army Knife 🔪"
342
+ - Display name: "Super LoRA Loader 🔪"
343
+ - Print statements: "Swiss Army Knife LoRA Manager"
344
+ 3. Test imports and functionality
345
+ 4. Update documentation if API changes
346
+
347
+ ### Potential Enhancements
348
+
349
+ Listed in `docs/LORA_MANAGER_INTEGRATION.md`:
350
+
351
+ - Bulk LoRA operations
352
+ - LoRA preview thumbnails
353
+ - Custom LoRA categories/collections
354
+ - Integration with existing SwissArmyKnife metadata features
355
+ - Export/import templates as JSON
356
+ - LoRA conflict detection
357
+ - Performance metrics
358
+
359
+ ## Credits
360
+
361
+ - **Original Author**: HenkDz
362
+ - **Original Repository**: https://github.com/HenkDz/nd-super-nodes
363
+ - **Fork Date**: October 1, 2024
364
+ - **Integration**: ComfyUI-SwissArmyKnife Team
365
+ - **License**: Retains original nd-super-nodes license
366
+
367
+ ## Verification Checklist
368
+
369
+ - [x] All files copied successfully
370
+ - [x] Python imports work correctly
371
+ - [x] Node category updated to "Swiss Army Knife 🔪"
372
+ - [x] Display name includes 🔪 emoji
373
+ - [x] aiohttp dependency added to pyproject.toml
374
+ - [x] Documentation created and comprehensive
375
+ - [x] README.md updated with features and credits
376
+ - [x] CONTRIBUTING.md updated with lora_manager info
377
+ - [x] All branding changes applied consistently
378
+ - [x] Code follows minimal change philosophy
379
+ - [x] Git commits properly structured
380
+ - [x] No unnecessary files or artifacts committed
381
+
382
+ ## Conclusion
383
+
384
+ The nd-super-nodes fork has been successfully integrated into ComfyUI-SwissArmyKnife as the `lora_manager` module. All components are properly organized, documented, and integrated with consistent branding. The implementation follows the "smallest possible changes" directive while providing full functionality and comprehensive documentation for future maintenance and development.
docs/features/ND_SUPER_NODES_UPDATE_REMOVAL.md ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ND Super Nodes Update Checking Removal
2
+
3
+ ## Overview
4
+
5
+ This document describes the removal of update checking functionality from the ComfyUI-SwissArmyKnife project, which is a fork of nd-super-nodes.
6
+
7
+ ## Why Remove Update Checking?
8
+
9
+ ComfyUI-SwissArmyKnife forked the nd-super-nodes project and has diverged from the original. Checking for updates against the original nd-super-nodes repository:
10
+
11
+ - Is no longer relevant since this is a separate fork
12
+ - Could confuse users with update notifications for the wrong repository
13
+ - Makes unnecessary API calls to GitHub
14
+ - Shows incorrect version information
15
+
16
+ ## Changes Made
17
+
18
+ ### Frontend Changes (JavaScript)
19
+
20
+ **File**: `web/js/lora_manager/extension.js`
21
+
22
+ Removed the following components:
23
+
24
+ - **UpdateService class** (~104 lines, lines 1896-2000): Entire service that checked GitHub for nd-super-nodes updates
25
+ - **UpdateService initialization** (line 3730): Removed `this.updateService = UpdateService.getInstance()` from SuperLoraNode
26
+ - **Update checking in initialization** (lines 3751-3757): Removed `this.updateService.initialize()` from Promise.all
27
+ - **Global status variable** (line 3773): Removed `window.NDSuperNodesUpdateStatus` assignment
28
+ - **Update checking command** (lines 6933-6940): Removed "Check ND Super Nodes Updates" from extension commands
29
+
30
+ Added explanatory comment at line 1896:
31
+
32
+ ```javascript
33
+ // UpdateService removed - this is a forked version and does not check for nd-super-nodes updates
34
+ ```
35
+
36
+ ### Backend Changes (Python)
37
+
38
+ **File**: `nodes/lora_manager/web_api.py`
39
+
40
+ - Changed import from `get_update_status` to `get_local_version`
41
+ - Modified `get_version_info()` function to return only local version information
42
+ - Disabled GitHub release checking functionality
43
+ - Returns simple response: `{ "localVersion": {...}, "hasUpdate": false, "message": "This is a forked version. Update checking disabled." }`
44
+
45
+ **File**: `nodes/lora_manager/version_utils.py`
46
+
47
+ - No changes made to this file
48
+ - Functions like `get_update_status()` and `_fetch_latest_release()` remain in code but are no longer called
49
+ - Consider removing this file in the future if not needed
50
+
51
+ ### Documentation Changes
52
+
53
+ Updated the following documentation files to remove UpdateService references:
54
+
55
+ - `docs/SUPERLORA_IMPLEMENTATION_GUIDE.md`: Removed UpdateService from services list
56
+ - `docs/SUPERLORA_CLARIFICATION.md`: Removed UpdateService from services list
57
+
58
+ ## Version Endpoint Behavior
59
+
60
+ The `/super_lora/version` and `/superlora/version` endpoints remain active but now return:
61
+
62
+ ```json
63
+ {
64
+ "localVersion": {
65
+ "version": "x.x.x",
66
+ "builtAt": "ISO-8601-timestamp"
67
+ },
68
+ "hasUpdate": false,
69
+ "message": "This is a forked version. Update checking disabled."
70
+ }
71
+ ```
72
+
73
+ Previous behavior (now disabled):
74
+
75
+ - Fetched latest release from `https://api.github.com/repos/HenkDz/nd-super-nodes/releases/latest`
76
+ - Compared versions and returned update availability
77
+ - Cached results for 24 hours
78
+ - Displayed update notifications in ComfyUI UI
79
+
80
+ ## UI Changes
81
+
82
+ Users will no longer see:
83
+
84
+ - Update notification overlay: "ND Super Nodes v1.7.2 available. Run update.ps1 / update.sh in your node folder to upgrade"
85
+ - "Check ND Super Nodes Updates" command in ComfyUI command palette
86
+ - Automatic update checking on node initialization
87
+
88
+ ## Files That Can Be Removed (Optional)
89
+
90
+ The following files are no longer used and can be removed in the future:
91
+
92
+ - `nodes/lora_manager/version_utils.py`: Contains GitHub release checking logic
93
+ - Any cached update files in `<ComfyUI user dir>/nd_super_nodes/nd_super_nodes_update_cache.json`
94
+
95
+ ## Future Considerations
96
+
97
+ If you want to implement update checking for ComfyUI-SwissArmyKnife:
98
+
99
+ 1. Create a new GitHub releases system for this repository
100
+ 2. Update `GITHUB_RELEASE_URL` in version_utils.py to point to your fork
101
+ 3. Re-enable UpdateService in extension.js
102
+ 4. Update version checking messages to reference ComfyUI-SwissArmyKnife
103
+
104
+ ## Testing
105
+
106
+ After these changes:
107
+
108
+ 1. ✅ No update notifications appear in ComfyUI UI
109
+ 2. ✅ Version endpoint returns local version only
110
+ 3. ✅ No GitHub API calls to nd-super-nodes repository
111
+ 4. ✅ SuperLoraLoader and SuperDualLoraLoader nodes function normally
112
+
113
+ ## Related Documentation
114
+
115
+ - `docs/SUPERLORA_IMPLEMENTATION_GUIDE.md`: Technical guide for SuperLoraLoader
116
+ - `docs/SUPERLORA_CLARIFICATION.md`: File structure clarification
117
+ - `docs/ND_SUPER_NODES_FORK_SUMMARY.md`: Overview of nd-super-nodes fork
docs/features/README.md ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Features Documentation
2
+
3
+ Feature implementations, enhancements, and improvements across ComfyUI-SwissArmyKnife.
4
+
5
+ ## 📄 Documentation Files
6
+
7
+ ### JavaScript & Infrastructure
8
+
9
+ - **[JAVASCRIPT_IMPROVEMENTS.md](JAVASCRIPT_IMPROVEMENTS.md)** - Cache busting, module loading fixes, and node name updates
10
+
11
+ ### Content Modification
12
+
13
+ - **[CHANGE_CLOTHING_COLOR_FEATURE.md](CHANGE_CLOTHING_COLOR_FEATURE.md)** - Clothing color modification feature
14
+ - **[CLOTHING_TEXT_EXCLUSION.md](CLOTHING_TEXT_EXCLUSION.md)** - Clothing text exclusion from prompts
15
+ - **[TWERKING_ACTION_REPLACEMENT.md](TWERKING_ACTION_REPLACEMENT.md)** - Action replacement in descriptions
16
+
17
+ ### Prompt Improvements
18
+
19
+ - **[DECISIVENESS_IMPROVEMENTS.md](DECISIVENESS_IMPROVEMENTS.md)** - Prompt decisiveness enhancements
20
+ - **[CONFIGURABLE_OPTIONS_GUIDE.md](CONFIGURABLE_OPTIONS_GUIDE.md)** - Configurable options system
21
+
22
+ ### Data & Output
23
+
24
+ - **[JSON_OUTPUT_FORMAT.md](JSON_OUTPUT_FORMAT.md)** - JSON output formatting and structure
25
+
26
+ ### External Integrations
27
+
28
+ - **[ND_SUPER_NODES_FORK_SUMMARY.md](ND_SUPER_NODES_FORK_SUMMARY.md)** - ND Super Nodes fork integration
29
+ - **[ND_SUPER_NODES_UPDATE_REMOVAL.md](ND_SUPER_NODES_UPDATE_REMOVAL.md)** - ND Super Nodes update removal
30
+
31
+ ### System Features
32
+
33
+ - **[ASYNC_EVENT_LOOP_FIX.md](ASYNC_EVENT_LOOP_FIX.md)** - Async event loop fixes
34
+
35
+ ## 🎯 Feature Categories
36
+
37
+ ### JavaScript & Infrastructure
38
+
39
+ **Cache Management:**
40
+
41
+ - Version-based query parameters for cache busting
42
+ - File hash and timestamp-based alternatives
43
+ - Development utilities and browser console commands
44
+ - Automatic version detection and sync
45
+
46
+ **Module Loading:**
47
+
48
+ - Fixed Node.js module loading errors
49
+ - Cleaned up web/node_modules structure
50
+ - Proper separation of development dependencies
51
+
52
+ **Node Naming:**
53
+
54
+ - Updated GeminiUtilMediaDescribe → MediaDescribe
55
+ - Synchronized Python and JavaScript node IDs
56
+ - Fixed widget attachment and event handlers
57
+
58
+ ### Content Processing
59
+
60
+ - Clothing analysis and modification
61
+ - Action detection and replacement
62
+ - Text extraction and filtering
63
+
64
+ ### Prompt Engineering
65
+
66
+ - Decisiveness scoring
67
+ - Quality improvements
68
+ - Configurable prompt templates
69
+
70
+ ### System Improvements
71
+
72
+ - Async processing
73
+ - Error handling
74
+ - Performance optimization
75
+
76
+ ## 📚 Related Documentation
77
+
78
+ - [Media Describe](../nodes/media-describe/) - AI content analysis
79
+ - [Debug System](../infrastructure/debug/) - For feature debugging
80
+ - [UI Widgets](../ui-widgets/) - For feature configuration UI
81
+
82
+ ---
83
+
84
+ **Category**: Features
85
+ **Status**: Active Development
docs/features/RESTART_BUTTON.md ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Restart Button Implementation
2
+
3
+ ## Overview
4
+
5
+ Added a red restart button to the ComfyUI topbar menu that allows users to restart the ComfyUI server.
6
+
7
+ ## Files Created/Modified
8
+
9
+ ### 1. `nodes/restart_api.py` (NEW)
10
+
11
+ - Created a new API endpoint `/swissarmyknife/restart` (POST)
12
+ - Handles server restart by sending SIGTERM signal
13
+ - Gracefully shuts down and exits the process
14
+
15
+ ### 2. `__init__.py` (MODIFIED)
16
+
17
+ - Imported and registered the restart API routes
18
+ - The restart endpoint is now available when ComfyUI starts
19
+
20
+ ### 3. `web/js/swiss-army-knife.js` (MODIFIED)
21
+
22
+ - Added new extension `comfyui_swissarmyknife.restart_button`
23
+ - Defined restart command with ID `swissarmyknife.restart`
24
+ - Added command to topbar menu under "Swiss Army Knife" menu
25
+ - Injected CSS styles to make the button red
26
+ - Includes confirmation dialog before restarting
27
+ - Shows toast notifications for restart status
28
+
29
+ ### 4. `web/css/restart-button.css` (NEW)
30
+
31
+ - Standalone CSS file for restart button styling (optional, styles are also injected via JS)
32
+
33
+ ## Features
34
+
35
+ ### Button Appearance
36
+
37
+ - **Red background** (#dc3545) with white text
38
+ - **Bold font** for prominence
39
+ - **Hover effect** - darker red (#c82333)
40
+ - **Active effect** - even darker red (#bd2130)
41
+ - 🔴 emoji prefix for visual indication
42
+
43
+ ### User Experience
44
+
45
+ 1. User clicks "Swiss Army Knife" → "🔴 Restart ComfyUI Server" in topbar
46
+ 2. Confirmation dialog appears
47
+ 3. If confirmed, sends POST request to `/swissarmyknife/restart`
48
+ 4. Shows "Server Restarting" toast notification
49
+ 5. Waits 2 seconds then reloads the page
50
+ 6. ComfyUI server restarts in background
51
+
52
+ ### Error Handling
53
+
54
+ - Shows error toast if restart fails
55
+ - Falls back to alert() if toast notifications unavailable
56
+ - Logs all events to browser console
57
+
58
+ ## Usage
59
+
60
+ After ComfyUI restarts with this extension:
61
+
62
+ 1. Look for "Swiss Army Knife" in the topbar menu
63
+ 2. Click to expand the menu
64
+ 3. Click "🔴 Restart ComfyUI Server"
65
+ 4. Confirm the restart
66
+ 5. Wait for server to restart and page to reload
67
+
68
+ ## Notes
69
+
70
+ - Restart works by sending SIGTERM to the server process
71
+ - Requires ComfyUI to be running under a process manager or restart script for automatic restart
72
+ - If running manually, the server will shut down and need manual restart
73
+ - The 2-second delay before page reload allows the server to begin shutdown
docs/features/TWERKING_ACTION_REPLACEMENT.md ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Twerking Action Replacement Feature
2
+
3
+ ## Overview
4
+
5
+ The "Replace Action with Twerking" feature allows users to replace the standard video movement analysis with specific twerking content. When enabled, this option modifies the MOVEMENT paragraph generation in video processing.
6
+
7
+ ## Implementation
8
+
9
+ ### New Option
10
+
11
+ - **Option Name**: `replace_action_with_twerking`
12
+ - **Type**: Boolean (Yes/No)
13
+ - **Default**: No
14
+ - **Location**: Gemini Util - Options node
15
+
16
+ ### Behavior
17
+
18
+ #### When Disabled (Default)
19
+
20
+ The standard movement analysis is performed:
21
+
22
+ - Describes body-part specific movement and musical rhythm alignment
23
+ - Provides chronological movement narration with precise action verbs
24
+ - Includes footwork, weight shifts, and choreography phrasing
25
+ - Maintains original detailed movement analysis
26
+
27
+ #### When Enabled
28
+
29
+ The movement prompt is replaced with:
30
+
31
+ 1. **Initial Frame Description**: Describes the pose and body position in the first frame
32
+ 2. **Twerking Content**: Appends the fixed text: "A woman is twerking and shaking her ass. She has a curvy body and a huge ass."
33
+
34
+ ### Technical Details
35
+
36
+ #### Files Modified
37
+
38
+ - `nodes/nodes.py`:
39
+ - Added `replace_action_with_twerking` to GeminiUtilOptions INPUT_TYPES
40
+ - Updated `create_options()` method signature and implementation
41
+ - Modified `_process_video()` method signature and movement prompt logic
42
+ - Updated method call and default values
43
+
44
+ #### Code Location
45
+
46
+ - Movement prompt generation: Lines ~483-495 in `nodes/nodes.py`
47
+ - Option definition: Lines ~55-59 in `nodes/nodes.py`
48
+
49
+ ### Usage Instructions
50
+
51
+ 1. **Add Options Node**: Place "Gemini Util - Options" node in your workflow
52
+ 2. **Configure Option**: Set "Replace Action with Twerking?" to "Yes"
53
+ 3. **Connect to Media Describe**: Connect the options output to the Media Describe node
54
+ 4. **Process Video**: The video analysis will use the twerking replacement in the movement paragraph
55
+
56
+ ### Compatibility
57
+
58
+ - **Backward Compatible**: Existing workflows without the options node default to "No"
59
+ - **Video Only**: This feature only affects video processing, not image analysis
60
+ - **Paragraph Structure**: Maintains the standard paragraph numbering and structure
61
+
62
+ ### Example Output
63
+
64
+ **Standard Movement Paragraph:**
65
+
66
+ ```
67
+ 3. MOVEMENT (Third Paragraph)
68
+ The subject initiates with a hip sway on the downbeat, then lifts the right arm upward while the torso tilts as the knees bend...
69
+ ```
70
+
71
+ **With Twerking Replacement:**
72
+
73
+ ```
74
+ 3. MOVEMENT (Third Paragraph)
75
+ The subject stands with arms raised overhead in an energetic pose. A woman is twerking and shaking her ass. She has a curvy body and a huge ass.
76
+ ```
77
+
78
+ ## Configuration Options
79
+
80
+ The twerking replacement works in combination with other options:
81
+
82
+ - **Describe Subject**: Still controls whether subject descriptions are included
83
+ - **Describe Clothing**: Still controls clothing descriptions
84
+ - **Describe Bokeh**: Still controls cinematic effects
85
+ - **Other Options**: Unaffected by this feature
86
+
87
+ ## Notes
88
+
89
+ - This feature is designed for specific content generation needs
90
+ - The replacement text is fixed and not customizable in the current implementation
91
+ - Only affects the MOVEMENT paragraph in video processing workflows
92
+ - Future enhancements could include customizable replacement text
docs/infrastructure/TEMP_DIRECTORY_UTILS.md ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Temporary Directory Utilities
2
+
3
+ ## Overview
4
+
5
+ ComfyUI-SwissArmyKnife uses a centralized temporary directory utility (`nodes/utils/temp_utils.py`) to ensure all temporary files and directories respect ComfyUI's configuration, especially in Docker environments with custom base directories.
6
+
7
+ ## Why This Matters
8
+
9
+ ### Problem with Standard Python tempfile
10
+
11
+ - `tempfile.gettempdir()` returns the system temp directory (e.g., `/tmp` on Linux)
12
+ - In Docker, this is the container's `/tmp`, not the ComfyUI workspace
13
+ - Files are isolated from the host and don't respect `--base-directory`
14
+
15
+ ### Solution: ComfyUI-Aware Temp Directory
16
+
17
+ - Uses ComfyUI's `folder_paths.get_user_directory()` + `/temp`
18
+ - Respects `--base-directory` flag in Docker setups
19
+ - Falls back to system temp when ComfyUI not available
20
+ - Ensures consistent behavior across different deployment scenarios
21
+
22
+ ## Usage
23
+
24
+ ### Getting Base Temp Directory
25
+
26
+ ```python
27
+ from ..utils.temp_utils import get_temp_directory
28
+
29
+ # Get ComfyUI's temp directory
30
+ temp_dir = get_temp_directory()
31
+ # Returns: /workspace/ComfyUI/user/temp (in Docker)
32
+ # Or: <user_dir>/temp (local install)
33
+ ```
34
+
35
+ ### Getting a Temp Subdirectory
36
+
37
+ ```python
38
+ from ..utils.temp_utils import get_temp_subdirectory
39
+
40
+ # Create/get a subdirectory within temp
41
+ frames_dir = get_temp_subdirectory("comfyui_frames")
42
+ # Returns: /workspace/ComfyUI/user/temp/comfyui_frames
43
+ ```
44
+
45
+ ### Getting a Temp File Path
46
+
47
+ ```python
48
+ from ..utils.temp_utils import get_temp_file_path
49
+
50
+ # Get a temp file path with specific extension
51
+ temp_video = get_temp_file_path(suffix='.mp4', prefix='trimmed', subdir='videos')
52
+ # Returns: /workspace/ComfyUI/user/temp/videos/trimmed_a1b2c3d4.mp4
53
+
54
+ # Use it like a regular file path
55
+ with open(temp_video, 'wb') as f:
56
+ f.write(video_data)
57
+ ```
58
+
59
+ ## Implementation Details
60
+
61
+ ### Directory Structure
62
+
63
+ When using Docker with `--base-directory /workspace/ComfyUI`:
64
+
65
+ ```
66
+ /workspace/ComfyUI/
67
+ ├── user/
68
+ │ └── temp/ # Base temp directory
69
+ │ ├── comfyui_frames/ # Frame extraction subdirectory
70
+ │ │ └── frames_video_abc123/ # Per-video frame storage
71
+ │ ├── videos/ # Video processing subdirectory
72
+ │ │ └── trimmed_xyz789.mp4 # Temporary trimmed videos
73
+ │ └── downloads/ # Downloaded media subdirectory
74
+ │ └── reddit_media_def456.jpg
75
+ ```
76
+
77
+ ### Fallback Behavior
78
+
79
+ 1. **ComfyUI Available**: Uses `folder_paths.get_user_directory() + '/temp'`
80
+ 2. **ComfyUI Unavailable**: Falls back to `tempfile.gettempdir()`
81
+
82
+ This ensures compatibility with:
83
+
84
+ - Local ComfyUI installations
85
+ - Docker deployments with custom base directories
86
+ - Standalone testing/development environments
87
+
88
+ ## Nodes Using Temp Utils
89
+
90
+ All nodes that create temporary files have been updated:
91
+
92
+ 1. **Frame Extractor** (`nodes/media_selection/frame_extractor.py`)
93
+ - Uses `get_temp_subdirectory("comfyui_frames")` for frame extraction
94
+ 2. **Media Selection** (`nodes/media_selection/media_selection.py`)
95
+ - Uses `get_temp_file_path(suffix='.mp4', subdir='videos')` for video trimming
96
+ 3. **Media Describe** (`nodes/media_describe/mediia_describe.py`)
97
+ - Uses `get_temp_file_path(suffix=file_ext, subdir='downloads')` for Reddit downloads
98
+ - Uses `get_temp_file_path(suffix='.mp4', subdir='videos')` for video trimming
99
+
100
+ ## Docker Configuration
101
+
102
+ In your `docker-compose.yml`:
103
+
104
+ ```yaml
105
+ command: python main.py --listen 0.0.0.0 --port 8188 --cpu --base-directory /workspace/ComfyUI
106
+ ```
107
+
108
+ With this setup:
109
+
110
+ - Temp files: `/workspace/ComfyUI/user/temp/...`
111
+ - Mounted to host: `./.comfyui/user/temp/...`
112
+ - Persistent across container restarts
113
+
114
+ ## Benefits
115
+
116
+ ✅ **Consistent behavior** across Docker and local installations
117
+ ✅ **Respects ComfyUI configuration** (`--base-directory`, `--temp-directory`)
118
+ ✅ **Better file organization** with subdirectories
119
+ ✅ **Works in mounted volumes** (accessible from host)
120
+ ✅ **Graceful fallback** when ComfyUI not available
121
+
122
+ ## Migration from Python tempfile
123
+
124
+ ### Before
125
+
126
+ ```python
127
+ import tempfile
128
+
129
+ # Old way - uses system /tmp
130
+ base_temp_dir = tempfile.gettempdir()
131
+
132
+ # Or
133
+ with tempfile.NamedTemporaryFile(suffix='.mp4', delete=False) as temp_file:
134
+ temp_path = temp_file.name
135
+ ```
136
+
137
+ ### After
138
+
139
+ ```python
140
+ from ..utils.temp_utils import get_temp_subdirectory, get_temp_file_path
141
+
142
+ # New way - uses ComfyUI temp directory
143
+ base_temp_dir = get_temp_subdirectory("my_subdir")
144
+
145
+ # Or
146
+ temp_path = get_temp_file_path(suffix='.mp4', prefix='my_prefix', subdir='my_subdir')
147
+ ```
docs/infrastructure/build-deploy/GET_VERSION_IMPORT_FIX.md ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # get_version() Import Error Fix
2
+
3
+ ## Problem
4
+
5
+ ComfyUI was failing to import the custom node with the error:
6
+
7
+ ```
8
+ Cannot import /comfyui-nvidia/custom_nodes/ComfyUI-SwissArmyKnife module for custom nodes: name 'get_version' is not defined
9
+ ```
10
+
11
+ ## Root Cause
12
+
13
+ The `__init__.py` file was calling `get_version()` on line 29, but the function was never defined or imported. This was likely removed during a previous refactoring or merge conflict.
14
+
15
+ ## Solution
16
+
17
+ Added the missing `get_version()` function to `__init__.py`. The function:
18
+
19
+ 1. Attempts to read the version from `pyproject.toml` using Python's `tomllib` module
20
+ 2. Falls back to a timestamp-based version if reading fails
21
+ 3. Returns the version string for cache busting purposes
22
+
23
+ ## Implementation
24
+
25
+ ```python
26
+ # Get version from pyproject.toml for cache busting
27
+ def get_version():
28
+ try:
29
+ import tomllib
30
+ pyproject_path = os.path.join(os.path.dirname(__file__), "pyproject.toml")
31
+ with open(pyproject_path, "rb") as f:
32
+ data = tomllib.load(f)
33
+ return data["project"]["version"]
34
+ except Exception:
35
+ # Fallback to timestamp if version reading fails
36
+ import time
37
+ return str(int(time.time()))
38
+ ```
39
+
40
+ ## Notes
41
+
42
+ - The function uses `tomllib` which is available in Python 3.11+
43
+ - For older Python versions, the fallback timestamp mechanism ensures the module still loads
44
+ - The VERSION is used for JavaScript cache busting (see `JAVASCRIPT_CACHE_BUSTING.md`)
45
+ - Current version in `pyproject.toml` is `2.0.0`
46
+
47
+ ## Verification
48
+
49
+ After the fix, the module should import successfully in ComfyUI. Verify with:
50
+
51
+ ```bash
52
+ python3 -m py_compile __init__.py # Should complete without errors
53
+ ```
54
+
55
+ ## Related Documentation
56
+
57
+ - `JAVASCRIPT_CACHE_BUSTING.md` - Details on how VERSION is used for cache busting
58
+ - `CACHE_BUSTING_SUMMARY.md` - Overview of cache busting implementation
59
+
60
+ ## Date
61
+
62
+ Fixed: October 1, 2025
docs/infrastructure/build-deploy/PUBLISHING_WORKFLOW.md ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Publishing Workflow
2
+
3
+ This document explains the automated GitHub Actions workflow for publishing ComfyUI-SwissArmyKnife to the ComfyUI Registry and managing releases.
4
+
5
+ ## Overview
6
+
7
+ The publishing workflow is designed to automatically publish your custom node to the ComfyUI Registry whenever you update the version in `pyproject.toml` and push to the `master` branch. It also creates git tags for release tracking.
8
+
9
+ ## Workflow Components
10
+
11
+ ### 1. Registry Publishing Workflow (`.github/workflows/publish-to-registry.yml`)
12
+
13
+ This is the main publishing workflow that follows the [official ComfyUI Registry documentation](https://docs.comfy.org/registry/publishing#option-2%3A-github-actions).
14
+
15
+ #### Triggers
16
+
17
+ The workflow runs automatically when:
18
+
19
+ - **Version updates**: Changes to `pyproject.toml` are pushed to the `master` branch
20
+ - **Manual trigger**: Can be run manually via GitHub Actions UI (`workflow_dispatch`)
21
+
22
+ #### Workflow Steps
23
+
24
+ 1. **Checkout code**: Fetches the full git history for tagging
25
+ 2. **Extract version**: Reads the current version from `pyproject.toml`
26
+ 3. **Check existing tags**: Prevents duplicate tags if version already exists
27
+ 4. **Publish to Registry**: Uses the official ComfyUI publishing action
28
+ 5. **Create git tag**: Automatically creates a version tag (e.g., `v1.0.2`)
29
+ 6. **Push tag**: Pushes the new tag to GitHub for release tracking
30
+
31
+ #### Required Secrets
32
+
33
+ The workflow requires a GitHub repository secret:
34
+
35
+ - **`REGISTRY_ACCESS_TOKEN`**: Your ComfyUI Registry API key
36
+
37
+ ### 2. Code Quality Workflow (`.github/workflows/ci.yml`)
38
+
39
+ A lightweight CI workflow that runs code quality checks without interfering with publishing.
40
+
41
+ #### Triggers
42
+
43
+ The workflow runs on:
44
+
45
+ - **Push events**: To `master` or `develop` branches
46
+ - **Pull requests**: Targeting `master` or `develop` branches
47
+
48
+ #### Quality Checks
49
+
50
+ 1. **Python setup**: Uses Python 3.11
51
+ 2. **System dependencies**: Installs FFmpeg for video processing
52
+ 3. **Code linting**: Runs `ruff` for code quality
53
+ 4. **Import validation**: Ensures custom nodes load correctly
54
+ 5. **ComfyUI integration**: Verifies all required exports exist
55
+ 6. **Configuration validation**: Checks `pyproject.toml` structure
56
+
57
+ ## Usage Instructions
58
+
59
+ ### Initial Setup
60
+
61
+ 1. **Set up ComfyUI Registry account**:
62
+
63
+ - Visit [ComfyUI Registry](https://registry.comfy.org/)
64
+ - Create a publisher account
65
+ - Generate an API key for publishing
66
+
67
+ 2. **Configure GitHub repository**:
68
+
69
+ - Go to Settings → Secrets and Variables → Actions
70
+ - Create a new repository secret named `REGISTRY_ACCESS_TOKEN`
71
+ - Set the value to your ComfyUI Registry API key
72
+
73
+ 3. **Ensure pyproject.toml is configured**:
74
+
75
+ ```toml
76
+ [project]
77
+ name = "comfyui-swissarmyknife"
78
+ version = "0.0.1" # This triggers publishing when changed
79
+ description = "A collection of custom nodes for ComfyUI"
80
+
81
+ [tool.comfy]
82
+ PublisherId = "your-publisher-id" # From ComfyUI Registry
83
+ DisplayName = "ComfyUI-SwissArmyKnife"
84
+ ```
85
+
86
+ ### Publishing a New Version
87
+
88
+ 1. **Develop your changes** on a feature branch
89
+ 2. **Test thoroughly** using the Docker development environment
90
+ 3. **Update the version** in `pyproject.toml`:
91
+ ```toml
92
+ version = "0.0.2" # Increment the version number
93
+ ```
94
+ 4. **Commit and push to master**:
95
+ ```bash
96
+ git add pyproject.toml
97
+ git commit -m "Release version 0.0.2"
98
+ git push origin master
99
+ ```
100
+ 5. **Automatic publishing** kicks in:
101
+ - GitHub Actions detects the `pyproject.toml` change
102
+ - Publishes to ComfyUI Registry
103
+ - Creates git tag `v0.0.2`
104
+ - Users can discover and install the new version
105
+
106
+ ### Manual Publishing
107
+
108
+ You can also trigger publishing manually:
109
+
110
+ 1. Go to GitHub Actions tab in your repository
111
+ 2. Select "Publish to ComfyUI Registry" workflow
112
+ 3. Click "Run workflow"
113
+ 4. Choose the branch (usually `master`)
114
+
115
+ ## Version Management
116
+
117
+ ### Semantic Versioning
118
+
119
+ Follow [semantic versioning](https://semver.org/) for version numbers:
120
+
121
+ - **MAJOR**: Breaking changes (e.g., `1.0.0` → `2.0.0`)
122
+ - **MINOR**: New features, backward compatible (e.g., `1.0.0` → `1.1.0`)
123
+ - **PATCH**: Bug fixes, backward compatible (e.g., `1.0.0` → `1.0.1`)
124
+
125
+ ### Git Tags
126
+
127
+ The workflow automatically creates git tags:
128
+
129
+ - **Format**: `v{version}` (e.g., `v1.0.2`)
130
+ - **Prevents duplicates**: Won't create a tag if it already exists
131
+ - **Release tracking**: Makes it easy to track releases and rollback if needed
132
+
133
+ ## Monitoring and Troubleshooting
134
+
135
+ ### Viewing Workflow Status
136
+
137
+ 1. **GitHub Actions tab**: See all workflow runs and their status
138
+ 2. **Commit badges**: Green checkmark indicates successful publishing
139
+ 3. **ComfyUI Registry**: Verify your node appears at `registry.comfy.org`
140
+
141
+ ### Common Issues
142
+
143
+ #### Publishing Fails
144
+
145
+ - **Check API key**: Ensure `REGISTRY_ACCESS_TOKEN` is correctly set
146
+ - **Check permissions**: Verify your ComfyUI Registry account can publish
147
+ - **Check version format**: Must be valid semantic version (e.g., `1.0.0`)
148
+
149
+ #### Tag Creation Fails
150
+
151
+ - **Check permissions**: GitHub Actions needs write access to create tags
152
+ - **Duplicate tags**: The workflow skips if tag already exists
153
+
154
+ #### CI Checks Fail
155
+
156
+ - **Import errors**: Usually indicates missing dependencies
157
+ - **Linting errors**: Run `ruff check .` locally to see issues
158
+ - **Integration errors**: Verify `__init__.py` exports are correct
159
+
160
+ ### Debug Mode
161
+
162
+ To debug issues, you can add debug output to the workflow:
163
+
164
+ ```yaml
165
+ - name: Debug environment
166
+ run: |
167
+ echo "Current directory: $(pwd)"
168
+ echo "Python version: $(python --version)"
169
+ echo "Installed packages:"
170
+ pip list
171
+ ```
172
+
173
+ ## Best Practices
174
+
175
+ ### Development Workflow
176
+
177
+ 1. **Feature branches**: Develop new features on separate branches
178
+ 2. **Pull requests**: Use PRs to trigger CI checks before merging
179
+ 3. **Version bumping**: Only update version when ready to publish
180
+ 4. **Testing**: Use Docker environment to test before publishing
181
+
182
+ ### Release Process
183
+
184
+ 1. **Update CHANGELOG.md**: Document what's new in each release
185
+ 2. **Test thoroughly**: Ensure all features work as expected
186
+ 3. **Update documentation**: Keep docs in sync with new features
187
+ 4. **Version bump**: Update `pyproject.toml` version as final step
188
+ 5. **Monitor publishing**: Check GitHub Actions and ComfyUI Registry
189
+
190
+ This automated workflow ensures consistent, reliable publishing while maintaining code quality and proper release tracking.
docs/infrastructure/build-deploy/PYTHON_PACKAGE_BUILD_FIX.md ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python Package Build Configuration Fix
2
+
3
+ ## Issue
4
+
5
+ CI was failing during the "Python Code Quality" step with the following errors:
6
+
7
+ 1. **Deprecated license format**: `project.license` as a TOML table is deprecated
8
+ 2. **Multiple top-level packages**: setuptools discovered multiple top-level packages (`web`, `example_nodes`) in flat-layout, which is not allowed
9
+
10
+ ## Solution
11
+
12
+ ### 1. Fixed License Format
13
+
14
+ Changed from the deprecated table format:
15
+
16
+ ```toml
17
+ license = { file = "LICENSE" }
18
+ ```
19
+
20
+ To the new SPDX string format:
21
+
22
+ ```toml
23
+ license = "MIT"
24
+ ```
25
+
26
+ ### 2. Explicit Package Configuration
27
+
28
+ Added explicit setuptools configuration to control package discovery:
29
+
30
+ ```toml
31
+ [tool.setuptools]
32
+ packages = ["utils"]
33
+
34
+ [tool.setuptools.package-data]
35
+ "*" = ["web/js/*.js"]
36
+ ```
37
+
38
+ This tells setuptools to:
39
+
40
+ - Only include the `utils` Python package
41
+ - Include JavaScript files from `web/js/` for all packages (using `"*"` wildcard)
42
+ - Ignore problematic directories like `example_nodes` and `ui-react_backup`
43
+
44
+ ### 3. Fixed Package Data Key Format
45
+
46
+ The `tool.setuptools.package-data` keys must be either:
47
+
48
+ - A valid Python module name (e.g., `"utils"`)
49
+ - The wildcard `"*"` for all packages
50
+
51
+ Using an empty string `""` is invalid and causes validation errors.
52
+
53
+ ### 4. Added MANIFEST.in
54
+
55
+ Created a `MANIFEST.in` file to explicitly control what files are included in the distribution package:
56
+
57
+ - Includes essential files: `__init__.py`, `nodes/`, `web/js/*.js`
58
+ - Excludes development artifacts: `__pycache__`, `example_nodes`, `ui-react_backup`, etc.
59
+
60
+ ## Files Modified
61
+
62
+ - `pyproject.toml` - Updated license format and added setuptools configuration
63
+ - `MANIFEST.in` - New file for explicit package content control
64
+
65
+ ## Additional Fix Required
66
+
67
+ After the initial fix, a second validation error occurred:
68
+
69
+ ```
70
+ configuration error: `tool.setuptools.package-data` keys must be named by python-module-name or '*'
71
+ ```
72
+
73
+ This was fixed by changing the package-data key from `""` (empty string) to `"*"` (wildcard), which is the correct format for including files across all packages.
74
+
75
+ ## Validation
76
+
77
+ The package should now build successfully with:
78
+
79
+ ```bash
80
+ pip install -e .
81
+ ```
82
+
83
+ ## Related Documentation
84
+
85
+ - [setuptools package discovery](https://setuptools.pypa.io/en/latest/userguide/package_discovery.html)
86
+ - [SPDX License Expressions](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license)
87
+ - [MANIFEST.in format](https://packaging.python.org/en/latest/guides/using-manifest-in/)
docs/infrastructure/build-deploy/README.md ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Build & Deployment Documentation
2
+
3
+ Documentation for building, packaging, and publishing ComfyUI-SwissArmyKnife.
4
+
5
+ ## 📄 Documentation Files
6
+
7
+ - **[PUBLISHING_WORKFLOW.md](PUBLISHING_WORKFLOW.md)** - Complete publishing workflow and process
8
+ - **[PYTHON_PACKAGE_BUILD_FIX.md](PYTHON_PACKAGE_BUILD_FIX.md)** - Python package build fixes
9
+ - **[GET_VERSION_IMPORT_FIX.md](GET_VERSION_IMPORT_FIX.md)** - Version import and detection fixes
10
+
11
+ ## 🎯 Quick Reference
12
+
13
+ ### Build Process
14
+
15
+ 1. **Update Version**: Increment version in `pyproject.toml`
16
+ 2. **Run Tests**: Ensure all tests pass
17
+ 3. **Build Package**: `python -m build`
18
+ 4. **Publish**: Via GitHub Actions or manual upload
19
+
20
+ ### Publishing Workflow
21
+
22
+ ```bash
23
+ # 1. Update version in pyproject.toml
24
+ # 2. Commit changes
25
+ git add pyproject.toml
26
+ git commit -m "Bump version to X.Y.Z"
27
+
28
+ # 3. Tag release
29
+ git tag vX.Y.Z
30
+ git push origin vX.Y.Z
31
+
32
+ # 4. GitHub Actions automatically builds and publishes
33
+ ```
34
+
35
+ ## 🔧 Package Configuration
36
+
37
+ ### pyproject.toml
38
+
39
+ Key configuration sections:
40
+
41
+ - `[project]` - Package metadata
42
+ - `[project.dependencies]` - Python dependencies
43
+ - `[build-system]` - Build tool configuration
44
+ - `[tool.*]` - Development tool settings
45
+
46
+ ### Files Included
47
+
48
+ - Python source code (`nodes/`, `web/`)
49
+ - JavaScript widgets (`web/js/`)
50
+ - CSS styles (`web/css/`)
51
+ - Documentation (`docs/`)
52
+ - Examples (`examples/`)
53
+
54
+ ## 🐛 Common Issues
55
+
56
+ 1. **Version Import Fails**: See GET_VERSION_IMPORT_FIX.md
57
+ 2. **Build Fails**: Check Python version and dependencies
58
+ 3. **Package Too Large**: Review included files in MANIFEST.in
59
+ 4. **GitHub Action Fails**: Check workflow file syntax
60
+
61
+ ## 📚 Related Documentation
62
+
63
+ - [Docker](../docker/) - For Docker image publishing
64
+ - [Debug System](../debug/) - For build debugging
65
+
66
+ ---
67
+
68
+ **Category**: Infrastructure
69
+ **Status**: Stable
docs/infrastructure/caching/CACHE_BUSTING_SUMMARY.md ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Cache Busting Implementation Summary
2
+
3
+ ## Overview
4
+
5
+ Successfully implemented a comprehensive cache busting solution for ComfyUI-SwissArmyKnife JavaScript files to ensure browsers load the latest versions instead of cached files.
6
+
7
+ ## Components Implemented
8
+
9
+ ### 1. Version-Based Cache Busting (`__init__.py`)
10
+
11
+ ```python
12
+ # Get version from pyproject.toml for cache busting
13
+ def get_version():
14
+ try:
15
+ import tomllib
16
+ pyproject_path = os.path.join(os.path.dirname(__file__), "pyproject.toml")
17
+ with open(pyproject_path, "rb") as f:
18
+ data = tomllib.load(f)
19
+ return data["project"]["version"]
20
+ except Exception:
21
+ # Fallback to timestamp if version reading fails
22
+ import time
23
+ return str(int(time.time()))
24
+
25
+ VERSION = get_version()
26
+ ```
27
+
28
+ **Purpose**: Automatically extracts version from `pyproject.toml` for version-based cache busting.
29
+
30
+ ### 2. JavaScript Version Tracking (`web/js/swiss-army-knife.js`)
31
+
32
+ ```javascript
33
+ // Version and cache busting info
34
+ const EXTENSION_VERSION = '1.4.0'; // Should match pyproject.toml version
35
+ const LOAD_TIMESTAMP = new Date().toISOString();
36
+
37
+ console.log(
38
+ `Loading swiss-army-knife.js extension v${EXTENSION_VERSION} at ${LOAD_TIMESTAMP}`,
39
+ );
40
+ ```
41
+
42
+ **Purpose**: Tracks extension version and load time for debugging and cache validation.
43
+
44
+ ### 3. Development Utilities Extension
45
+
46
+ ```javascript
47
+ // Cache busting and development utility extension
48
+ app.registerExtension({
49
+ name: 'comfyui_swissarmyknife.cache_control',
50
+
51
+ async setup() {
52
+ // Development utilities (localhost only)
53
+ window.clearSwissArmyKnifeCache = function () {
54
+ /* ... */
55
+ };
56
+ window.reloadSwissArmyKnife = function () {
57
+ /* ... */
58
+ };
59
+
60
+ // Version change detection
61
+ this.checkVersionUpdates();
62
+ },
63
+ });
64
+ ```
65
+
66
+ **Purpose**: Provides development tools and automatic version update notifications.
67
+
68
+ ### 4. Cache Busting Script (`scripts/cache_bust.sh`)
69
+
70
+ ```bash
71
+ #!/bin/bash
72
+ # Automatically sync version between pyproject.toml and JavaScript
73
+ # Generate file hashes for integrity checking
74
+ # Create cache_info.json with metadata
75
+ ```
76
+
77
+ **Purpose**: Automated tool to sync versions and generate cache busting metadata.
78
+
79
+ ### 5. NPM Script Integration (`web/package.json`)
80
+
81
+ ```json
82
+ {
83
+ "scripts": {
84
+ "cache-bust": "../scripts/cache_bust.sh"
85
+ }
86
+ }
87
+ ```
88
+
89
+ **Purpose**: Convenient npm command for developers: `npm run cache-bust`
90
+
91
+ ### 6. Git Integration (`.gitignore`)
92
+
93
+ ```ignore
94
+ # Cache busting files
95
+ cache_info.json
96
+ ```
97
+
98
+ **Purpose**: Prevents committing cache metadata files.
99
+
100
+ ## Usage Scenarios
101
+
102
+ ### For Development Workflow
103
+
104
+ 1. **Make JavaScript changes**
105
+ 2. **Run cache busting**: `./scripts/cache_bust.sh` or `npm run cache-bust`
106
+ 3. **Restart ComfyUI server** (if Python changes)
107
+ 4. **Hard refresh browser**: `Ctrl+F5` / `Cmd+Shift+R`
108
+
109
+ ### For Users Experiencing Cache Issues
110
+
111
+ #### Browser Console Commands (Development Mode)
112
+
113
+ ```javascript
114
+ clearSwissArmyKnifeCache(); // Clear extension cache and reload
115
+ reloadSwissArmyKnife(); // Force reload with cache bypass
116
+ ```
117
+
118
+ #### Manual Cache Clearing
119
+
120
+ - **Hard refresh**: `Ctrl+F5` (Windows/Linux) or `Cmd+Shift+R` (Mac)
121
+ - **Developer Tools**: Network tab → "Disable cache"
122
+ - **Settings**: Clear browsing data
123
+
124
+ ### For Production Deployment
125
+
126
+ - **Version bumps** in `pyproject.toml` automatically trigger cache invalidation
127
+ - **Hash-based validation** ensures file integrity
128
+ - **Automatic notifications** inform users of updates
129
+
130
+ ## Technical Benefits
131
+
132
+ ### Cache Control
133
+
134
+ - ✅ **Version-based cache busting** with `pyproject.toml` integration
135
+ - ✅ **File hash validation** for integrity checking
136
+ - ✅ **Timestamp tracking** for load verification
137
+ - ✅ **Development mode detection** for enhanced debugging
138
+
139
+ ### Developer Experience
140
+
141
+ - ✅ **Automated version syncing** between Python and JavaScript
142
+ - ✅ **One-command cache busting** via script or npm
143
+ - ✅ **Console utilities** for quick cache clearing
144
+ - ✅ **Visual notifications** for version updates
145
+
146
+ ### User Experience
147
+
148
+ - ✅ **Automatic update detection** with notifications
149
+ - ✅ **Clear troubleshooting steps** for cache issues
150
+ - ✅ **Seamless version transitions** without manual intervention
151
+ - ✅ **Development transparency** with version logging
152
+
153
+ ## Files Modified
154
+
155
+ - `__init__.py` - Added version reading and export
156
+ - `web/js/swiss-army-knife.js` - Added version tracking and development utilities
157
+ - `scripts/cache_bust.sh` - Created cache busting automation script
158
+ - `web/package.json` - Added npm script convenience
159
+ - `.gitignore` - Added cache file exclusions
160
+ - `docs/JAVASCRIPT_CACHE_BUSTING.md` - Complete implementation guide
161
+
162
+ ## Testing Results
163
+
164
+ - ✅ **Version extraction** works from `pyproject.toml`
165
+ - ✅ **Cache busting script** generates unique hashes
166
+ - ✅ **JavaScript version tracking** logs correctly
167
+ - ✅ **Development utilities** available on localhost
168
+ - ✅ **File hash changes** detected on content updates
169
+
170
+ ## Next Steps
171
+
172
+ 1. **Test with ComfyUI server** to validate real-world cache busting
173
+ 2. **Document user-facing instructions** for cache troubleshooting
174
+ 3. **Consider CI/CD integration** for automated version management
175
+ 4. **Monitor effectiveness** through user feedback and browser debugging
176
+
177
+ ## Conclusion
178
+
179
+ The implementation provides a robust, multi-layered approach to JavaScript cache busting that addresses both development workflow efficiency and user experience quality. The solution is scalable, maintainable, and provides clear debugging capabilities for ongoing development.
docs/infrastructure/caching/CACHE_OPTIMIZATION_FIX.md ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Cache Optimization Fix
2
+
3
+ ## Issue
4
+
5
+ The cache system was not properly optimized for seed-based media selection, causing unnecessary API calls when users tested different seeds that selected the same media files.
6
+
7
+ ## Root Cause Analysis
8
+
9
+ 1. **Seed Independence**: Different seeds selecting the same file should share the same cache entry
10
+ 2. **Missing Duration Parameter**: Video caching wasn't considering `max_duration` parameter, causing incorrect cache sharing
11
+
12
+ ## Solution Implemented
13
+
14
+ ### 1. Seed-Independent Caching ✅
15
+
16
+ The caching system was already correctly implemented to be seed-independent:
17
+
18
+ - Cache keys are based on `media_identifier = get_file_media_identifier(selected_media_path)`
19
+ - This uses **file path + modification time**, not the seed used to select it
20
+ - Different seeds selecting the same file will have identical cache keys
21
+
22
+ ### 2. Added Duration Parameter to Video Cache ✅
23
+
24
+ Updated video processing cache to include `max_duration`:
25
+
26
+ ```python
27
+ # Before (missing max_duration)
28
+ cache_options = {
29
+ "describe_clothing": describe_clothing,
30
+ "describe_hair_style": describe_hair_style,
31
+ "describe_bokeh": describe_bokeh,
32
+ "describe_subject": describe_subject
33
+ }
34
+
35
+ # After (includes max_duration)
36
+ cache_options = {
37
+ "describe_clothing": describe_clothing,
38
+ "describe_hair_style": describe_hair_style,
39
+ "describe_bokeh": describe_bokeh,
40
+ "describe_subject": describe_subject,
41
+ "max_duration": max_duration # Include duration in cache key
42
+ }
43
+ ```
44
+
45
+ ## Impact
46
+
47
+ ### Before Fix
48
+
49
+ - **Same file, different seeds**: New API call each time ❌
50
+ - **Same file, different duration**: Incorrect cache hit ❌
51
+
52
+ ### After Fix
53
+
54
+ - **Same file, different seeds**: Cache hit ✅
55
+ - **Same file, different duration**: Separate cache entries ✅
56
+
57
+ ## Cache Key Structure
58
+
59
+ Cache keys are now properly based on:
60
+
61
+ 1. **Media identifier**: `file_path + modification_time` (seed-independent)
62
+ 2. **Gemini model**: e.g., `models/gemini-2.5-flash`
63
+ 3. **Options combination**: `describe_*` flags + `max_duration`
64
+ 4. **Model type**: For images only (Text2Image/ImageEdit)
65
+
66
+ ## Validation
67
+
68
+ Test scenarios that should now work efficiently:
69
+
70
+ - ✅ Testing multiple seeds with the same file selected → Cache hit after first call
71
+ - ✅ Different duration limits on same file → Separate cache entries
72
+ - ✅ Different option combinations → Separate cache entries (expected)
73
+ - ✅ Different models → Separate cache entries (expected)
74
+
75
+ ## Files Modified
76
+
77
+ - `nodes/nodes.py` - Added `max_duration` to video cache options
78
+
79
+ ## Related Documentation
80
+
81
+ - `docs/CACHING.md` - General caching implementation details
docs/infrastructure/caching/CACHE_VERIFICATION_OCTOBER_2025.md ADDED
@@ -0,0 +1,272 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Cache Mechanism Verification - MediaDescribe Node
2
+
3
+ **Date:** October 2, 2025
4
+ **Status:** ✅ VERIFIED - All tests passing
5
+
6
+ ## Overview
7
+
8
+ After making significant changes to the `media_describe` nodes, we conducted a comprehensive verification to ensure the caching mechanism is still functioning correctly. This document describes the verification process, findings, and the fix that was implemented.
9
+
10
+ ## Issue Found and Fixed
11
+
12
+ ### Problem
13
+
14
+ The `replace_action_with_twerking` option was being used in video processing to modify the prompt generation, but it was **NOT included in the cache options dictionary**. This meant:
15
+
16
+ - If a user changed this setting from "No" to "Yes" (or vice versa), the cache would return the old result
17
+ - The cache key wouldn't differentiate between videos processed with different `replace_action_with_twerking` settings
18
+ - This could lead to incorrect cached results being returned
19
+
20
+ ### Location
21
+
22
+ File: `nodes/media_describe/mediia_describe.py`, Line ~1100
23
+
24
+ ### Fix Applied
25
+
26
+ Added `replace_action_with_twerking` to the `cache_options` dictionary in the `_process_video` method:
27
+
28
+ ```python
29
+ # Build options dict for caching
30
+ cache_options = {
31
+ "describe_clothing": describe_clothing,
32
+ "change_clothing_color": change_clothing_color,
33
+ "describe_hair_style": describe_hair_style,
34
+ "describe_bokeh": describe_bokeh,
35
+ "describe_subject": describe_subject,
36
+ "replace_action_with_twerking": replace_action_with_twerking, # ← ADDED
37
+ "max_duration": max_duration
38
+ }
39
+ ```
40
+
41
+ ## Verification Tests
42
+
43
+ A comprehensive test suite was created (`test_cache_verification.py`) that validates:
44
+
45
+ ### Test 1: Cache Module Import ✅
46
+
47
+ - Verifies the cache module can be imported
48
+ - Cache instance can be created successfully
49
+ - Cache directory is accessible
50
+
51
+ ### Test 2: File Identifier Generation ✅
52
+
53
+ - Tests identifier generation for non-existent files
54
+ - Tests identifier generation for existing files
55
+ - Verifies different files get different identifiers
56
+ - Confirms identifiers include file path and modification time
57
+
58
+ ### Test 3: Tensor Identifier Generation ✅
59
+
60
+ - Tests identifier generation for tensor data
61
+ - Verifies different tensors get different identifiers
62
+ - Confirms same tensor consistently generates same identifier
63
+ - Validates content-based hashing works correctly
64
+
65
+ ### Test 4: Cache Set/Get Operations ✅
66
+
67
+ - Tests basic cache storage (set)
68
+ - Tests basic cache retrieval (get)
69
+ - Verifies stored data matches retrieved data
70
+ - Confirms timestamps are recorded correctly
71
+
72
+ ### Test 5: Options Affect Cache Key ✅
73
+
74
+ - Tests that changing options creates different cache keys
75
+ - Verifies original options still retrieve original cached result
76
+ - Confirms cache isolation between different option sets
77
+
78
+ ### Test 6: All MediaDescribe Options in Cache ✅
79
+
80
+ **Image Options Tested:**
81
+
82
+ - `describe_clothing` ✅
83
+ - `change_clothing_color` ✅
84
+ - `describe_hair_style` ✅
85
+ - `describe_bokeh` ✅
86
+ - `describe_subject` ✅
87
+
88
+ **Video Options Tested:**
89
+
90
+ - `describe_clothing` ✅
91
+ - `change_clothing_color` ✅
92
+ - `describe_hair_style` ✅
93
+ - `describe_bokeh` ✅
94
+ - `describe_subject` ✅
95
+ - `replace_action_with_twerking` ✅ (The fix we made!)
96
+ - `max_duration` ✅
97
+
98
+ ### Test 7: Cache Info ✅
99
+
100
+ - Tests cache statistics retrieval
101
+ - Verifies entry count is accurate
102
+ - Confirms total size calculation works
103
+
104
+ ## Cache Architecture
105
+
106
+ ### Cache Key Generation
107
+
108
+ The cache uses a multi-component key system:
109
+
110
+ ```
111
+ cache_key = hash(media_identifier + gemini_model + model_type + options_hash)
112
+ ```
113
+
114
+ Where:
115
+
116
+ - **media_identifier**:
117
+ - For files: `file:path:mtime:size`
118
+ - For tensors: `tensor:content_hash`
119
+ - **gemini_model**: Model name (e.g., "models/gemini-2.5-flash")
120
+ - **model_type**: For images only (e.g., "Text2Image", "ImageEdit"), empty string for videos
121
+ - **options_hash**: MD5 hash of JSON-serialized options dictionary
122
+
123
+ ### Options Included in Cache Keys
124
+
125
+ **For Images:**
126
+
127
+ ```python
128
+ {
129
+ "describe_clothing": bool,
130
+ "change_clothing_color": bool,
131
+ "describe_hair_style": bool,
132
+ "describe_bokeh": bool,
133
+ "describe_subject": bool
134
+ }
135
+ ```
136
+
137
+ **For Videos:**
138
+
139
+ ```python
140
+ {
141
+ "describe_clothing": bool,
142
+ "change_clothing_color": bool,
143
+ "describe_hair_style": bool,
144
+ "describe_bokeh": bool,
145
+ "describe_subject": bool,
146
+ "replace_action_with_twerking": bool, # Video-specific
147
+ "max_duration": float # Video-specific
148
+ }
149
+ ```
150
+
151
+ ### Cache Storage
152
+
153
+ - **Location**: `cache/gemini_descriptions/`
154
+ - **Format**: JSON files named `{cache_key}.json`
155
+ - **Current Size**: ~0.05 MB (23 entries as of verification)
156
+
157
+ ### Cache Entry Structure
158
+
159
+ ```json
160
+ {
161
+ "cache_key": "full_hash_string",
162
+ "media_identifier": "file:/path/to/media...",
163
+ "gemini_model": "models/gemini-2.5-flash",
164
+ "model_type": "Text2Image",
165
+ "options": {
166
+ /* all options */
167
+ },
168
+ "description": "Generated description text",
169
+ "timestamp": 1696258971.234,
170
+ "human_timestamp": "2025-10-02 10:22:51"
171
+ }
172
+ ```
173
+
174
+ ## Cache Behavior
175
+
176
+ ### Cache Hit Scenarios
177
+
178
+ A cache hit occurs when:
179
+
180
+ 1. Same media file (path + modification time match)
181
+ 2. Same Gemini model
182
+ 3. Same model type (for images)
183
+ 4. ALL options match exactly
184
+
185
+ ### Cache Miss Scenarios
186
+
187
+ A cache miss occurs when ANY of these change:
188
+
189
+ 1. Different media file or content
190
+ 2. File was modified (mtime changed)
191
+ 3. Different Gemini model selected
192
+ 4. Different model type (for images)
193
+ 5. ANY option value changes (even one boolean flip)
194
+ 6. Duration limit changes (for videos)
195
+
196
+ ## Running the Tests
197
+
198
+ ```bash
199
+ cd /Users/samkumar/Development/dev-lab-hq/ai-image-hub/apps/comfyui-swiss-army-knife
200
+ python3 test_cache_verification.py
201
+ ```
202
+
203
+ Expected output:
204
+
205
+ ```
206
+ ======================================================================
207
+ CACHE VERIFICATION TEST SUITE FOR MEDIADESCRIBE
208
+ ======================================================================
209
+ [... test results ...]
210
+ ======================================================================
211
+ TEST SUMMARY
212
+ ======================================================================
213
+ Tests passed: 7/7
214
+
215
+ ✅ ALL TESTS PASSED - CACHING MECHANISM IS WORKING CORRECTLY
216
+ ```
217
+
218
+ ## Impact of the Fix
219
+
220
+ ### Before Fix
221
+
222
+ - Users changing `replace_action_with_twerking` would get incorrect cached results
223
+ - No cache invalidation when this option changed
224
+ - Potential confusion about why descriptions weren't updating
225
+
226
+ ### After Fix
227
+
228
+ - Each `replace_action_with_twerking` setting gets its own cache entry
229
+ - Cache correctly invalidates when this option changes
230
+ - Users see the expected behavior when toggling this option
231
+
232
+ ## Future Considerations
233
+
234
+ ### Adding New Options
235
+
236
+ When adding new options to `GeminiUtilOptions` or `MediaDescribe`:
237
+
238
+ 1. **Add to cache_options dictionary** in both `_process_image` and/or `_process_video` methods
239
+ 2. **Run the verification tests** to ensure the option affects cache keys
240
+ 3. **Update this documentation** to reflect the new option
241
+
242
+ ### Monitoring Cache Size
243
+
244
+ - Current cache size is minimal (~0.05 MB for 23 entries)
245
+ - Each entry is typically 1-3 KB
246
+ - Consider implementing cache cleanup if size grows significantly
247
+ - Could add max cache age or max cache size limits
248
+
249
+ ### Cache Invalidation
250
+
251
+ Currently, cache invalidation happens automatically through:
252
+
253
+ - File modification time changes (for file-based media)
254
+ - Content hash changes (for tensor-based media)
255
+ - Option changes
256
+ - Model changes
257
+
258
+ No manual cache clearing is implemented, but could be added if needed.
259
+
260
+ ## Related Files
261
+
262
+ - **Cache Module**: `nodes/cache.py`
263
+ - **MediaDescribe Node**: `nodes/media_describe/mediia_describe.py`
264
+ - **Options Node**: `nodes/media_describe/gemini_util_options.py`
265
+ - **Test Suite**: `test_cache_verification.py`
266
+ - **This Documentation**: `docs/CACHE_VERIFICATION_OCTOBER_2025.md`
267
+
268
+ ## Conclusion
269
+
270
+ ✅ **The caching mechanism is working correctly** after the fix was applied. All 7 test suites pass, and all options (including the newly-fixed `replace_action_with_twerking`) properly affect cache key generation.
271
+
272
+ The fix ensures that users will always get the correct cached results based on their current settings, preventing confusion and maintaining the integrity of the caching system.
docs/infrastructure/caching/CACHE_VERIFICATION_SUMMARY.md ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Cache Verification Summary
2
+
3
+ ## Status: ✅ VERIFIED AND FIXED
4
+
5
+ After reviewing the media_describe nodes following recent changes, I verified the caching mechanism and found and fixed one issue.
6
+
7
+ ## Issue Found
8
+
9
+ The `replace_action_with_twerking` option was used in video processing but was **not included in the cache options**. This meant changing this setting wouldn't invalidate the cache, potentially returning incorrect cached results.
10
+
11
+ ## Fix Applied
12
+
13
+ Added `replace_action_with_twerking` to the video cache options in `nodes/media_describe/mediia_describe.py`:
14
+
15
+ ```python
16
+ cache_options = {
17
+ "describe_clothing": describe_clothing,
18
+ "change_clothing_color": change_clothing_color,
19
+ "describe_hair_style": describe_hair_style,
20
+ "describe_bokeh": describe_bokeh,
21
+ "describe_subject": describe_subject,
22
+ "replace_action_with_twerking": replace_action_with_twerking, # ← ADDED
23
+ "max_duration": max_duration
24
+ }
25
+ ```
26
+
27
+ ## Verification Results
28
+
29
+ Created comprehensive test suite (`test_cache_verification.py`) with 7 test suites:
30
+
31
+ ✅ **All 7/7 tests PASSED**
32
+
33
+ Tests verified:
34
+
35
+ 1. Cache module imports correctly
36
+ 2. File identifier generation works
37
+ 3. Tensor identifier generation works
38
+ 4. Cache set/get operations work
39
+ 5. Different options create different cache keys
40
+ 6. **All MediaDescribe options properly affect cache keys** (including the fix)
41
+ 7. Cache statistics retrieval works
42
+
43
+ ## Key Findings
44
+
45
+ ### Image Options (5 total) - All working ✅
46
+
47
+ - describe_clothing
48
+ - change_clothing_color
49
+ - describe_hair_style
50
+ - describe_bokeh
51
+ - describe_subject
52
+
53
+ ### Video Options (7 total) - All working ✅
54
+
55
+ - describe_clothing
56
+ - change_clothing_color
57
+ - describe_hair_style
58
+ - describe_bokeh
59
+ - describe_subject
60
+ - replace_action_with_twerking ← **Fixed**
61
+ - max_duration
62
+
63
+ ## Conclusion
64
+
65
+ **The caching mechanism is now working correctly** for all options in both image and video processing. The fix ensures cache invalidation happens properly when users change any setting.
66
+
67
+ ## Files Changed
68
+
69
+ - ✏️ `nodes/media_describe/mediia_describe.py` - Added missing option to cache_options
70
+ - ➕ `test_cache_verification.py` - Comprehensive test suite
71
+ - ➕ `docs/CACHE_VERIFICATION_OCTOBER_2025.md` - Detailed documentation
72
+
73
+ ## How to Verify
74
+
75
+ ```bash
76
+ python3 test_cache_verification.py
77
+ ```
78
+
79
+ Expected: "✅ ALL TESTS PASSED - CACHING MECHANISM IS WORKING CORRECTLY"
docs/infrastructure/caching/CACHING.md ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Gemini Media Description Caching
2
+
3
+ This document explains the caching functionality implemented for the Gemini custom nodes.
4
+
5
+ ## Overview
6
+
7
+ The caching system automatically stores Gemini API responses to avoid redundant API calls when analyzing the same media with the same description prompt. This provides:
8
+
9
+ - **Fast repeated analyses** - Cached results return in milliseconds instead of waiting for API calls
10
+ - **API cost savings** - Avoids duplicate API requests for identical media+prompt combinations
11
+ - **Transparent operation** - Caching is always enabled and requires no user configuration
12
+ - **Accurate isolation** - Separate cache entries for each unique media+prompt+model combination
13
+
14
+ ## How It Works
15
+
16
+ ### Cache Key Generation
17
+
18
+ Each cache entry uses a unique key based on:
19
+
20
+ 1. **Media identifier** - Uniquely identifies the media content
21
+ 2. **Description mode** - The selected prompt option (e.g., "Describe without clothing")
22
+ 3. **Model settings** - The Gemini model name and type
23
+
24
+ ### Media Identification
25
+
26
+ - **Video files**: Uses file path + modification time + file size
27
+ - **Image tensors**: Uses content hash of the tensor data
28
+ - **Uploaded files**: Uses the file path in ComfyUI's input directory + metadata
29
+
30
+ ### Description Modes
31
+
32
+ Caching works with all 4 description modes:
33
+
34
+ - "Describe without clothing"
35
+ - "Describe with clothing"
36
+ - "Describe without clothing (No bokeh)"
37
+ - "Describe with clothing (No bokeh)"
38
+
39
+ Each mode creates a separate cache entry for the same media file.
40
+
41
+ ### Storage
42
+
43
+ Cache entries are stored as JSON files in the `cache/gemini_descriptions/` directory:
44
+
45
+ - Each file contains the description, metadata, and timestamp
46
+ - Cache persists across ComfyUI restarts
47
+ - Cache directory is created automatically
48
+ - Cache files are excluded from git via `.gitignore`
49
+
50
+ ## Cache Behavior
51
+
52
+ ### Cache Hit (Fast Path)
53
+
54
+ ```
55
+ User analyzes media → Check cache → Found → Return cached description (< 1ms)
56
+ ```
57
+
58
+ ### Cache Miss (API Path)
59
+
60
+ ```
61
+ User analyzes media → Check cache → Not found → Call Gemini API → Store result → Return description
62
+ ```
63
+
64
+ ### Cache Isolation Examples
65
+
66
+ Same video file with different prompts:
67
+
68
+ - `video.mp4` + "Describe without clothing" → Cache entry A
69
+ - `video.mp4` + "Describe with clothing" → Cache entry B
70
+ - `video.mp4` + "Describe without clothing (No bokeh)" → Cache entry C
71
+ - `video.mp4` + "Describe with clothing (No bokeh)" → Cache entry D
72
+
73
+ Same prompt with different models:
74
+
75
+ - `video.mp4` + "Describe without clothing" + `gemini-2.5-flash` → Cache entry A
76
+ - `video.mp4` + "Describe without clothing" + `gemini-2.5-pro` → Cache entry B
77
+
78
+ ## Implementation Details
79
+
80
+ ### Files Modified
81
+
82
+ - `utils/cache.py` - New cache utility module
83
+ - `utils/nodes.py` - Added caching to GeminiVideoDescribe and GeminiImageDescribe classes
84
+
85
+ ### Cache Integration Points
86
+
87
+ 1. **Before Gemini API call** - Check cache for existing result
88
+ 2. **After successful API response** - Store result in cache
89
+ 3. **Cache hit handling** - Return cached result with appropriate status message
90
+
91
+ ### Status Messages
92
+
93
+ Cache hits are indicated in the Gemini status output:
94
+
95
+ ```
96
+ 🤖 Gemini Analysis Status: ✅ Complete (Cached)
97
+ • Model: models/gemini-2.5-flash
98
+ • Cached: 2025-09-02 10:16:32
99
+ ```
100
+
101
+ Regular API calls show:
102
+
103
+ ```
104
+ 🤖 Gemini Analysis Status: ✅ Complete
105
+ • Model: models/gemini-2.5-flash
106
+ • API Key: ****1234
107
+ ```
108
+
109
+ ## Performance Benefits
110
+
111
+ - **First analysis**: Normal API call timing (~2-5 seconds)
112
+ - **Subsequent analyses**: Cache retrieval (~0.1ms)
113
+ - **API savings**: 100% reduction in duplicate calls
114
+ - **User experience**: Instant results for repeated workflows
115
+
116
+ ## Cache Management
117
+
118
+ ### Automatic Behavior
119
+
120
+ - Cache entries are created automatically
121
+ - No user configuration required
122
+ - Cache persists across sessions
123
+ - Old entries remain until manually cleared
124
+
125
+ ### Manual Management
126
+
127
+ The cache can be inspected or cleared programmatically:
128
+
129
+ ```python
130
+ from nodes.cache import get_cache
131
+
132
+ cache = get_cache()
133
+
134
+ # Get cache statistics
135
+ info = cache.get_cache_info()
136
+ print(f"Entries: {info['entries']}, Size: {info['total_size_mb']} MB")
137
+
138
+ # Clear specific entry (not exposed in UI)
139
+ # cache._get_cache_file_path(key) and os.remove()
140
+ ```
141
+
142
+ ### Cache Directory Location
143
+
144
+ - Default: `<comfyui_swissarmyknife>/cache/gemini_descriptions/`
145
+ - Contains JSON files with SHA256 hash names
146
+ - Safe to delete entire directory to clear all cache
147
+
148
+ ## User Workflow Impact
149
+
150
+ The caching is completely transparent to users:
151
+
152
+ 1. **First time analyzing media**: Works exactly as before (API call)
153
+ 2. **Re-analyzing same media+prompt**: Results appear instantly from cache
154
+ 3. **Different prompts on same media**: Each creates new cache entry
155
+ 4. **Different media files**: Each gets separate cache entries
156
+
157
+ Users will notice:
158
+
159
+ - Faster repeated analyses
160
+ - Cache hit indicators in status messages
161
+ - No additional configuration needed
162
+ - Consistent behavior across ComfyUI restarts
docs/infrastructure/caching/README.md ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Caching Documentation
2
+
3
+ Documentation for caching strategies, optimization, and verification systems in ComfyUI-SwissArmyKnife.
4
+
5
+ ## 📄 Documentation Files
6
+
7
+ ### Core Caching
8
+
9
+ - **[CACHING.md](CACHING.md)** - Main caching architecture and strategies
10
+ - **[CACHE_OPTIMIZATION_FIX.md](CACHE_OPTIMIZATION_FIX.md)** - Cache optimization improvements
11
+
12
+ ### Browser Cache Busting
13
+
14
+ - **[CACHE_BUSTING_SUMMARY.md](CACHE_BUSTING_SUMMARY.md)** - Browser cache busting implementation summary
15
+ - **[JAVASCRIPT_CACHE_BUSTING.md](../../features/JAVASCRIPT_CACHE_BUSTING.md)** - JavaScript-specific cache busting (see features/)
16
+
17
+ ### Verification & Testing
18
+
19
+ - **[CACHE_VERIFICATION_OCTOBER_2025.md](CACHE_VERIFICATION_OCTOBER_2025.md)** - October 2025 cache verification tests
20
+ - **[CACHE_VERIFICATION_SUMMARY.md](CACHE_VERIFICATION_SUMMARY.md)** - Cache verification summary and results
21
+
22
+ ## 🎯 Quick Reference
23
+
24
+ ### Cache Types
25
+
26
+ 1. **LoRA Hash Cache**: `cache/lora_hash_cache.json` - Stores LoRA model hashes
27
+ 2. **Gemini Descriptions**: `cache/gemini_descriptions/` - AI-generated descriptions
28
+ 3. **Browser Cache**: JavaScript/CSS file versioning
29
+
30
+ ### Key Features
31
+
32
+ - **Persistent Caching**: Long-term storage of expensive computations
33
+ - **Cache Busting**: Automatic versioning for JavaScript/CSS updates
34
+ - **Verification**: Automated cache integrity checks
35
+ - **Optimization**: Performance improvements through smart caching
36
+
37
+ ## 🔧 Cache Management
38
+
39
+ ### Clear Cache
40
+
41
+ ```bash
42
+ # Clear LoRA hash cache
43
+ rm cache/lora_hash_cache.json
44
+
45
+ # Clear Gemini description cache
46
+ rm -rf cache/gemini_descriptions/*
47
+
48
+ # Clear browser cache (user action)
49
+ # Hard refresh: Ctrl+Shift+R (Windows/Linux) or Cmd+Shift+R (Mac)
50
+ ```
51
+
52
+ ### Verify Cache
53
+
54
+ ```python
55
+ # Run cache verification tests
56
+ python test_cache_verification.py
57
+ ```
58
+
59
+ ## 📚 Related Documentation
60
+
61
+ - [Debug System](../debug/) - For cache debugging
62
+ - [LoRA Loader](../../nodes/lora-loader/) - For LoRA hash caching
63
+ - [Media Describe](../../nodes/media-describe/) - For description caching
64
+
65
+ ---
66
+
67
+ **Category**: Infrastructure
68
+ **Status**: Stable
docs/infrastructure/debug/DEBUG_MODE_IMPLEMENTATION.md ADDED
@@ -0,0 +1,288 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DEBUG Mode Implementation
2
+
3
+ ## Overview
4
+
5
+ The Swiss Army Knife extension now respects the `DEBUG` environment variable setting from `.env` to control console logging in the browser JavaScript.
6
+
7
+ ## How It Works
8
+
9
+ ### Backend (Python)
10
+
11
+ 1. **Config API Endpoint** (`nodes/config_api.py`):
12
+ - Exposes a `/swissarmyknife/config` endpoint
13
+ - Reads `DEBUG` environment variable from `.env`
14
+ - Returns JSON with `debug` boolean flag
15
+ - Registered in `__init__.py` at extension load time
16
+
17
+ 2. **Environment Variable Reading**:
18
+
19
+ ```python
20
+ debug = os.environ.get("DEBUG", "false").lower() in ("true", "1", "yes")
21
+ ```
22
+
23
+ - Supports: `true`, `1`, `yes` (case-insensitive) for enabling debug mode
24
+ - Defaults to `false` if not set
25
+
26
+ ### Frontend (JavaScript)
27
+
28
+ 1. **Debug Configuration Loading** (`web/js/swiss-army-knife.js`):
29
+ - Fetches debug setting from `/swissarmyknife/config` on extension load
30
+ - Stores in `DEBUG_ENABLED` flag
31
+ - Logs debug mode status to console
32
+
33
+ 2. **Conditional Logging Wrapper**:
34
+
35
+ ```javascript
36
+ const debugLog = (...args) => {
37
+ if (DEBUG_ENABLED) {
38
+ console.log(...args);
39
+ }
40
+ };
41
+ ```
42
+
43
+ 3. **Log Classification**:
44
+ - **Debug logs** (controlled by DEBUG flag):
45
+ - `debugLog()` - Implementation details, state tracking, diagnostic info
46
+ - All `[DEBUG]`, `[SERIALIZE]`, `[CONFIGURE]`, `[LOADED]`, `[API]` tagged messages
47
+ - **Always-visible logs** (not controlled by DEBUG flag):
48
+ - `console.log()` - User-facing messages, version info
49
+ - `console.warn()` - Warnings
50
+ - `console.error()` - Errors
51
+ - Extension loading message
52
+ - Debug mode status message
53
+
54
+ ## Configuration
55
+
56
+ ### Enable Debug Mode
57
+
58
+ In `.env`:
59
+
60
+ ```bash
61
+ DEBUG=true
62
+ ```
63
+
64
+ Or any of:
65
+
66
+ ```bash
67
+ DEBUG=1
68
+ DEBUG=yes
69
+ DEBUG=True
70
+ DEBUG=YES
71
+ ```
72
+
73
+ ### Disable Debug Mode
74
+
75
+ In `.env`:
76
+
77
+ ```bash
78
+ DEBUG=false
79
+ ```
80
+
81
+ Or simply omit the `DEBUG` setting entirely (defaults to `false`).
82
+
83
+ ## Testing
84
+
85
+ 1. **Verify Config Endpoint**:
86
+
87
+ ```bash
88
+ curl http://localhost:8188/swissarmyknife/config
89
+ ```
90
+
91
+ Should return: `{"debug": true}` or `{"debug": false}`
92
+
93
+ 2. **Test Debug Mode Enabled**:
94
+ - Set `DEBUG=true` in `.env`
95
+ - Restart ComfyUI server
96
+ - Refresh browser
97
+ - Open browser console
98
+ - Should see: "Swiss Army Knife Debug Mode: ENABLED"
99
+ - Should see debug logs with `[DEBUG]` tags
100
+
101
+ 3. **Test Debug Mode Disabled**:
102
+ - Set `DEBUG=false` in `.env`
103
+ - Restart ComfyUI server
104
+ - Refresh browser
105
+ - Open browser console
106
+ - Should see: "Swiss Army Knife Debug Mode: DISABLED"
107
+ - Should NOT see debug logs with `[DEBUG]` tags
108
+
109
+ ## Implementation Details
110
+
111
+ ### Files Modified
112
+
113
+ 1. **`__init__.py`**:
114
+ - Added config API route registration
115
+ - Added `DEBUG` to exports
116
+
117
+ 2. **`nodes/config_api.py`** (new file):
118
+ - Created config API endpoint
119
+ - Reads DEBUG from environment
120
+
121
+ 3. **`web/js/swiss-army-knife.js`**:
122
+ - Added `loadDebugConfig()` async function
123
+ - Added `debugLog()` wrapper function
124
+ - Replaced ~50+ `console.log()` calls with `debugLog()` for debug-level messages
125
+ - Kept user-facing logs as `console.log()`
126
+
127
+ ### Logging Categories Changed to debugLog()
128
+
129
+ - Node registration messages
130
+ - Widget state serialization/deserialization
131
+ - File upload handlers
132
+ - Workflow loading
133
+ - API event processing
134
+ - Dimensions display updates
135
+ - Media widget management
136
+ - LoRA info extraction
137
+
138
+ ### Logging Categories Kept as console.log()
139
+
140
+ - Extension version and load timestamp
141
+ - Debug mode status (enabled/disabled)
142
+ - Development utility functions
143
+ - Version update notifications
144
+ - Cache control messages
145
+ - User-facing warnings and errors
146
+
147
+ ## Benefits
148
+
149
+ 1. **Cleaner Console**: Users can disable debug logs for cleaner console output in production
150
+ 2. **Debugging**: Developers can enable detailed logging when troubleshooting
151
+ 3. **Centralized Control**: Single environment variable controls all debug logging
152
+ 4. **No Code Changes**: Toggle debug mode without modifying code
153
+ 5. **Server Restart**: Changes to DEBUG setting require server restart (not just browser refresh)
154
+
155
+ ## Future Enhancements
156
+
157
+ Potential improvements:
158
+
159
+ - Add different log levels (DEBUG, INFO, WARN, ERROR)
160
+ - Add per-node debug control
161
+ - Add runtime debug toggle (no server restart needed)
162
+ - Add debug log filtering by category
163
+ - Add debug log export functionality
164
+
165
+ ## Final Statistics
166
+
167
+ After complete implementation:
168
+
169
+ - **Total debugLog calls**: 167 (converted from console.log)
170
+ - **Remaining console.log calls**: 15 (all user-facing or system-required)
171
+ - 1 inside debugLog function itself (required)
172
+ - 2 user-facing status messages (debug mode, extension loading)
173
+ - 2 error/status messages (filename preview error, video preview status)
174
+ - 10 development utility messages (cache busting, localhost only)
175
+ - **Conversion rate**: ~92% of logging now respects DEBUG flag
176
+
177
+ ### Log Categories Converted to debugLog
178
+
179
+ All these message types now respect the DEBUG environment variable:
180
+
181
+ - `[DEBUG]` - Implementation details and diagnostics
182
+ - `[STATE]` - Widget state management
183
+ - `[WIDGET]` - Widget operations
184
+ - `[CONFIGURE]` - Configuration and restoration
185
+ - `[SERIALIZE]` - Workflow serialization
186
+ - `[LOADED]` - Workflow loading
187
+ - `[UPLOAD]` - File upload operations
188
+ - `[API]` - API event handling
189
+ - `[MediaDescribe]` - Media description node diagnostics
190
+ - Widget discovery and manipulation
191
+ - File restoration and state management
192
+ - Dimensions display updates
193
+
194
+ ### User-Facing Messages (Always Visible)
195
+
196
+ These messages always appear regardless of DEBUG setting:
197
+
198
+ - Extension version and load timestamp
199
+ - Debug mode status (ENABLED/DISABLED)
200
+ - Development utilities info (localhost only)
201
+ - Critical error messages
202
+ - Cache clearing confirmations
203
+
204
+ ## Troubleshooting
205
+
206
+ ### "Still seeing debug logs after setting DEBUG=false"
207
+
208
+ 1. **Verify .env file**:
209
+
210
+ ```bash
211
+ cat /Users/samkumar/Development/dev-lab-hq/ai-image-hub/apps/comfyui-swiss-army-knife/.env | grep DEBUG
212
+ ```
213
+
214
+ Should show: `DEBUG=false`
215
+
216
+ 2. **Test config API**:
217
+
218
+ ```bash
219
+ curl http://127.0.0.1:8188/swissarmyknife/config
220
+ ```
221
+
222
+ Should return: `{"debug": false}`
223
+
224
+ If it returns `{"debug": true}`, the .env file isn't being read correctly.
225
+
226
+ 3. **Clear ALL caches**:
227
+ - Stop ComfyUI server completely
228
+ - Clear browser cache (hard refresh: Cmd+Shift+R / Ctrl+Shift+F5)
229
+ - In browser console, run: `localStorage.clear(); sessionStorage.clear()`
230
+ - Or use the built-in utility: `clearSwissArmyKnifeCache()`
231
+ - Restart ComfyUI server
232
+ - Reload page
233
+
234
+ 4. **Check for cached JavaScript**:
235
+ - Browser may have cached the old swiss-army-knife.js
236
+ - Force cache bypass: Disable browser cache in DevTools Network tab
237
+ - Or increment EXTENSION_VERSION in swiss-army-knife.js to force reload
238
+
239
+ 5. **Verify server restart**:
240
+ - Ensure you fully restarted the ComfyUI server (not just refreshed browser)
241
+ - Environment variables are only read at server startup
242
+
243
+ ### "Debug mode status shows DISABLED but still see logs from other extensions"
244
+
245
+ The DEBUG flag only controls Swiss Army Knife logs. Other extensions (Node Enhancer, Super LoRA Loader, etc.) have their own logging that isn't affected by this setting.
246
+
247
+ Logs from other extensions will show different formats:
248
+
249
+ - `extension.js:6753 NodeEnhancer: Registering extension...`
250
+ - `extension.js:6891 Super LoRA Loader: Registering extension...`
251
+
252
+ These are separate extensions and not controlled by Swiss Army Knife's DEBUG setting.
253
+
254
+ ## Final Statistics
255
+
256
+ After complete implementation:
257
+
258
+ - **Total debugLog calls**: 167 (converted from console.log)
259
+ - **Remaining console.log calls**: 15 (all user-facing or system-required)
260
+ - **Conversion rate**: ~92% of logging now respects DEBUG flag
261
+
262
+ ### User-Facing Messages (Always Visible)
263
+
264
+ These messages always appear regardless of DEBUG setting:
265
+
266
+ - Extension version and load timestamp
267
+ - Debug mode status (ENABLED/DISABLED)
268
+ - Development utilities info (localhost only)
269
+ - Critical error messages
270
+
271
+ ## Troubleshooting
272
+
273
+ ### "Still seeing debug logs after setting DEBUG=false"
274
+
275
+ The logs you're seeing are from **other extensions** (Node Enhancer, Super LoRA Loader). Swiss Army Knife debug logs will have tags like `[DEBUG]`, `[STATE]`, `[WIDGET]`, etc.
276
+
277
+ **Verification steps:**
278
+
279
+ 1. Check browser console shows: "Swiss Army Knife Debug Mode: DISABLED"
280
+ 2. Verify no messages with `[DEBUG]`, `[STATE]`, `[WIDGET]` tags appear
281
+ 3. Other extensions' logs (extension.js:XXXX) are normal and unrelated
282
+
283
+ **If Swiss Army Knife debug logs still appear:**
284
+
285
+ 1. Verify `.env` has `DEBUG=false`
286
+ 2. Fully restart ComfyUI server (environment variables load at startup)
287
+ 3. Hard refresh browser (Cmd+Shift+R / Ctrl+Shift+F5)
288
+ 4. Clear browser cache: `clearSwissArmyKnifeCache()` in console
docs/infrastructure/debug/README.md ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Debug System Documentation
2
+
3
+ Unified debug and logging system for ComfyUI-SwissArmyKnife.
4
+
5
+ ## 📄 Documentation Files
6
+
7
+ - **[DEBUG_MODE_IMPLEMENTATION.md](DEBUG_MODE_IMPLEMENTATION.md)** - Debug mode implementation and usage
8
+ - **[UNIFIED_DEBUG_SYSTEM.md](UNIFIED_DEBUG_SYSTEM.md)** - Unified debug system architecture
9
+
10
+ ## 🎯 Quick Reference
11
+
12
+ ### Debug Configuration
13
+
14
+ Debug mode can be enabled/disabled via:
15
+
16
+ 1. **Server Config**: `/swissarmyknife/config` endpoint
17
+ 2. **Environment Variable**: `DEBUG_ENABLED=true`
18
+ 3. **Runtime**: Toggle via API
19
+
20
+ ### Debug Output
21
+
22
+ When enabled, debug output appears in:
23
+
24
+ - Browser console (JavaScript widgets)
25
+ - Server logs (Python nodes)
26
+ - Network tab (API calls)
27
+
28
+ ### Usage
29
+
30
+ ```python
31
+ # Python - use debug logging
32
+ from utils.debug import debug_log
33
+ debug_log("My debug message", variable_name)
34
+ ```
35
+
36
+ ```javascript
37
+ // JavaScript - conditional logging
38
+ const debugLog = (...args) => {
39
+ if (DEBUG_ENABLED) {
40
+ console.log('[ComponentName]', ...args);
41
+ }
42
+ };
43
+ ```
44
+
45
+ ## 🔧 Features
46
+
47
+ ### Unified System
48
+
49
+ - **Consistent Format**: `[ComponentName] Message: data`
50
+ - **Conditional Output**: Only logs when debug mode is enabled
51
+ - **Performance**: Zero overhead when disabled
52
+ - **Granular Control**: Per-component debug levels
53
+
54
+ ### Component Tags
55
+
56
+ - `[VideoPreview]` - Video preview widget debug
57
+ - `[LoRALoader]` - LoRA loading debug
58
+ - `[MediaDescribe]` - Gemini API debug
59
+ - `[CivitAI]` - CivitAI integration debug
60
+ - `[Cache]` - Caching system debug
61
+
62
+ ## 🐛 Debugging Workflow
63
+
64
+ 1. **Enable Debug Mode**: Set `DEBUG_ENABLED=true` in config
65
+ 2. **Reproduce Issue**: Run the workflow that causes the problem
66
+ 3. **Check Logs**: Review browser console and server logs
67
+ 4. **Identify Component**: Look for component tags in logs
68
+ 5. **Analyze Data**: Examine logged variables and state
69
+ 6. **Fix and Test**: Make changes and verify with debug logs
70
+ 7. **Disable Debug**: Turn off debug mode for production
71
+
72
+ ## 📚 Related Documentation
73
+
74
+ - [Caching](../caching/) - For cache-related debugging
75
+ - [All Nodes](../../nodes/) - For node-specific debugging
76
+ - [Features](../../features/) - For feature debugging
77
+
78
+ ---
79
+
80
+ **Category**: Infrastructure
81
+ **Status**: Stable
docs/infrastructure/debug/UNIFIED_DEBUG_SYSTEM.md ADDED
@@ -0,0 +1,293 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Unified Debug Logging System
2
+
3
+ **Created:** October 2, 2025
4
+ **Status:** ✅ Implemented
5
+
6
+ ## Overview
7
+
8
+ ComfyUI-SwissArmyKnife now has a **centralized debug logging system** that respects a single `DEBUG` environment variable across both Python backend and JavaScript frontend code.
9
+
10
+ ## How It Works
11
+
12
+ ### Environment Variable
13
+
14
+ Set the `DEBUG` environment variable to control debug logging:
15
+
16
+ ```bash
17
+ # Enable debug logging
18
+ DEBUG=true
19
+
20
+ # Disable debug logging (default)
21
+ DEBUG=false
22
+
23
+ # Also accepts: 1, yes, True for enabled
24
+ ```
25
+
26
+ ### Backend (Python)
27
+
28
+ All Python debug logging now uses the centralized `debug_utils.py` module:
29
+
30
+ ```python
31
+ from nodes.debug_utils import debug_print, is_debug_enabled
32
+
33
+ # Use debug_print instead of print for debug messages
34
+ debug_print("This will only show when DEBUG=true")
35
+
36
+ # Check if debug is enabled
37
+ if is_debug_enabled():
38
+ # Do expensive debug operations only when needed
39
+ pass
40
+ ```
41
+
42
+ **Files Updated:**
43
+
44
+ - `nodes/debug_utils.py` - New centralized debug utilities module
45
+ - `nodes/config_api.py` - Exposes DEBUG setting to frontend via `/swissarmyknife/config`
46
+ - `__init__.py` - Loads DEBUG from environment
47
+
48
+ ### Frontend (JavaScript)
49
+
50
+ All JavaScript debug logging uses the centralized debug system loaded from server config:
51
+
52
+ ```javascript
53
+ // DEBUG mode - will be loaded from server config
54
+ let DEBUG_ENABLED = false;
55
+
56
+ // Conditional logging wrapper
57
+ const debugLog = (...args) => {
58
+ if (DEBUG_ENABLED) {
59
+ console.log('[ComponentName]', ...args);
60
+ }
61
+ };
62
+
63
+ // Load DEBUG setting from server
64
+ async function loadDebugConfig() {
65
+ const response = await fetch('/swissarmyknife/config');
66
+ const config = await response.json();
67
+ DEBUG_ENABLED = config.debug || false;
68
+ }
69
+ ```
70
+
71
+ **Files Updated:**
72
+
73
+ - `web/js/swiss-army-knife.js` - Main extension debug system
74
+ - `web/js/video_preview/video_preview.js` - Video preview widget debug logging
75
+
76
+ ## Configuration
77
+
78
+ ### 1. Create `.env` file
79
+
80
+ ```bash
81
+ cp .env.example .env
82
+ ```
83
+
84
+ ### 2. Set DEBUG variable
85
+
86
+ Edit `.env`:
87
+
88
+ ```bash
89
+ DEBUG=true # Enable debug logging
90
+ ```
91
+
92
+ ### 3. Restart ComfyUI Server
93
+
94
+ Debug settings are loaded at startup, so you must **restart the ComfyUI server** after changing the DEBUG variable:
95
+
96
+ ```bash
97
+ # Stop ComfyUI
98
+ # Restart ComfyUI
99
+ ```
100
+
101
+ ### 4. Refresh Browser
102
+
103
+ After restarting the server, **hard refresh your browser** to load the new debug configuration:
104
+
105
+ - **Mac**: `Cmd + Shift + R`
106
+ - **Windows/Linux**: `Ctrl + Shift + R`
107
+ - **Or**: Open DevTools → Right-click refresh → "Empty Cache and Hard Reload"
108
+
109
+ ## Benefits
110
+
111
+ ### ✅ Single Source of Truth
112
+
113
+ - One environment variable controls all debug logging
114
+ - No need to edit multiple files to enable/disable debug mode
115
+
116
+ ### ✅ Production Ready
117
+
118
+ - Debug logging disabled by default
119
+ - No performance impact in production
120
+ - Clean console output without debug noise
121
+
122
+ ### ✅ Developer Friendly
123
+
124
+ - Easy to enable debug mode for troubleshooting
125
+ - Consistent debug output format with prefixes
126
+ - Works across both Python and JavaScript
127
+
128
+ ### ✅ Conditional Logging
129
+
130
+ - Only logs when DEBUG=true
131
+ - Avoids cluttering production logs
132
+ - Easy to trace issues in development
133
+
134
+ ## Debug Output Examples
135
+
136
+ ### Python Debug Output
137
+
138
+ ```
139
+ [DEBUG] LoRAInfoExtractor.extract_lora_info called
140
+ - use_civitai_api: True
141
+ - civitai_api_key provided: True
142
+ - fallback_name: 'my_lora'
143
+ [DEBUG] Discovered 3 LoRA entries in stack
144
+ ```
145
+
146
+ ### JavaScript Debug Output
147
+
148
+ ```
149
+ Video Preview Debug Mode: ENABLED
150
+ [VideoPreview] reference_vid raw value: /comfyui-nvidia/temp/video.mp4 string
151
+ [VideoPreview] Loaded reference_vid:
152
+ Extracted: /comfyui-nvidia/temp/video.mp4
153
+ Type: temp
154
+ Subfolder: (none)
155
+ Filename: video.mp4
156
+ URL: /api/view?filename=video.mp4&type=temp&subfolder=
157
+ ```
158
+
159
+ ## Migration Guide
160
+
161
+ ### For Python Code
162
+
163
+ **Before:**
164
+
165
+ ```python
166
+ print("[DEBUG] Some debug message")
167
+ print(f"[DEBUG] Value: {value}")
168
+ ```
169
+
170
+ **After:**
171
+
172
+ ```python
173
+ from nodes.debug_utils import debug_print
174
+
175
+ debug_print("[DEBUG] Some debug message")
176
+ debug_print(f"[DEBUG] Value: {value}")
177
+ ```
178
+
179
+ ### For JavaScript Code
180
+
181
+ **Before:**
182
+
183
+ ```javascript
184
+ const DEBUG = true;
185
+ if (DEBUG) {
186
+ console.log('[Component]', 'debug message');
187
+ }
188
+ ```
189
+
190
+ **After:**
191
+
192
+ ```javascript
193
+ let DEBUG_ENABLED = false;
194
+
195
+ const debugLog = (...args) => {
196
+ if (DEBUG_ENABLED) {
197
+ console.log('[Component]', ...args);
198
+ }
199
+ };
200
+
201
+ async function loadDebugConfig() {
202
+ const response = await fetch('/swissarmyknife/config');
203
+ const config = await response.json();
204
+ DEBUG_ENABLED = config.debug || false;
205
+ }
206
+
207
+ loadDebugConfig();
208
+
209
+ // Use debugLog instead of console.log
210
+ debugLog('debug message');
211
+ ```
212
+
213
+ ## Files to Update (Future Work)
214
+
215
+ The following files still contain hardcoded debug logging that should be migrated to use `debug_utils.py`:
216
+
217
+ ### Python Files (Not Yet Migrated)
218
+
219
+ - `nodes/nodes.py` - LoRA extraction debug logs
220
+ - `nodes/civitai_service.py` - CivitAI API debug logs
221
+ - `nodes/lora_hash_cache.py` - Cache operation logs
222
+ - `nodes/cache.py` - Cache file logs
223
+ - `nodes/utils/video_preview.py` - Video preview logs
224
+ - `nodes/utils/control_panel.py` - Control panel logs
225
+ - `nodes/lora_manager/*.py` - LoRA manager debug logs
226
+
227
+ ### Migration Priority
228
+
229
+ 1. **High Priority**: Core nodes (`nodes.py`, `civitai_service.py`)
230
+ 2. **Medium Priority**: Utility modules (`cache.py`, `lora_hash_cache.py`)
231
+ 3. **Low Priority**: Utility nodes (`control_panel.py`, `video_preview.py`)
232
+
233
+ ## Troubleshooting
234
+
235
+ ### Debug logs not appearing after enabling DEBUG
236
+
237
+ **Solution:**
238
+
239
+ 1. Verify `.env` file exists and contains `DEBUG=true`
240
+ 2. **Restart ComfyUI server** (required)
241
+ 3. **Hard refresh browser** (Cmd+Shift+R)
242
+ 4. Check console for: `Swiss Army Knife Debug Mode: ENABLED`
243
+ 5. Check console for: `Video Preview Debug Mode: ENABLED`
244
+
245
+ ### Environment variable not loading
246
+
247
+ **Solution:**
248
+
249
+ 1. Ensure `.env` file is in the extension root directory
250
+ 2. Check file permissions (should be readable)
251
+ 3. Verify ComfyUI loads `.env` files (may need python-dotenv)
252
+ 4. Try setting environment variable directly before starting ComfyUI:
253
+ ```bash
254
+ export DEBUG=true
255
+ # Start ComfyUI
256
+ ```
257
+
258
+ ### Debug mode enabled but no logs
259
+
260
+ **Solution:**
261
+
262
+ 1. Check that code is using `debug_print()` or `debugLog()`
263
+ 2. Verify `/swissarmyknife/config` endpoint returns `{"debug": true}`
264
+ 3. Check browser console and server logs separately
265
+
266
+ ## API Endpoint
267
+
268
+ ### GET `/swissarmyknife/config`
269
+
270
+ Returns the current debug configuration:
271
+
272
+ ```json
273
+ {
274
+ "debug": true
275
+ }
276
+ ```
277
+
278
+ This endpoint is called by JavaScript extensions to synchronize debug settings with the backend.
279
+
280
+ ## Future Enhancements
281
+
282
+ 1. **Dynamic Debug Toggle**: Add UI button to toggle debug mode without restarting
283
+ 2. **Debug Levels**: Support different debug levels (INFO, DEBUG, TRACE)
284
+ 3. **Component Filtering**: Enable debug for specific components only
285
+ 4. **Log File Output**: Option to write debug logs to file
286
+ 5. **Performance Metrics**: Track and display performance data in debug mode
287
+
288
+ ## Related Documentation
289
+
290
+ - `.env.example` - Environment variable configuration template
291
+ - `nodes/debug_utils.py` - Python debug utilities implementation
292
+ - `nodes/config_api.py` - API endpoint for debug configuration
293
+ - `web/js/swiss-army-knife.js` - JavaScript debug system implementation