bobinamoe commited on
Commit
baac5bb
·
verified ·
1 Parent(s): 6be8636

Upload 1664 files

Browse files

Custom nodes implemented thanks to @Agoodjoe2 on X.

This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +10 -0
  2. custom_nodes/ComfyUI-Crystools/.editorconfig +20 -0
  3. custom_nodes/ComfyUI-Crystools/.eslintrc.cjs +164 -0
  4. custom_nodes/ComfyUI-Crystools/.github/ISSUE_TEMPLATE/bug_report.md +47 -0
  5. custom_nodes/ComfyUI-Crystools/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  6. custom_nodes/ComfyUI-Crystools/.github/workflows/publish.yml +24 -0
  7. custom_nodes/ComfyUI-Crystools/.gitignore +156 -0
  8. custom_nodes/ComfyUI-Crystools/.others/ComfyUI.run.xml +25 -0
  9. custom_nodes/ComfyUI-Crystools/.others/lint.run.xml +12 -0
  10. custom_nodes/ComfyUI-Crystools/.others/pre-commit +33 -0
  11. custom_nodes/ComfyUI-Crystools/.others/typescript.run.xml +12 -0
  12. custom_nodes/ComfyUI-Crystools/.others/version.py +60 -0
  13. custom_nodes/ComfyUI-Crystools/LICENSE +21 -0
  14. custom_nodes/ComfyUI-Crystools/README.md +672 -0
  15. custom_nodes/ComfyUI-Crystools/__init__.py +108 -0
  16. custom_nodes/ComfyUI-Crystools/__pycache__/__init__.cpython-312.pyc +0 -0
  17. custom_nodes/ComfyUI-Crystools/core/__init__.py +6 -0
  18. custom_nodes/ComfyUI-Crystools/core/__pycache__/__init__.cpython-312.pyc +0 -0
  19. custom_nodes/ComfyUI-Crystools/core/__pycache__/common.cpython-312.pyc +0 -0
  20. custom_nodes/ComfyUI-Crystools/core/__pycache__/config.cpython-312.pyc +0 -0
  21. custom_nodes/ComfyUI-Crystools/core/__pycache__/keys.cpython-312.pyc +0 -0
  22. custom_nodes/ComfyUI-Crystools/core/__pycache__/logger.cpython-312.pyc +0 -0
  23. custom_nodes/ComfyUI-Crystools/core/__pycache__/types.cpython-312.pyc +0 -0
  24. custom_nodes/ComfyUI-Crystools/core/__pycache__/version.cpython-312.pyc +0 -0
  25. custom_nodes/ComfyUI-Crystools/core/common.py +119 -0
  26. custom_nodes/ComfyUI-Crystools/core/config.py +7 -0
  27. custom_nodes/ComfyUI-Crystools/core/keys.py +29 -0
  28. custom_nodes/ComfyUI-Crystools/core/logger.py +39 -0
  29. custom_nodes/ComfyUI-Crystools/core/types.py +36 -0
  30. custom_nodes/ComfyUI-Crystools/core/version.py +1 -0
  31. custom_nodes/ComfyUI-Crystools/docs/crystools-save.png +3 -0
  32. custom_nodes/ComfyUI-Crystools/docs/debugger-show-any.png +3 -0
  33. custom_nodes/ComfyUI-Crystools/docs/debugger-show-json.png +3 -0
  34. custom_nodes/ComfyUI-Crystools/docs/debugger-show-metadata.png +3 -0
  35. custom_nodes/ComfyUI-Crystools/docs/image-load.png +3 -0
  36. custom_nodes/ComfyUI-Crystools/docs/image-preview-diff.png +3 -0
  37. custom_nodes/ComfyUI-Crystools/docs/image-preview-metadata.png +3 -0
  38. custom_nodes/ComfyUI-Crystools/docs/image-preview.png +3 -0
  39. custom_nodes/ComfyUI-Crystools/docs/image-resolution.png +3 -0
  40. custom_nodes/ComfyUI-Crystools/docs/image-save.png +3 -0
  41. custom_nodes/ComfyUI-Crystools/docs/jake.gif +3 -0
  42. custom_nodes/ComfyUI-Crystools/docs/list-any.png +3 -0
  43. custom_nodes/ComfyUI-Crystools/docs/list-string.png +3 -0
  44. custom_nodes/ComfyUI-Crystools/docs/menu.png +3 -0
  45. custom_nodes/ComfyUI-Crystools/docs/metadata-comparator-mark.png +3 -0
  46. custom_nodes/ComfyUI-Crystools/docs/metadata-comparator.png +3 -0
  47. custom_nodes/ComfyUI-Crystools/docs/metadata-extractor-photoshop.png +3 -0
  48. custom_nodes/ComfyUI-Crystools/docs/metadata-extractor.png +3 -0
  49. custom_nodes/ComfyUI-Crystools/docs/monitor-settings.png +3 -0
  50. custom_nodes/ComfyUI-Crystools/docs/monitor.png +3 -0
.gitattributes CHANGED
@@ -53,3 +53,13 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
53
  *.jpg filter=lfs diff=lfs merge=lfs -text
54
  *.jpeg filter=lfs diff=lfs merge=lfs -text
55
  *.webp filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
53
  *.jpg filter=lfs diff=lfs merge=lfs -text
54
  *.jpeg filter=lfs diff=lfs merge=lfs -text
55
  *.webp filter=lfs diff=lfs merge=lfs -text
56
+ custom_nodes/comfyui_controlnet_aux/NotoSans-Regular.ttf filter=lfs diff=lfs merge=lfs -text
57
+ custom_nodes/comfyui_controlnet_aux/src/custom_controlnet_aux/mesh_graphormer/hand_landmarker.task filter=lfs diff=lfs merge=lfs -text
58
+ custom_nodes/comfyui-elegant-resource-monitor/web/assets/css/material.woff2 filter=lfs diff=lfs merge=lfs -text
59
+ custom_nodes/comfyui-impact-pack/modules/impact/__pycache__/core.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
60
+ custom_nodes/comfyui-impact-pack/modules/impact/__pycache__/impact_pack.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
61
+ custom_nodes/comfyui-kjnodes/fonts/FreeMono.ttf filter=lfs diff=lfs merge=lfs -text
62
+ custom_nodes/comfyui-kjnodes/fonts/FreeMonoBoldOblique.otf filter=lfs diff=lfs merge=lfs -text
63
+ custom_nodes/comfyui-kjnodes/fonts/TTNorms-Black.otf filter=lfs diff=lfs merge=lfs -text
64
+ custom_nodes/comfyui-kjnodes/nodes/__pycache__/image_nodes.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
65
+ custom_nodes/comfyui-kjnodes/nodes/__pycache__/nodes.cpython-312.pyc filter=lfs diff=lfs merge=lfs -text
custom_nodes/ComfyUI-Crystools/.editorconfig ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # EditorConfig helps developers define and maintain consistent
2
+ # coding styles between different editors and IDEs
3
+ # editorconfig.org
4
+
5
+ root = true
6
+
7
+ [*]
8
+ # Change these settings to your own preference
9
+ indent_style = space
10
+ indent_size = 2
11
+ max_line_length = 120
12
+
13
+ end_of_line = lf
14
+ charset = utf-8
15
+ trim_trailing_whitespace = true
16
+ insert_final_newline = true
17
+
18
+ [*.md]
19
+ max_line_length = off
20
+ trim_trailing_whitespace = false
custom_nodes/ComfyUI-Crystools/.eslintrc.cjs ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ module.exports = {
2
+ root: true,
3
+ env: { browser: true, es2020: true },
4
+ extends: [
5
+ 'eslint:recommended',
6
+ 'plugin:@typescript-eslint/recommended',
7
+ 'plugin:@typescript-eslint/recommended-type-checked',
8
+ 'plugin:@typescript-eslint/stylistic-type-checked'
9
+ ],
10
+ parser: '@typescript-eslint/parser',
11
+ plugins: ['@typescript-eslint', 'import'],
12
+ parserOptions: {
13
+ // tsconfigRootDir: __dirname,
14
+ sourceType: 'module',
15
+ ecmaVersion: 'latest',
16
+ ecmaFeatures: {
17
+ // experimentalObjectRestSpread: true,
18
+ modules: true,
19
+ legacyDecorators: true
20
+ },
21
+ project: ['./tsconfig.json'],
22
+ },
23
+ rules: {
24
+ // 'import/extensions': [
25
+ // 'error',
26
+ // "ignorePackages",
27
+ // {
28
+ // "js": "always",
29
+ // "ts": "never"
30
+ // }
31
+ // ],
32
+ 'import/no-unresolved': ['off'],
33
+ 'class-methods-use-this': ['off'],
34
+ 'radix': ['off'],
35
+ 'import/prefer-default-export': ['off'],
36
+ 'implicit-arrow-linebreak': ['off'],
37
+ 'no-trailing-spaces': [
38
+ 'error', {
39
+ 'skipBlankLines': true,
40
+ 'ignoreComments': true,
41
+ },
42
+ ],
43
+ 'max-len': [
44
+ 'error', {
45
+ 'code': 120,
46
+ },
47
+ ],
48
+ 'prefer-rest-params': ['off'],
49
+
50
+ 'import/no-extraneous-dependencies': [
51
+ 'error', {
52
+ 'devDependencies': ['**/__tests__/*.ts', '**/__mocks__/*.ts'],
53
+ },
54
+ ],
55
+
56
+ 'one-var': ['off'],
57
+
58
+ // false positive https://github.com/typescript-eslint/typescript-eslint/issues/2483
59
+ 'no-shadow': 'off',
60
+ 'object-curly-newline': ["error", {
61
+ "ObjectExpression": { "multiline": true, "minProperties": 8 },
62
+ "ObjectPattern": { "multiline": true, "minProperties": 8 },
63
+ "ImportDeclaration": {"multiline": true, "minProperties": 8 },
64
+ "ExportDeclaration": { "multiline": true, "minProperties": 8 }
65
+ }],
66
+ "@typescript-eslint/explicit-function-return-type": 'error',
67
+ '@typescript-eslint/triple-slash-reference': 'off',
68
+ '@typescript-eslint/no-shadow': 'error',
69
+ '@typescript-eslint/no-unsafe-argument': 'off',
70
+ '@typescript-eslint/no-unsafe-assignment': 'off',
71
+ '@typescript-eslint/no-unsafe-member-access': 'off',
72
+ '@typescript-eslint/no-unsafe-return': 'off',
73
+ '@typescript-eslint/no-unsafe-call': 'off',
74
+ '@typescript-eslint/prefer-nullish-coalescing': 'off',
75
+ '@typescript-eslint/consistent-type-definitions': 'off',
76
+ '@typescript-eslint/no-unused-expressions': [
77
+ 'error',
78
+ {
79
+ 'allowShortCircuit': true,
80
+ 'allowTernary': true,
81
+ },
82
+ ],
83
+ '@typescript-eslint/no-use-before-define': ['off'],
84
+ '@typescript-eslint/no-unused-vars': [
85
+ 'error',
86
+ {'argsIgnorePattern': '^_'},
87
+ ],
88
+ '@typescript-eslint/explicit-module-boundary-types': [
89
+ 'off', {
90
+ allowArgumentsExplicitlyTypedAsAny: true,
91
+ },
92
+ ],
93
+ '@typescript-eslint/no-explicit-any': 'off',
94
+ '@typescript-eslint/ban-ts-comment': [
95
+ 'off',
96
+ {'ts-expect-error': 'allow-with-description'},
97
+ ],
98
+ '@typescript-eslint/no-empty-function': [
99
+ 'error',
100
+ {
101
+ 'allow': [
102
+ 'methods',
103
+ 'asyncMethods',
104
+ ],
105
+ },
106
+ ],
107
+
108
+ 'lines-between-class-members': 'off',
109
+ '@typescript-eslint/lines-between-class-members': 'off',
110
+
111
+ 'curly': ['error', 'multi-line', 'consistent'],
112
+ 'no-unused-vars': 'off',
113
+ 'jest/no-test-prefixes': 'off',
114
+ 'jest/no-focused-tests': 'off',
115
+ 'comma-dangle': ['error', 'only-multiline'],
116
+ 'linebreak-style': ['error', 'unix'],
117
+ 'quotes': ['error', 'single'],
118
+ 'semi': ['error', 'always'],
119
+ 'eqeqeq': ['error', 'always'],
120
+ 'complexity': [
121
+ 'error', {
122
+ max: 8,
123
+ },
124
+ ],
125
+ 'block-scoped-var': 'error',
126
+ 'no-else-return': [
127
+ 'error', {
128
+ allowElseIf: true,
129
+ },
130
+ ],
131
+ 'no-debugger': 'off',
132
+ 'no-eval': 'error',
133
+ 'no-lone-blocks': 'error',
134
+ 'no-multi-spaces': 'error',
135
+ 'no-useless-return': 'error',
136
+ 'no-var': 'error',
137
+ 'no-console': [
138
+ // 'error', {
139
+ // allow: ['warn', 'error'],
140
+ // },
141
+ 'off',
142
+ ],
143
+ 'no-throw-literal': 'error',
144
+ 'newline-per-chained-call': [
145
+ 'error', {
146
+ ignoreChainWithDepth: 4,
147
+ },
148
+ ],
149
+ 'no-extra-boolean-cast': [
150
+ 'error', {
151
+ enforceForLogicalOperands: true,
152
+ },
153
+ ],
154
+ 'no-fallthrough': 'error',
155
+ 'no-use-before-define': 'off',
156
+ 'no-case-declarations': 'off',
157
+ },
158
+ ignorePatterns: [
159
+ 'node_modules',
160
+ 'web/**/*.d.ts',
161
+ 'web/**/*.js'
162
+ ],
163
+ globals: {},
164
+ }
custom_nodes/ComfyUI-Crystools/.github/ISSUE_TEMPLATE/bug_report.md ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Describe the bug**
11
+ A clear and concise description of what the bug is.
12
+
13
+ **To Reproduce**
14
+ __Please attach a workflow file to make it easier for others to reproduce the error!__
15
+
16
+ **Expected behavior**
17
+ A clear and concise description of what you expected to happen.
18
+
19
+ **Screenshots**
20
+ If applicable, add screenshots to help explain your problem.
21
+
22
+ **Error in console:**
23
+ If applicable, add the error message from the console.
24
+
25
+ **Versions:**
26
+ Copy the output of the console (4 parts), like this:
27
+ ```
28
+ ** Python version: 3.10.11 (tags/v3.10.11:7d4cc5a, Apr 5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)]
29
+ ```
30
+ ```
31
+ Total VRAM 12287 MB, total RAM 130996 MB
32
+ Set vram state to: NORMAL_VRAM
33
+ ```
34
+ ```
35
+ [Crystools INFO] Crystools version: 1.9.2
36
+ [Crystools INFO] CPU: AMD Ryzen 9 5950X 16-Core Processor - Arch: AMD64 - OS: Windows 10
37
+ [Crystools INFO] GPU/s:
38
+ [Crystools INFO] 0) NVIDIA GeForce RTX 3080 Ti
39
+ [Crystools INFO] NVIDIA Driver: 546.33
40
+ ```
41
+ ```
42
+ ### Loading: ComfyUI-Manager (V1.25.3)
43
+ ### ComfyUI Revision: 1886 [6a10640f] | Released on '2024-01-08'
44
+ ```
45
+
46
+ **Additional context**
47
+ Add any other context about the problem here.
custom_nodes/ComfyUI-Crystools/.github/ISSUE_TEMPLATE/feature_request.md ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Is your feature request related to a problem? Please describe.**
11
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12
+
13
+ **Describe the solution you'd like**
14
+ A clear and concise description of what you want to happen.
15
+
16
+ **Describe alternatives you've considered**
17
+ A clear and concise description of any alternative solutions or features you've considered.
18
+
19
+ **Additional context**
20
+ Add any other context or screenshots about the feature request here.
custom_nodes/ComfyUI-Crystools/.github/workflows/publish.yml ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Publish to Comfy registry
2
+ on:
3
+ workflow_dispatch:
4
+ push:
5
+ branches:
6
+ - main
7
+ paths:
8
+ - "pyproject.toml"
9
+
10
+ permissions:
11
+ issues: write
12
+
13
+ jobs:
14
+ publish-node:
15
+ name: Publish Custom Node to registry
16
+ runs-on: ubuntu-latest
17
+ if: ${{ github.repository_owner == 'crystian' }}
18
+ steps:
19
+ - name: Check out code
20
+ uses: actions/checkout@v4
21
+ - name: Publish Custom Node
22
+ uses: Comfy-Org/publish-node-action@v1
23
+ with:
24
+ personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
custom_nodes/ComfyUI-Crystools/.gitignore ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ downloads/
14
+ eggs/
15
+ .eggs/
16
+ lib/
17
+ lib64/
18
+ parts/
19
+ sdist/
20
+ var/
21
+ wheels/
22
+ share/python-wheels/
23
+ *.egg-info/
24
+ .installed.cfg
25
+ *.egg
26
+ MANIFEST
27
+
28
+ # PyInstaller
29
+ # Usually these files are written by a python script from a template
30
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
31
+ *.manifest
32
+ *.spec
33
+
34
+ # Installer logs
35
+ pip-log.txt
36
+ pip-delete-this-directory.txt
37
+
38
+ # Unit test / coverage reports
39
+ htmlcov/
40
+ .tox/
41
+ .nox/
42
+ .coverage
43
+ .coverage.*
44
+ .cache
45
+ nosetests.xml
46
+ coverage.xml
47
+ *.cover
48
+ *.py,cover
49
+ .hypothesis/
50
+ .pytest_cache/
51
+ cover/
52
+
53
+ # Translations
54
+ *.mo
55
+ *.pot
56
+
57
+ # Django stuff:
58
+ *.log
59
+ local_settings.py
60
+ db.sqlite3
61
+ db.sqlite3-journal
62
+
63
+ # Flask stuff:
64
+ instance/
65
+ .webassets-cache
66
+
67
+ # Scrapy stuff:
68
+ .scrapy
69
+
70
+ # Sphinx documentation
71
+ docs/_build/
72
+
73
+ # PyBuilder
74
+ .pybuilder/
75
+ target/
76
+
77
+ # Jupyter Notebook
78
+ .ipynb_checkpoints
79
+
80
+ # IPython
81
+ profile_default/
82
+ ipython_config.py
83
+
84
+ # pyenv
85
+ # For a library or package, you might want to ignore these files since the code is
86
+ # intended to run in multiple environments; otherwise, check them in:
87
+ # .python-version
88
+
89
+ # pipenv
90
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
91
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
92
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
93
+ # install all needed dependencies.
94
+ #Pipfile.lock
95
+
96
+ # poetry
97
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
98
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
99
+ # commonly ignored for libraries.
100
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
101
+ #poetry.lock
102
+
103
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
104
+ __pypackages__/
105
+
106
+ # Celery stuff
107
+ celerybeat-schedule
108
+ celerybeat.pid
109
+
110
+ # SageMath parsed files
111
+ *.sage.py
112
+
113
+ # Environments
114
+ .env
115
+ .venv
116
+ env/
117
+ venv/
118
+ ENV/
119
+ env.bak/
120
+ venv.bak/
121
+
122
+ # Spyder project settings
123
+ .spyderproject
124
+ .spyproject
125
+
126
+ # Rope project settings
127
+ .ropeproject
128
+
129
+ # mkdocs documentation
130
+ /site
131
+
132
+ # mypy
133
+ .mypy_cache/
134
+ .dmypy.json
135
+ dmypy.json
136
+
137
+ # Pyre type checker
138
+ .pyre/
139
+
140
+ # pytype static type analyzer
141
+ .pytype/
142
+
143
+ # Cython debug symbols
144
+ cython_debug/
145
+
146
+ # PyCharm
147
+ # JetBrains specific template is maintainted in a separate JetBrains.gitignore that can
148
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
149
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
150
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
151
+ #.idea/
152
+ *.pyc
153
+
154
+ .idea
155
+ /node_modules
156
+ /node.zip
custom_nodes/ComfyUI-Crystools/.others/ComfyUI.run.xml ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <component name="ProjectRunConfigurationManager">
2
+ <configuration default="false" name="ComfyUI" type="PythonConfigurationType" factoryName="Python">
3
+ <module name="ComfyUI" />
4
+ <option name="ENV_FILES" value="" />
5
+ <option name="INTERPRETER_OPTIONS" value="" />
6
+ <option name="PARENT_ENVS" value="true" />
7
+ <envs>
8
+ <env name="PYTHONUNBUFFERED" value="1" />
9
+ <env name="CRYSTOOLS_LOGLEVEL" value="10" />
10
+ </envs>
11
+ <option name="SDK_HOME" value="" />
12
+ <option name="WORKING_DIRECTORY" value="X:\comfy\ComfyUI" />
13
+ <option name="IS_MODULE_SDK" value="true" />
14
+ <option name="ADD_CONTENT_ROOTS" value="true" />
15
+ <option name="ADD_SOURCE_ROOTS" value="true" />
16
+ <option name="SCRIPT_NAME" value="$PROJECT_DIR$/main.py" />
17
+ <option name="PARAMETERS" value="--extra-model-paths-config ..\extra_model_paths.yaml --output-directory ..\..\comfyUI.output --input-directory ..\..\comfyUI.input --disable-auto-launch --preview-size 1024 --front-end-version aComfy-Org/ComfyUI_frontend@latest" />
18
+ <option name="SHOW_COMMAND_LINE" value="false" />
19
+ <option name="EMULATE_TERMINAL" value="false" />
20
+ <option name="MODULE_MODE" value="false" />
21
+ <option name="REDIRECT_INPUT" value="false" />
22
+ <option name="INPUT_FILE" value="" />
23
+ <method v="2" />
24
+ </configuration>
25
+ </component>
custom_nodes/ComfyUI-Crystools/.others/lint.run.xml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <component name="ProjectRunConfigurationManager">
2
+ <configuration default="false" name="lint" type="js.build_tools.npm">
3
+ <package-json value="$PROJECT_DIR$/custom_nodes/comfyui-crystools/package.json" />
4
+ <command value="run" />
5
+ <scripts>
6
+ <script value="lint" />
7
+ </scripts>
8
+ <node-interpreter value="project" />
9
+ <envs />
10
+ <method v="2" />
11
+ </configuration>
12
+ </component>
custom_nodes/ComfyUI-Crystools/.others/pre-commit ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # REMEMBER TO COPY THIS FILE INTO .git/hooks/pre-commit
3
+
4
+ cd ../comfy/ComfyUI
5
+ rm ./custom_nodes/comfyui-crystools/web/*.js -f
6
+
7
+ LOCAL_COMMAND="npm --prefix ./custom_nodes/comfyui-crystools run validate"
8
+ OUTPUT=$($LOCAL_COMMAND 2>&1)
9
+ EXIT_CODE=$?
10
+
11
+ if [ $EXIT_CODE -eq 0 ]; then
12
+ echo "Validate ok"
13
+ cd ../../comfyui-crystools
14
+ else
15
+ echo "Validate KO!"
16
+ echo $OUTPUT
17
+ exit 1
18
+ fi
19
+
20
+ LOCAL_COMMAND="python .others/version.py"
21
+
22
+ OUTPUT=$($LOCAL_COMMAND 2>&1)
23
+ EXIT_CODE=$?
24
+
25
+ if [ $EXIT_CODE -eq 0 ]; then
26
+ echo "Version changed"
27
+ else
28
+ echo "Can't change the version! check the .other/version.py"
29
+ echo $OUTPUT
30
+ exit 1
31
+ fi
32
+
33
+ git add version pyproject.toml __init__.py core/version.py web/*.js
custom_nodes/ComfyUI-Crystools/.others/typescript.run.xml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <component name="ProjectRunConfigurationManager">
2
+ <configuration default="false" name="typescript" type="js.build_tools.npm">
3
+ <package-json value="$PROJECT_DIR$/package.json" />
4
+ <command value="run" />
5
+ <scripts>
6
+ <script value="start" />
7
+ </scripts>
8
+ <node-interpreter value="W:/!Workstation/nodejs/node" />
9
+ <envs />
10
+ <method v="2" />
11
+ </configuration>
12
+ </component>
custom_nodes/ComfyUI-Crystools/.others/version.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ print("-- Setting up the version --")
4
+
5
+ versionLabel = "@version:"
6
+ version_file = os.path.join(os.path.dirname(__file__), "../version")
7
+
8
+ with open(version_file, "r") as f:
9
+ version = f.read().strip()
10
+
11
+ if version is None or version == "":
12
+ raise RuntimeError(f"File without version: {version_file}")
13
+
14
+ print(f"Version to set: {version}")
15
+
16
+ # modify the __init__.py file with @version
17
+ file1 = os.path.join(os.path.dirname(__file__), "../__init__.py")
18
+ print(f"> File1: {file1}")
19
+
20
+ file1VersionFound = False
21
+ # lines = None
22
+ with open(file1, "r") as f:
23
+ lines = f.readlines()
24
+ for line in lines:
25
+ if versionLabel in line:
26
+ file1VersionFound = True
27
+ lines[lines.index(line)] = f"{versionLabel} {version}\n"
28
+
29
+ if not file1VersionFound:
30
+ raise RuntimeError(f"Version label not found in file: {file1}")
31
+
32
+ with open(file1, "w") as f2:
33
+ f2.writelines(lines)
34
+
35
+ file2 = os.path.join(os.path.dirname(__file__), "../core/version.py")
36
+ print(f"> File2 {file2}")
37
+
38
+ with open(file2, "w") as f2:
39
+ f2.writelines([f"version = \"{version}\"\n"])
40
+
41
+
42
+ # modify pyproject.toml file with @version
43
+ file3 = os.path.join(os.path.dirname(__file__), "../pyproject.toml")
44
+ print(f"> File3: {file3}")
45
+
46
+ file3VersionFound = False
47
+ # lines = None
48
+ with open(file3, "r") as f:
49
+ lines = f.readlines()
50
+ for line in lines:
51
+
52
+ if "version = " in line:
53
+ file3VersionFound = True
54
+ lines[lines.index(line)] = f"version = \"{version}\"\n"
55
+
56
+ if not file3VersionFound:
57
+ raise RuntimeError(f"Version label not found in file: {file3}")
58
+
59
+ with open(file3, "w") as f3:
60
+ f3.writelines(lines)
custom_nodes/ComfyUI-Crystools/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Crystian
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
custom_nodes/ComfyUI-Crystools/README.md ADDED
@@ -0,0 +1,672 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # comfyui-crystools [![Donate](https://img.shields.io/badge/Donate-PayPal-blue.svg)](https://paypal.me/crystian77) <a src="https://colab.research.google.com/assets/colab-badge.svg" href="https://colab.research.google.com/drive/1xiTiPmZkcIqNOsLQPO1UNCdJZqgK3U5k?usp=sharing"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open in Colab"></a>
2
+
3
+ **_🪛 A powerful set of tools for your belt when you work with ComfyUI 🪛_**
4
+
5
+ With this suit, you can see the resources monitor, progress bar & time elapsed, metadata and compare between two images, compare between two JSONs, show any value to console/display, pipes, and more!
6
+ This provides better nodes to load/save images, previews, etc, and see "hidden" data without loading a new workflow.
7
+
8
+ ![Show metadata](./docs/jake.gif)
9
+
10
+ # Table of contents
11
+ - [General](#general)
12
+ - [Metadata](#metadata)
13
+ - [Debugger](#debugger)
14
+ - [Image](#image)
15
+ - [Pipe](#pipe)
16
+ - [Utils](#utils)
17
+ - [Primitives](#primitives)
18
+ - [List](#list)
19
+ - [Switch](#switch)
20
+ - Others: [About](#about), [To do](#to-do), [Changelog](#changelog), [Installation](#installation), [Use](#use)
21
+
22
+ ---
23
+
24
+ ## General
25
+
26
+ ### Resources monitor
27
+
28
+ **🎉Finally, you can see the resources used by ComfyUI (CPU, GPU, RAM, VRAM, GPU Temp and space) on the menu in real-time!**
29
+
30
+ Horizontal:
31
+ ![Monitors](./docs/monitor1.webp)
32
+
33
+ Vertical:
34
+ ![Monitors](./docs/monitor3.webp)
35
+
36
+ Now you can identify the bottlenecks in your workflow and know when it's time to restart the server, unload models or even close some tabs!
37
+
38
+ You can configure the refresh rate which resources to show:
39
+
40
+ ![Monitors](./docs/monitor-settings.png)
41
+
42
+ > **Notes:**
43
+ > - The GPU data is only available when you use CUDA (only NVIDIA cards, sorry AMD users).
44
+ > - This extension needs ComfyUI 1915 (or higher).
45
+ > - The cost of the monitor is low (0.1 to 0.5% of utilization), you can disable it from settings (`Refres rate` to `0`).
46
+ > - Data comes from these libraries:
47
+ > - [psutil](https://pypi.org/project/psutil/)
48
+ > - [torch](https://pytorch.org/)
49
+ > - [pynvml](https://pypi.org/project/pynvml/) (official NVIDIA library)
50
+
51
+
52
+ ### Progress bar
53
+
54
+ You can see the progress of your workflow with a progress bar on the menu!
55
+
56
+ ![Progress bar](./docs/progress-bar.png)
57
+
58
+ https://github.com/crystian/comfyui-crystools/assets/3886806/35cc1257-2199-4b85-936e-2e31d892959c
59
+
60
+ Additionally, it shows the time elapsed at the end of the workflow, and you can `click` on it to see the **current working node.**
61
+
62
+ > **Notes:**
63
+ > - If you don't want to see it, you can turn it off from settings (`Show progress bar in menu`)
64
+
65
+
66
+ ## Metadata
67
+
68
+ ### Node: Metadata extractor
69
+
70
+ This node is used to extract the metadata from the image and handle it as a JSON source for other nodes.
71
+ You can see **all information**, even metadata from other sources (like Photoshop, see sample).
72
+
73
+ The input comes from the [load image with metadata](#node-load-image-with-metadata) or [preview from image](#node-preview-from-image) nodes (and others in the future).
74
+
75
+ ![Metadata extractor](./docs/metadata-extractor.png)
76
+
77
+ **Sample:** [metadata-extractor.json](./samples/metadata-extractor.json)
78
+
79
+ ><details>
80
+ > <summary>Other metadata sample (photoshop)</summary>
81
+ >
82
+ > With metadata from Photoshop
83
+ ![Metadata extractor](./docs/metadata-extractor-photoshop.png)
84
+ ></details>
85
+
86
+ ><details>
87
+ > <summary><i>Parameters</i></summary>
88
+ >
89
+ > - input:
90
+ > - metadata_raw: The metadata raw from the image or preview node
91
+ > - Output:
92
+ > - prompt: The prompt used to produce the image.
93
+ > - workflow: The workflow used to produce the image (all information about nodes, values, etc).
94
+ > - file info: The file info of the image/metadata (resolution, size, etc) is human readable.
95
+ > - raw to JSON: The entire metadata is raw but formatted/readable.
96
+ > - raw to property: The entire metadata is raw in "properties" format.
97
+ > - raw to csv: The entire metadata is raw in "csv" format.
98
+ ></details>
99
+
100
+ <br />
101
+
102
+ ### Node: Metadata comparator
103
+
104
+ This node is so useful for comparing two metadata and seeing the differences (**the main reason why I created this extension!**)
105
+
106
+ You can compare 3 inputs: "Prompt", "Workflow" and "Fileinfo"
107
+
108
+ There are three potential "outputs": `values_changed`, `dictionary_item_added`, and `dictionary_item_removed` (in this order of priority).
109
+
110
+ ![Metadata extractor](./docs/metadata-comparator.png)
111
+
112
+ **Sample:** [metadata-comparator.json](./samples/metadata-comparator.json)
113
+
114
+ **Notes:**
115
+ - I use [DeepDiff](https://pypi.org/project/deepdiff) for that. For more info check the link.
116
+ - If you want to compare two JSONs, you can use the [JSON comparator](#node-JSON-comparator) node.
117
+
118
+
119
+ ><details>
120
+ > <summary><i>Parameters</i></summary>
121
+ >
122
+ > - options:
123
+ > - what: What to compare, you can choose between "Prompt", "Workflow" and "Fileinfo"
124
+ > - input:
125
+ > - metadata_raw_old: The metadata raw to start comparing
126
+ > - metadata_raw_new: The metadata raw to compare
127
+ > - Output:
128
+ > - diff: This is the same output you can see in the display of the node; you can use it on other nodes.
129
+ ></details>
130
+
131
+ <br />
132
+
133
+ ---
134
+
135
+ ## Debugger
136
+
137
+ ### Node: Show Metadata
138
+
139
+ With this node, you will be able to see the JSON produced from your entire prompt and workflow so that you can know all the values (and more) of your prompt quickly without opening the file (PNG or JSON).
140
+
141
+ ![Show metadata](./docs/debugger-show-metadata.png)
142
+
143
+ **Sample:** [debugger-metadata.json](./samples/debugger-metadata.json)
144
+
145
+ ><details>
146
+ > <summary><i>Parameters</i></summary>
147
+ >
148
+ > - Options:
149
+ > - Active: Enable/disable the node
150
+ > - Parsed: Show the parsed JSON or plain text
151
+ > - What: Show the prompt or workflow (prompt are values to produce the image, and workflow is the entire workflow of ComfyUI)
152
+ ></details>
153
+
154
+ <br />
155
+
156
+ ### Node: Show any
157
+
158
+ You can see on the console or display any text or data from the nodes. Connect it to what you want to inspect, and you will see it.
159
+
160
+ ![Show any](./docs/debugger-show-any.png)
161
+
162
+ **Sample:** [debugger-any.json](./samples/debugger-any.json)
163
+
164
+ ><details>
165
+ > <summary><i>Parameters</i></summary>
166
+ >
167
+ > - Input:
168
+ > - any_value: Any value to show, which can be a string, number, etc.
169
+ > - Options:
170
+ > - Console: Enable/disable write to console
171
+ > - Display: Enable/disable write on this node
172
+ > - Prefix: Prefix to console
173
+ ></details>
174
+
175
+ <br />
176
+
177
+ ### Node: Show any to JSON
178
+
179
+ It is the same as the previous one, but it formatted the value to JSON (only display).
180
+
181
+ ![Show any](./docs/debugger-show-json.png)
182
+
183
+ **Sample:** [debugger-json.json](./samples/debugger-json.json)
184
+
185
+ ><details>
186
+ > <summary><i>Parameters</i></summary>
187
+ >
188
+ > - Input:
189
+ > - any_value: Any value to try to convert to JSON
190
+ > - Output:
191
+ > - string: The same string is shown on the display
192
+ ></details>
193
+
194
+ <br />
195
+
196
+ ---
197
+
198
+ ## Image
199
+
200
+ ### Node: Load image with metadata
201
+ This node is the same as the default one, but it adds three features: Prompt, Metadata, and supports **subfolders** of the "input" folder.
202
+
203
+ ![Load image with metadata](./docs/image-load.png)
204
+
205
+ **Sample:** [image-load.json](./samples/image-load.json)
206
+
207
+ ><details>
208
+ > <summary><i>Parameters</i></summary>
209
+ >
210
+ > - Input:
211
+ > - image: Read the images from the input folder (and subfolder) (you can drop the image here or even paste an image from the clipboard)
212
+ > - Output:
213
+ > - Image/Mask: The same as the default node
214
+ > - Prompt: The prompt used to produce the image (not the workflow)
215
+ > - Metadata RAW: The metadata raw of the image (full workflow) as string
216
+ ></details>
217
+
218
+ **Note:** The subfolders support inspired on: [comfyui-imagesubfolders](https://github.com/catscandrive/comfyui-imagesubfolders)
219
+
220
+ <br />
221
+
222
+ ### Node: Save image with extra metadata
223
+ This node is the same as the default one, but it adds two features: Save the workflow in the png or not, and you can add any piece of metadata (as JSON).
224
+
225
+ This saves custom data on the image, so you can share it with others, and they can see the workflow and metadata (see [preview from metadata](#node-preview-from-metadata)), even your custom data.
226
+
227
+ It can be any type of information that supports text and JSON.
228
+
229
+ ![Save image with extra metadata](./docs/image-save.png)
230
+
231
+ **Sample:** [image-save.json](./samples/image-save.json)
232
+
233
+ ><details>
234
+ > <summary><i>Parameters</i></summary>
235
+ >
236
+ > - options:
237
+ > - with_workflow: If you want to save into the image workflow (special to share the workflow with others)
238
+ > - Input:
239
+ > - image: The image to save (same as the default node)
240
+ > - Output:
241
+ > - Metadata RAW: The metadata raw of the image (full workflow) as string
242
+ ></details>
243
+
244
+ **Note:** The data is saved as special "exif" (as ComfyUI does) in the png file; you can read it with [Load image with metadata](#node-load-image-with-metadata).
245
+
246
+ > **Important:**
247
+ > - If you want to save your workflow with a particular name and your data as creator, you need to use the [ComfyUI-Crystools-save](https://github.com/crystian/ComfyUI-Crystools-save) extension; try it!
248
+ ![Crystools-save](./docs/crystools-save.png)
249
+
250
+
251
+ <br />
252
+
253
+ ### Node: Preview from image
254
+
255
+ This node is used to preview the image with the **current prompt** and additional features.
256
+
257
+ ![Preview from image](./docs/image-preview.png)
258
+
259
+ **Feature:** It supports cache (shows as "CACHED") (not permanent yet!), so you can disconnect the node and still see the image and data, so you can use it to compare with others!
260
+
261
+ ![Preview from image](./docs/image-preview-diff.png)
262
+
263
+ As you can see the seed, steps, and cfg were changed
264
+
265
+ **Sample:** [image-preview-image.json](./samples/image-preview-image.json)
266
+
267
+ ><details>
268
+ > <summary><i>Parameters</i></summary>
269
+ >
270
+ > - Input:
271
+ > - image: Any kind of image link
272
+ > - Output:
273
+ > - Metadata RAW: The metadata raw of the image and full workflow.
274
+ > - You can use it to **compare with others** (see [metadata comparator](#node-metadata-comparator))
275
+ > - The file info like filename, resolution, datetime and size with **the current prompt, not the original one!** (see important note)
276
+ ></details>
277
+
278
+ > **Important:**
279
+ > - If you want to read the metadata of the image, you need to use the [load image with metadata](#node-load-image-with-metadata) and use the output "metadata RAW" not the image link.
280
+ > - To do a preview, it is necessary to save it first on the temporal folder, and the data shown is from the temporal image, **not the original one** even **the prompt!**
281
+
282
+ <br />
283
+
284
+ ### Node: Preview from metadata
285
+
286
+ This node is used to preview the image from the metadata and shows additional data (all around this one).
287
+ It supports the same features as [preview from image](#node-preview-from-image) (cache, metadata raw, etc.). But the important difference is you see **real data from the image** (not the temporal one or the current prompt).
288
+
289
+ ![Preview from metadata](./docs/image-preview-metadata.png)
290
+
291
+ **Sample:** [image-preview-metadata.json](./samples/image-preview-metadata.json)
292
+
293
+ <br />
294
+
295
+ ### Node: Show resolution
296
+
297
+ This node is used to show the resolution of an image.
298
+
299
+ > Can be used with any image link.
300
+
301
+ ![Show resolution](./docs/image-resolution.png)
302
+
303
+ **Sample:** [image-resolution.json](./samples/image-resolution.json)
304
+
305
+ ><details>
306
+ > <summary><i>Parameters</i></summary>
307
+ >
308
+ > - Input:
309
+ > - image: Any kind of image link
310
+ > - Output:
311
+ > - Width: The width of the image
312
+ > - Height: The height of the image
313
+ ></details>
314
+
315
+ <br />
316
+
317
+ ---
318
+
319
+ ## Pipe
320
+
321
+ ### Nodes: Pipe to/edit any, Pipe from any
322
+
323
+ This powerful set of nodes is used to better organize your pipes.
324
+
325
+ The "Pipe to/edit any" node is used to encapsulate multiple links into a single one. It includes support for editing and easily adding the modified content back to the same pipe number.
326
+
327
+ The "Pipe from any" node is used to extract the content of a pipe.
328
+
329
+ Typical example:
330
+
331
+ ![Pipes](./docs/pipe-0.png)
332
+
333
+ With pipes:
334
+
335
+ ![Pipes](./docs/pipe-1.png)
336
+
337
+ **Sample:** [pipe-1.json](./samples/pipe-1.json)
338
+
339
+ Editing pipes:
340
+
341
+ ![Pipes](./docs/pipe-2.png)
342
+
343
+ **Sample:** [pipe-2.json](./samples/pipe-2.json)
344
+
345
+ ><details>
346
+ > <summary><i>Parameters</i></summary>
347
+ >
348
+ > - Input:
349
+ > - CPipeAny: This is the type of this pipe you can use to edit (see the sample)
350
+ > - any_*: 6 possible inputs to use
351
+ > - Output:
352
+ > - CPipeAny: You can continue the pipe with this output; you can use it to bifurcate the pipe (see the sample)
353
+ ></details>
354
+
355
+ >**Important:**
356
+ > - Please note that it supports "any," meaning it does not validate (not yet!) the correspondence of input nodes with the output ones. When creating the link, it is recommended to link consciously number by number.
357
+ > - "RecursionError" It's crucial to note that the flow of links **must be in the same direction**, and they cannot be mixed with other flows that use the result of this one. Otherwise, this may lead to recursion and block the server (you need to restart it!)
358
+
359
+
360
+ ><details>
361
+ > <summary><i>Bad example with "RecursionError: maximum recursion depth exceeded"</i></summary>
362
+ >
363
+ > If you see something like this on your console, you need to check your pipes. That is bad sample of pipes, you can't mix the flows.
364
+ ![Pipes](./docs/pipe-3.png)
365
+ ></details>
366
+
367
+ <br />
368
+
369
+ ---
370
+
371
+ ## Utils
372
+
373
+ Some useful nodes to use in your workflow.
374
+
375
+ ### Node: JSON comparator
376
+
377
+ This node is so useful to compare two JSONs and see the differences.
378
+
379
+ ![JSON comparator](./docs/utils-json-comparator.png)
380
+
381
+ **Sample:** [utils-json-comparator.json](./samples/utils-json-comparator.json)
382
+
383
+
384
+ ><details>
385
+ > <summary><i>Parameters</i></summary>
386
+ >
387
+ > - input:
388
+ > - json_old: The first JSON to start compare
389
+ > - json_new: The JSON to compare
390
+ > - Output:
391
+ > - diff: A new JSON with the differences
392
+ ></details>
393
+
394
+
395
+ **Notes:**
396
+ As you can see, it is the same as the [metadata comparator](#node-metadata-comparator) but with JSONs.
397
+ The other is intentionally simple to compare two images metadata; this is more generic.
398
+ The main difference is that you can compare any JSON, not only metadata.
399
+
400
+ <br />
401
+
402
+ ### Node: Stats system
403
+
404
+ This node is used to show the system stats (RAM, VRAM, and Space).
405
+ It **should** connect as a pipe.
406
+
407
+ ![JSON comparator](./docs/utils-stats.png)
408
+
409
+ **Sample:** [utils-stats.json](./samples/utils-stats.json)
410
+
411
+ ><details>
412
+ > <summary><i>Parameters</i></summary>
413
+ >
414
+ > - input:
415
+ > - latent: The latent to use to measure the stats
416
+ > - Output:
417
+ > - latent: Return the same latent to continue the pipe
418
+ ></details>
419
+
420
+ **Notes:** The original is in [WAS](https://github.com/WASasquatch/was-node-suite-comfyui), I only show it on the display.
421
+
422
+ <br />
423
+
424
+ ---
425
+
426
+ ## Primitives
427
+
428
+ ### Nodes: Primitive boolean, Primitive integer, Primitive float, Primitive string, Primitive string multiline
429
+
430
+ A set of nodes with primitive values to use in your prompts.
431
+
432
+ ![Primitives](./docs/primitives.png)
433
+
434
+ <br />
435
+
436
+ ---
437
+
438
+ ## List
439
+ A set of nodes with a list of values (any or strings/texts) for any proposal (news nodes to use it coming soon!).
440
+
441
+ > **Important:** You can use other nodes like "Show any" to see the values of the list
442
+
443
+ ### Node: List of strings
444
+
445
+ **Feature:** You can concatenate them.
446
+
447
+ ![Lists](./docs/list-string.png)
448
+
449
+ **Sample:** [list-strings.json](./samples/list-strings.json)
450
+
451
+ ><details>
452
+ > <summary><i>Parameters</i></summary>
453
+ >
454
+ > - Input:
455
+ > - string_*: 8 possible inputs to use
456
+ > - delimiter: Use to concatenate the values on the output
457
+ > - Output:
458
+ > - concatenated: A string with all values concatenated
459
+ > - list_string: The list of strings (only with values)
460
+ ></details>
461
+
462
+ <br />
463
+
464
+ ### Node: List of any
465
+
466
+ You can concatenate any value (it will try to convert it to a string and show the value), so it is util to see several values at the same time.
467
+
468
+ ![Lists](./docs/list-any.png)
469
+
470
+ **Sample:** [list-any.json](./samples/list-any.json)
471
+
472
+ ><details>
473
+ > <summary><i>Parameters</i></summary>
474
+ >
475
+ > - Input:
476
+ > - any_*: 8 possible inputs to use
477
+ > - Output:
478
+ > - list_any: The list of any elements (only with values)
479
+ ></details>
480
+
481
+ <br />
482
+
483
+ ---
484
+
485
+ ## Switch
486
+ A set of nodes to switch between flows.
487
+
488
+ All switches are boolean; you can switch between flows by simply changing the value of the switch.
489
+ You have predefined switches (string, latent, image, conditioning) but you can use "Switch any" for any value/type.
490
+
491
+ ![Switches](./docs/switches.png)
492
+
493
+ **Sample:** [switch.json](./samples/switch.json)
494
+
495
+ <br />
496
+
497
+ ---
498
+
499
+ ## About
500
+
501
+ **Notes from the author:**
502
+ - This is my first project in python ¯\\_(ツ)_/¯ (PR are welcome!)
503
+ - I'm a software engineer but in other languages (web technologies)
504
+ - My Instagram is: https://www.instagram.com/crystian.ia I'll publish my works on it, so consider following me for news! :)
505
+ - I'm not a native English speaker, so sorry for my English :P
506
+
507
+ ---
508
+
509
+ ## To do
510
+ - [ ] Several unit tests
511
+ - [ ] Add permanent cache for preview/metadata image (to survive to F5! or restart the server)
512
+
513
+ ---
514
+
515
+ ## Changelog
516
+
517
+ ### Crystools
518
+
519
+ ### 1.27.0 (17/08/2025)
520
+ - revert the lower case on name, cannot change on registry ¯\_(ツ)_/¯
521
+ - zluda check removed, it is not necessary anymore
522
+
523
+ ### 1.25.3 (27/07/2025)
524
+ - change the name to lower case
525
+
526
+ ### 1.25.1 (02/06/2025)
527
+ - fix issues with switches on settings menu
528
+ - node: "Switch from any" added
529
+ - load image with metadata: filtered (exclude hidden folders an typically metadata files)
530
+ - other fixes
531
+
532
+ ### 1.24.0 (02/06/2025)
533
+ - PRs by community merged
534
+ - Improved VRAM usage/readout
535
+ - HDD error handling
536
+ - Lazy switches
537
+
538
+ ### 1.23.0 (02/06/2025)
539
+ - Jetson support added by @johnnynunez
540
+ - some ui fixes
541
+
542
+ ### 1.20.0 (21/10/2024)
543
+ - BETA of JSON file reader and extractor, to allow you to read your own JSON files and extract the values to use in your workflow
544
+
545
+ ### 1.19.0 (06/10/2024)
546
+ - HORIZONTAL UI! New version is ready! 🎉
547
+
548
+ ### 1.18.0 (21/09/2024)
549
+ - HORIZONTAL UI! 🎉
550
+ - Configurable size of monitors on settings menu
551
+
552
+ ### 1.17.0 (21/09/2024)
553
+ - Settings menu reorganized
554
+ - Preparing for horizontal UI
555
+ - Update from ComfyUI (typescript and new features)
556
+
557
+ ### 1.16.0 (31/07/2024)
558
+ - Rollback of AMD support by manager does not support other repository parameter (https://test.pypi.org/simple by pyrsmi)
559
+
560
+ ### 1.15.0 (21/07/2024)
561
+ - AMD Branch merged to the main branch, should work for AMD users on **Linux**
562
+
563
+ ### 1.14.0 (15/07/2024)
564
+ - Tried to use AMD info, but it breaks installation on windows, so I removed it ¯\_(ツ)_/¯
565
+ - AMD Branch added, if you use AMD and Linux, you can try it (not tested for me)
566
+
567
+ ### 1.13.0 (01/07/2024)
568
+ - Integrate with new ecosystem of ComfyUI
569
+ - Webp support added on load image with metadata node
570
+
571
+ ### 1.12.0 (27/03/2024)
572
+ - GPU Temperature added
573
+
574
+ ### 1.10.0 (17/01/2024)
575
+ - Multi-gpu added
576
+
577
+ ### 1.9.2 (15/01/2024)
578
+ - Big refactor on hardwareInfo and monitor.ts, gpu was separated on another file, preparing for multi-gpu support
579
+
580
+ ### 1.8.0 (14/01/2024) - internal
581
+ - HDD monitor selector on settings
582
+
583
+ ### 1.7.0 (11/01/2024) - internal
584
+ - Typescript added!
585
+
586
+ ### 1.6.0 (11/01/2024)
587
+ - Fix issue [#7](https://github.com/crystian/comfyui-crystools/issues/7) to the thread deadlock on concurrency
588
+
589
+ ### 1.5.0 (10/01/2024)
590
+ - Improvements on the resources monitor and how handle the threads
591
+ - Some fixes
592
+
593
+ ### 1.3.0 (08/01/2024)
594
+ - Added in general Resources monitor (CPU, GPU, RAM, VRAM, and space)
595
+ - Added this icon to identify this set of tools: 🪛
596
+
597
+ ### 1.2.0 (05/01/2024)
598
+ - progress bar added
599
+
600
+ ### 1.1.0 (29/12/2023)
601
+ - Node added: "Save image with extra metadata"
602
+ - Support to **read** Jpeg metadata added (not save)
603
+
604
+ ### 1.0.0 (26/12/2023)
605
+ - First release
606
+
607
+
608
+ ### Crystools-save - DEPRECATED (01/06/2025)
609
+
610
+ ### 1.1.0 (07/01/2024)
611
+ - Labeling updated according to the new version of Crystools (this project)
612
+
613
+ ### 1.0.0 (29/12/2023)
614
+ - Created another extension to save the info about the author on workflow: [ComfyUI-Crystools-save](https://github.com/crystian/ComfyUI-Crystools-save)
615
+
616
+ ---
617
+
618
+ ## Installation
619
+
620
+ ### Install from GitHub
621
+ 1. Install [ComfyUi](https://github.com/comfyanonymous/ComfyUI).
622
+ 2. Clone this repo into `custom_nodes`:
623
+ ```
624
+ cd ComfyUI/custom_nodes
625
+ git clone https://github.com/crystian/comfyui-crystools.git
626
+ cd comfyui-crystools
627
+ pip install -r requirements.txt
628
+ ```
629
+ 3. Start up ComfyUI.
630
+
631
+ #### For AMD users
632
+ If you are an AMD user with Linux, you can try the AMD branch:
633
+
634
+ **ATTENTION:** Don't install with the manager, you need to install manually:
635
+
636
+ ```
637
+ cd ComfyUI/custom_nodes
638
+ git clone -b AMD https://github.com/crystian/comfyui-crystools.git
639
+ cd comfyui-crystools
640
+ pip install -r requirements.txt
641
+ ```
642
+
643
+ ### Install from manager
644
+
645
+ Search for `crystools` in the [manager](https://github.com/ltdrdata/ComfyUI-Manager.git) and install it.
646
+
647
+ ### Using on Google Colab
648
+
649
+ You can use it on Google Colab, but you need to install it manually:
650
+
651
+ [Google Colab](https://colab.research.google.com/drive/1xiTiPmZkcIqNOsLQPO1UNCdJZqgK3U5k?usp=sharing)
652
+
653
+ * Run the first cell to install ComfyUI and launch the server
654
+ * After it finishes, use the link to open the a new tab, looking a line like this:
655
+ ```
656
+ This is the URL to access ComfyUI: https://identifying-complications-fw-some.trycloudflare.com
657
+ ```
658
+
659
+ ---
660
+
661
+ ## Use
662
+
663
+ You can use it as any other node, just using the menu in the category `crystools` or double clicking on the canvas (I recommended using the "oo" to fast filter), all nodes were post fixing with `[Crystools]`.
664
+
665
+ ![Menu](./docs/menu.png)
666
+ ![shortcut](./docs/shortcut.png)
667
+
668
+ If for some reason you need to see the logs, you can define the environment variable `CRYSTOOLS_LOGLEVEL` and set the [value](https://docs.python.org/es/3/howto/logging.html).
669
+
670
+ ---
671
+
672
+ Made with ❤️ by Crystian.
custom_nodes/ComfyUI-Crystools/__init__.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ @author: Crystian
3
+ @title: Crystools
4
+ @nickname: Crystools
5
+ @version: 1.27.3
6
+ @project: "https://github.com/crystian/comfyui-crystools",
7
+ @description: Plugins for multiples uses, mainly for debugging, you need them! IG: https://www.instagram.com/crystian.ia
8
+ """
9
+
10
+ from .core import version, logger
11
+ logger.info(f'Crystools version: {version}')
12
+
13
+ from .nodes._names import CLASSES
14
+ from .nodes.primitive import CBoolean, CText, CTextML, CInteger, CFloat
15
+ from .nodes.switch import CSwitchBooleanAny, CSwitchBooleanLatent, CSwitchBooleanConditioning, CSwitchBooleanImage, \
16
+ CSwitchBooleanString, CSwitchBooleanMask, CSwitchFromAny
17
+ from .nodes.debugger import CConsoleAny, CConsoleAnyToJson
18
+ from .nodes.image import CImagePreviewFromImage, CImageLoadWithMetadata, CImageGetResolution, CImagePreviewFromMetadata, \
19
+ CImageSaveWithExtraMetadata
20
+ from .nodes.list import CListAny, CListString
21
+ from .nodes.pipe import CPipeToAny, CPipeFromAny
22
+ from .nodes.utils import CUtilsCompareJsons, CUtilsStatSystem
23
+ from .nodes.metadata import CMetadataExtractor, CMetadataCompare
24
+ from .nodes.parameters import CJsonFile, CJsonExtractor
25
+ from .server import *
26
+ from .general import *
27
+
28
+ NODE_CLASS_MAPPINGS = {
29
+ CLASSES.CBOOLEAN_NAME.value: CBoolean,
30
+ CLASSES.CTEXT_NAME.value: CText,
31
+ CLASSES.CTEXTML_NAME.value: CTextML,
32
+ CLASSES.CINTEGER_NAME.value: CInteger,
33
+ CLASSES.CFLOAT_NAME.value: CFloat,
34
+
35
+ CLASSES.CDEBUGGER_CONSOLE_ANY_NAME.value: CConsoleAny,
36
+ CLASSES.CDEBUGGER_CONSOLE_ANY_TO_JSON_NAME.value: CConsoleAnyToJson,
37
+
38
+ CLASSES.CLIST_ANY_NAME.value: CListAny,
39
+ CLASSES.CLIST_STRING_NAME.value: CListString,
40
+
41
+ CLASSES.CSWITCH_FROM_ANY_NAME.value: CSwitchFromAny,
42
+ CLASSES.CSWITCH_ANY_NAME.value: CSwitchBooleanAny,
43
+ CLASSES.CSWITCH_LATENT_NAME.value: CSwitchBooleanLatent,
44
+ CLASSES.CSWITCH_CONDITIONING_NAME.value: CSwitchBooleanConditioning,
45
+ CLASSES.CSWITCH_IMAGE_NAME.value: CSwitchBooleanImage,
46
+ CLASSES.CSWITCH_MASK_NAME.value: CSwitchBooleanMask,
47
+ CLASSES.CSWITCH_STRING_NAME.value: CSwitchBooleanString,
48
+
49
+ CLASSES.CPIPE_TO_ANY_NAME.value: CPipeToAny,
50
+ CLASSES.CPIPE_FROM_ANY_NAME.value: CPipeFromAny,
51
+
52
+ CLASSES.CIMAGE_LOAD_METADATA_NAME.value: CImageLoadWithMetadata,
53
+ CLASSES.CIMAGE_GET_RESOLUTION_NAME.value: CImageGetResolution,
54
+ CLASSES.CIMAGE_PREVIEW_IMAGE_NAME.value: CImagePreviewFromImage,
55
+ CLASSES.CIMAGE_PREVIEW_METADATA_NAME.value: CImagePreviewFromMetadata,
56
+ CLASSES.CIMAGE_SAVE_METADATA_NAME.value: CImageSaveWithExtraMetadata,
57
+
58
+ CLASSES.CMETADATA_EXTRACTOR_NAME.value: CMetadataExtractor,
59
+ CLASSES.CMETADATA_COMPARATOR_NAME.value: CMetadataCompare,
60
+ CLASSES.CUTILS_JSON_COMPARATOR_NAME.value: CUtilsCompareJsons,
61
+ CLASSES.CUTILS_STAT_SYSTEM_NAME.value: CUtilsStatSystem,
62
+ CLASSES.CJSONFILE_NAME.value: CJsonFile,
63
+ CLASSES.CJSONEXTRACTOR_NAME.value: CJsonExtractor,
64
+ }
65
+
66
+ NODE_DISPLAY_NAME_MAPPINGS = {
67
+ CLASSES.CBOOLEAN_NAME.value: CLASSES.CBOOLEAN_DESC.value,
68
+ CLASSES.CTEXT_NAME.value: CLASSES.CTEXT_DESC.value,
69
+ CLASSES.CTEXTML_NAME.value: CLASSES.CTEXTML_DESC.value,
70
+ CLASSES.CINTEGER_NAME.value: CLASSES.CINTEGER_DESC.value,
71
+ CLASSES.CFLOAT_NAME.value: CLASSES.CFLOAT_DESC.value,
72
+
73
+ CLASSES.CDEBUGGER_CONSOLE_ANY_NAME.value: CLASSES.CDEBUGGER_ANY_DESC.value,
74
+ CLASSES.CDEBUGGER_CONSOLE_ANY_TO_JSON_NAME.value: CLASSES.CDEBUGGER_CONSOLE_ANY_TO_JSON_DESC.value,
75
+
76
+ CLASSES.CLIST_ANY_NAME.value: CLASSES.CLIST_ANY_DESC.value,
77
+ CLASSES.CLIST_STRING_NAME.value: CLASSES.CLIST_STRING_DESC.value,
78
+
79
+ CLASSES.CSWITCH_FROM_ANY_NAME.value: CLASSES.CSWITCH_FROM_ANY_DESC.value,
80
+ CLASSES.CSWITCH_ANY_NAME.value: CLASSES.CSWITCH_ANY_DESC.value,
81
+ CLASSES.CSWITCH_LATENT_NAME.value: CLASSES.CSWITCH_LATENT_DESC.value,
82
+ CLASSES.CSWITCH_CONDITIONING_NAME.value: CLASSES.CSWITCH_CONDITIONING_DESC.value,
83
+ CLASSES.CSWITCH_IMAGE_NAME.value: CLASSES.CSWITCH_IMAGE_DESC.value,
84
+ CLASSES.CSWITCH_MASK_NAME.value: CLASSES.CSWITCH_MASK_DESC.value,
85
+ CLASSES.CSWITCH_STRING_NAME.value: CLASSES.CSWITCH_STRING_DESC.value,
86
+
87
+ CLASSES.CPIPE_TO_ANY_NAME.value: CLASSES.CPIPE_TO_ANY_DESC.value,
88
+ CLASSES.CPIPE_FROM_ANY_NAME.value: CLASSES.CPIPE_FROM_ANY_DESC.value,
89
+
90
+ CLASSES.CIMAGE_LOAD_METADATA_NAME.value: CLASSES.CIMAGE_LOAD_METADATA_DESC.value,
91
+ CLASSES.CIMAGE_GET_RESOLUTION_NAME.value: CLASSES.CIMAGE_GET_RESOLUTION_DESC.value,
92
+ CLASSES.CIMAGE_PREVIEW_IMAGE_NAME.value: CLASSES.CIMAGE_PREVIEW_IMAGE_DESC.value,
93
+ CLASSES.CIMAGE_PREVIEW_METADATA_NAME.value: CLASSES.CIMAGE_PREVIEW_METADATA_DESC.value,
94
+ CLASSES.CIMAGE_SAVE_METADATA_NAME.value: CLASSES.CIMAGE_SAVE_METADATA_DESC.value,
95
+
96
+ CLASSES.CMETADATA_EXTRACTOR_NAME.value: CLASSES.CMETADATA_EXTRACTOR_DESC.value,
97
+ CLASSES.CMETADATA_COMPARATOR_NAME.value: CLASSES.CMETADATA_COMPARATOR_DESC.value,
98
+
99
+ CLASSES.CUTILS_JSON_COMPARATOR_NAME.value: CLASSES.CUTILS_JSON_COMPARATOR_DESC.value,
100
+ CLASSES.CUTILS_STAT_SYSTEM_NAME.value: CLASSES.CUTILS_STAT_SYSTEM_DESC.value,
101
+
102
+ CLASSES.CJSONFILE_NAME.value: CLASSES.CJSONFILE_DESC.value,
103
+ CLASSES.CJSONEXTRACTOR_NAME.value: CLASSES.CJSONEXTRACTOR_DESC.value,
104
+ }
105
+
106
+
107
+ WEB_DIRECTORY = "./web"
108
+ __all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]
custom_nodes/ComfyUI-Crystools/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (8.53 kB). View file
 
custom_nodes/ComfyUI-Crystools/core/__init__.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from .logger import *
2
+ from .keys import *
3
+ from .types import *
4
+ from .config import *
5
+ from .common import *
6
+ from .version import *
custom_nodes/ComfyUI-Crystools/core/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (307 Bytes). View file
 
custom_nodes/ComfyUI-Crystools/core/__pycache__/common.cpython-312.pyc ADDED
Binary file (5.19 kB). View file
 
custom_nodes/ComfyUI-Crystools/core/__pycache__/config.cpython-312.pyc ADDED
Binary file (526 Bytes). View file
 
custom_nodes/ComfyUI-Crystools/core/__pycache__/keys.cpython-312.pyc ADDED
Binary file (1.23 kB). View file
 
custom_nodes/ComfyUI-Crystools/core/__pycache__/logger.cpython-312.pyc ADDED
Binary file (1.87 kB). View file
 
custom_nodes/ComfyUI-Crystools/core/__pycache__/types.cpython-312.pyc ADDED
Binary file (1.5 kB). View file
 
custom_nodes/ComfyUI-Crystools/core/__pycache__/version.cpython-312.pyc ADDED
Binary file (198 Bytes). View file
 
custom_nodes/ComfyUI-Crystools/core/common.py ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import torch
4
+ from deepdiff import DeepDiff
5
+ from ..core import CONFIG, logger
6
+
7
+
8
+ # just a helper function to set the widget values (or clear them)
9
+ def setWidgetValues(value=None, unique_id=None, extra_pnginfo=None) -> None:
10
+ if unique_id and extra_pnginfo:
11
+ workflow = extra_pnginfo["workflow"]
12
+ node = next((x for x in workflow["nodes"] if str(x["id"]) == unique_id), None)
13
+
14
+ if node:
15
+ node["widgets_values"] = value
16
+
17
+ return None
18
+
19
+
20
+ # find difference between two jsons
21
+ def findJsonStrDiff(json1, json2):
22
+ msgError = "Could not compare jsons"
23
+ returnJson = {"error": msgError}
24
+ try:
25
+ # TODO review this
26
+ # dict1 = json.loads(json1)
27
+ # dict2 = json.loads(json2)
28
+
29
+ returnJson = findJsonsDiff(json1, json2)
30
+
31
+ returnJson = json.dumps(returnJson, indent=CONFIG["indent"])
32
+ except Exception as e:
33
+ logger.warn(f"{msgError}: {e}")
34
+
35
+ return returnJson
36
+
37
+
38
+ def findJsonsDiff(json1, json2):
39
+ msgError = "Could not compare jsons"
40
+ returnJson = {"error": msgError}
41
+
42
+ try:
43
+ diff = DeepDiff(json1, json2, ignore_order=True, verbose_level=2)
44
+
45
+ returnJson = {k: v for k, v in diff.items() if
46
+ k in ('dictionary_item_added', 'dictionary_item_removed', 'values_changed')}
47
+
48
+ # just for print "values_changed" at first
49
+ returnJson = dict(reversed(returnJson.items()))
50
+
51
+ except Exception as e:
52
+ logger.warn(f"{msgError}: {e}")
53
+
54
+ return returnJson
55
+
56
+
57
+ # powered by:
58
+ # https://github.com/WASasquatch/was-node-suite-comfyui/blob/main/WAS_Node_Suite.py
59
+ # class: WAS_Samples_Passthrough_Stat_System
60
+ def get_system_stats():
61
+ import psutil
62
+
63
+ # RAM
64
+ ram = psutil.virtual_memory()
65
+ ram_used = ram.used / (1024 ** 3)
66
+ ram_total = ram.total / (1024 ** 3)
67
+ ram_stats = f"Used RAM: {ram_used:.2f} GB / Total RAM: {ram_total:.2f} GB"
68
+
69
+ # VRAM (with PyTorch)
70
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
71
+ vram_used = torch.cuda.memory_allocated(device) / (1024 ** 3)
72
+ vram_total = torch.cuda.get_device_properties(device).total_memory / (1024 ** 3)
73
+ vram_stats = f"Used VRAM: {vram_used:.2f} GB / Total VRAM: {vram_total:.2f} GB"
74
+
75
+ # Hard Drive Space
76
+ hard_drive = psutil.disk_usage("/")
77
+ used_space = hard_drive.used / (1024 ** 3)
78
+ total_space = hard_drive.total / (1024 ** 3)
79
+ hard_drive_stats = f"Used Space: {used_space:.2f} GB / Total Space: {total_space:.2f} GB"
80
+
81
+ return [ram_stats, vram_stats, hard_drive_stats]
82
+
83
+
84
+ # return x and y resolution of an image (torch tensor)
85
+ def getResolutionByTensor(image=None) -> dict:
86
+ res = {"x": 0, "y": 0}
87
+
88
+ if image is not None:
89
+ img = image.movedim(-1, 1)
90
+
91
+ res["x"] = img.shape[3]
92
+ res["y"] = img.shape[2]
93
+
94
+ return res
95
+
96
+
97
+ # by https://stackoverflow.com/questions/6080477/how-to-get-the-size-of-tar-gz-in-mb-file-in-python
98
+ def get_size(path):
99
+ size = os.path.getsize(path)
100
+ if size < 1024:
101
+ return f"{size} bytes"
102
+ elif size < pow(1024, 2):
103
+ return f"{round(size / 1024, 2)} KB"
104
+ elif size < pow(1024, 3):
105
+ return f"{round(size / (pow(1024, 2)), 2)} MB"
106
+ elif size < pow(1024, 4):
107
+ return f"{round(size / (pow(1024, 3)), 2)} GB"
108
+
109
+
110
+ def get_nested_value(data, dotted_key, default=None):
111
+ keys = dotted_key.split('.')
112
+ for key in keys:
113
+ if isinstance(data, str):
114
+ data = json.loads(data)
115
+ if isinstance(data, dict) and key in data:
116
+ data = data[key]
117
+ else:
118
+ return default
119
+ return data
custom_nodes/ComfyUI-Crystools/core/config.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import os
2
+ import logging
3
+
4
+ CONFIG = {
5
+ "loglevel": int(os.environ.get("CRYSTOOLS_LOGLEVEL", logging.INFO)),
6
+ "indent": int(os.environ.get("CRYSTOOLS_INDENT", 2))
7
+ }
custom_nodes/ComfyUI-Crystools/core/keys.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from enum import Enum
2
+
3
+
4
+ class TEXTS(Enum):
5
+ CUSTOM_NODE_NAME = "Crystools"
6
+ LOGGER_PREFIX = "Crystools"
7
+ CONCAT = "concatenated"
8
+ INACTIVE_MSG = "inactive"
9
+ INVALID_METADATA_MSG = "Invalid metadata raw"
10
+ FILE_NOT_FOUND = "File not found!"
11
+
12
+
13
+ class CATEGORY(Enum):
14
+ TESTING = "_for_testing"
15
+ MAIN = "crystools 🪛"
16
+ PRIMITIVE = "/Primitive"
17
+ DEBUGGER = "/Debugger"
18
+ LIST = "/List"
19
+ SWITCH = "/Switch"
20
+ PIPE = "/Pipe"
21
+ IMAGE = "/Image"
22
+ UTILS = "/Utils"
23
+ METADATA = "/Metadata"
24
+
25
+
26
+ # remember, all keys should be in lowercase!
27
+ class KEYS(Enum):
28
+ LIST = "list_string"
29
+ PREFIX = "prefix"
custom_nodes/ComfyUI-Crystools/core/logger.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # by https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet/blob/main/control/logger.py
2
+ import sys
3
+ import copy
4
+ import logging
5
+ from .keys import TEXTS
6
+ from .config import CONFIG
7
+
8
+
9
+ class ColoredFormatter(logging.Formatter):
10
+ COLORS = {
11
+ "DEBUG": "\033[0;36m", # CYAN
12
+ "INFO": "\033[0;32m", # GREEN
13
+ "WARNING": "\033[0;33m", # YELLOW
14
+ "ERROR": "\033[0;31m", # RED
15
+ "CRITICAL": "\033[0;37;41m", # WHITE ON RED
16
+ "RESET": "\033[0m", # RESET COLOR
17
+ }
18
+
19
+ def format(self, record):
20
+ colored_record = copy.copy(record)
21
+ levelname = colored_record.levelname
22
+ seq = self.COLORS.get(levelname, self.COLORS["RESET"])
23
+ colored_record.levelname = f"{seq}{levelname}{self.COLORS['RESET']}"
24
+ return super().format(colored_record)
25
+
26
+
27
+ # Create a new logger
28
+ logger = logging.getLogger(TEXTS.LOGGER_PREFIX.value)
29
+ logger.propagate = False
30
+
31
+ # Add handler if we don't have one.
32
+ if not logger.handlers:
33
+ handler = logging.StreamHandler(sys.stdout)
34
+ handler.setFormatter(ColoredFormatter("[%(name)s %(levelname)s] %(message)s"))
35
+ logger.addHandler(handler)
36
+
37
+ # Configure logger
38
+ loglevel = CONFIG["loglevel"]
39
+ logger.setLevel(loglevel)
custom_nodes/ComfyUI-Crystools/core/types.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+
3
+ FLOAT = ("FLOAT", {"default": 1,
4
+ "min": -sys.float_info.max,
5
+ "max": sys.float_info.max,
6
+ "step": 0.01})
7
+
8
+ BOOLEAN = ("BOOLEAN", {"default": True})
9
+ BOOLEAN_FALSE = ("BOOLEAN", {"default": False})
10
+
11
+ INT = ("INT", {"default": 1,
12
+ "min": -sys.maxsize,
13
+ "max": sys.maxsize,
14
+ "step": 1})
15
+
16
+ STRING = ("STRING", {"default": ""})
17
+
18
+ STRING_ML = ("STRING", {"multiline": True, "default": ""})
19
+
20
+ STRING_WIDGET = ("STRING", {"forceInput": True})
21
+
22
+ JSON_WIDGET = ("JSON", {"forceInput": True})
23
+
24
+ METADATA_RAW = ("METADATA_RAW", {"forceInput": True})
25
+
26
+ class AnyType(str):
27
+ """A special class that is always equal in not equal comparisons. Credit to pythongosssss"""
28
+
29
+ def __eq__(self, _) -> bool:
30
+ return True
31
+
32
+ def __ne__(self, __value: object) -> bool:
33
+ return False
34
+
35
+
36
+ any = AnyType("*")
custom_nodes/ComfyUI-Crystools/core/version.py ADDED
@@ -0,0 +1 @@
 
 
1
+ version = "1.27.3"
custom_nodes/ComfyUI-Crystools/docs/crystools-save.png ADDED

Git LFS Details

  • SHA256: a83e0ea651921fb32ec931f2f174dbe961e37dd1b9ad0bc0d86c0ca2b57a377b
  • Pointer size: 130 Bytes
  • Size of remote file: 13.8 kB
custom_nodes/ComfyUI-Crystools/docs/debugger-show-any.png ADDED

Git LFS Details

  • SHA256: 62f5048bbbbc46e1a087d589ee3461707d76713ca3f764600c35c01fcd89e1ed
  • Pointer size: 131 Bytes
  • Size of remote file: 171 kB
custom_nodes/ComfyUI-Crystools/docs/debugger-show-json.png ADDED

Git LFS Details

  • SHA256: e3cb0d6d79ed1439bdb38657b52d041e3306918f66fd89aebe7938d4a4892e81
  • Pointer size: 131 Bytes
  • Size of remote file: 210 kB
custom_nodes/ComfyUI-Crystools/docs/debugger-show-metadata.png ADDED

Git LFS Details

  • SHA256: ffd286e581956bf18ca4e4af14ce7078008f5333ff46de93272d63de90e8ba42
  • Pointer size: 131 Bytes
  • Size of remote file: 269 kB
custom_nodes/ComfyUI-Crystools/docs/image-load.png ADDED

Git LFS Details

  • SHA256: b455ab84f771c1d3e5688c0015df2e2a39836cb2ee80dbe869b88984c007ffc4
  • Pointer size: 131 Bytes
  • Size of remote file: 183 kB
custom_nodes/ComfyUI-Crystools/docs/image-preview-diff.png ADDED

Git LFS Details

  • SHA256: 8cbd7835d6e4b4f542799d9004bd2036813a6600530ac60b4119b7d087b1e448
  • Pointer size: 131 Bytes
  • Size of remote file: 279 kB
custom_nodes/ComfyUI-Crystools/docs/image-preview-metadata.png ADDED

Git LFS Details

  • SHA256: accd1afd495048637a82879e616082be910baedc330ad9143dc1f62c2d043c03
  • Pointer size: 131 Bytes
  • Size of remote file: 270 kB
custom_nodes/ComfyUI-Crystools/docs/image-preview.png ADDED

Git LFS Details

  • SHA256: d680193412c6eebf62327d6529b692a345817697ee86167bffdf27b3f80a4581
  • Pointer size: 131 Bytes
  • Size of remote file: 115 kB
custom_nodes/ComfyUI-Crystools/docs/image-resolution.png ADDED

Git LFS Details

  • SHA256: 32fdfc3bdad190cbb9eb40eba48aaf2ae5c198333c7c5f5cc4fb5b8edf595e68
  • Pointer size: 131 Bytes
  • Size of remote file: 168 kB
custom_nodes/ComfyUI-Crystools/docs/image-save.png ADDED

Git LFS Details

  • SHA256: 81097fccdb79fc5360c4bbbba82a041360a83ca071b0d528b0cd43f780051b04
  • Pointer size: 131 Bytes
  • Size of remote file: 213 kB
custom_nodes/ComfyUI-Crystools/docs/jake.gif ADDED

Git LFS Details

  • SHA256: c56a5c327e232144ee30dc0e4b994ccfd6306defde59706e830044065a5554e9
  • Pointer size: 131 Bytes
  • Size of remote file: 153 kB
custom_nodes/ComfyUI-Crystools/docs/list-any.png ADDED

Git LFS Details

  • SHA256: 115338f3bfa9dc608f9711892efe2928675233ed7f241ea9998c8f221a570efa
  • Pointer size: 130 Bytes
  • Size of remote file: 95 kB
custom_nodes/ComfyUI-Crystools/docs/list-string.png ADDED

Git LFS Details

  • SHA256: 8c995ab876b342480d6a05a1dc68af5846030ffe93b1d9485b4a13815533f0e5
  • Pointer size: 130 Bytes
  • Size of remote file: 79.6 kB
custom_nodes/ComfyUI-Crystools/docs/menu.png ADDED

Git LFS Details

  • SHA256: ffb1cc1eb2c305d90bd687027ec4ff6457e777bd0c71abd0998a8b576b820e9e
  • Pointer size: 130 Bytes
  • Size of remote file: 10.6 kB
custom_nodes/ComfyUI-Crystools/docs/metadata-comparator-mark.png ADDED

Git LFS Details

  • SHA256: bc26cb4a8642d8d0b4dbf62ddac4df31b61412364e5e824b35641173ba63e9a5
  • Pointer size: 131 Bytes
  • Size of remote file: 157 kB
custom_nodes/ComfyUI-Crystools/docs/metadata-comparator.png ADDED

Git LFS Details

  • SHA256: dfbc70cc6f3347d998721ddc01538b7230df58580955a604b191ba24370476fd
  • Pointer size: 131 Bytes
  • Size of remote file: 152 kB
custom_nodes/ComfyUI-Crystools/docs/metadata-extractor-photoshop.png ADDED

Git LFS Details

  • SHA256: cbea5cf84072d64c9581f9924d6f815060a164d16f0bbfd730e1284902882a43
  • Pointer size: 131 Bytes
  • Size of remote file: 181 kB
custom_nodes/ComfyUI-Crystools/docs/metadata-extractor.png ADDED

Git LFS Details

  • SHA256: 03cd71a70f05506d3ca04173151243deb576d8686f2e52eddb392b4b2520db7b
  • Pointer size: 131 Bytes
  • Size of remote file: 262 kB
custom_nodes/ComfyUI-Crystools/docs/monitor-settings.png ADDED

Git LFS Details

  • SHA256: 2a4ebe9c4edd2dd27dda1c0d89d5d5d2188a48261c612eeb5e89c81943b69284
  • Pointer size: 130 Bytes
  • Size of remote file: 33.8 kB
custom_nodes/ComfyUI-Crystools/docs/monitor.png ADDED

Git LFS Details

  • SHA256: 7ba262e65abbfbfd3153295431019ab2741a7ac8cb4418ccfbe10d02fbc0e9bc
  • Pointer size: 130 Bytes
  • Size of remote file: 54.2 kB