comfy-env 0.1.15__py3-none-any.whl → 0.1.17__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. comfy_env/__init__.py +117 -40
  2. comfy_env/cli.py +122 -311
  3. comfy_env/config/__init__.py +12 -4
  4. comfy_env/config/parser.py +30 -79
  5. comfy_env/config/types.py +37 -0
  6. comfy_env/detection/__init__.py +77 -0
  7. comfy_env/detection/cuda.py +61 -0
  8. comfy_env/detection/gpu.py +230 -0
  9. comfy_env/detection/platform.py +70 -0
  10. comfy_env/detection/runtime.py +103 -0
  11. comfy_env/environment/__init__.py +53 -0
  12. comfy_env/environment/cache.py +141 -0
  13. comfy_env/environment/libomp.py +41 -0
  14. comfy_env/environment/paths.py +38 -0
  15. comfy_env/environment/setup.py +91 -0
  16. comfy_env/install.py +134 -331
  17. comfy_env/isolation/__init__.py +32 -2
  18. comfy_env/isolation/tensor_utils.py +83 -0
  19. comfy_env/isolation/workers/__init__.py +16 -0
  20. comfy_env/{workers → isolation/workers}/mp.py +1 -1
  21. comfy_env/{workers → isolation/workers}/subprocess.py +1 -1
  22. comfy_env/isolation/wrap.py +128 -509
  23. comfy_env/packages/__init__.py +60 -0
  24. comfy_env/packages/apt.py +36 -0
  25. comfy_env/packages/cuda_wheels.py +97 -0
  26. comfy_env/packages/node_dependencies.py +77 -0
  27. comfy_env/packages/pixi.py +85 -0
  28. comfy_env/packages/toml_generator.py +88 -0
  29. comfy_env-0.1.17.dist-info/METADATA +225 -0
  30. comfy_env-0.1.17.dist-info/RECORD +36 -0
  31. comfy_env/cache.py +0 -203
  32. comfy_env/nodes.py +0 -187
  33. comfy_env/pixi/__init__.py +0 -48
  34. comfy_env/pixi/core.py +0 -587
  35. comfy_env/pixi/cuda_detection.py +0 -303
  36. comfy_env/pixi/platform/__init__.py +0 -21
  37. comfy_env/pixi/platform/base.py +0 -96
  38. comfy_env/pixi/platform/darwin.py +0 -53
  39. comfy_env/pixi/platform/linux.py +0 -68
  40. comfy_env/pixi/platform/windows.py +0 -284
  41. comfy_env/pixi/resolver.py +0 -198
  42. comfy_env/prestartup.py +0 -208
  43. comfy_env/workers/__init__.py +0 -38
  44. comfy_env/workers/tensor_utils.py +0 -188
  45. comfy_env-0.1.15.dist-info/METADATA +0 -291
  46. comfy_env-0.1.15.dist-info/RECORD +0 -31
  47. /comfy_env/{workers → isolation/workers}/base.py +0 -0
  48. {comfy_env-0.1.15.dist-info → comfy_env-0.1.17.dist-info}/WHEEL +0 -0
  49. {comfy_env-0.1.15.dist-info → comfy_env-0.1.17.dist-info}/entry_points.txt +0 -0
  50. {comfy_env-0.1.15.dist-info → comfy_env-0.1.17.dist-info}/licenses/LICENSE +0 -0
comfy_env/cli.py CHANGED
@@ -1,23 +1,4 @@
1
- """
2
- CLI for comfy-env.
3
-
4
- Provides the `comfy-env` command with subcommands:
5
- - init: Create a default comfy-env.toml
6
- - generate: Generate pixi.toml from comfy-env.toml
7
- - install: Install dependencies from config
8
- - info: Show runtime environment information
9
- - doctor: Verify installation
10
-
11
- Usage:
12
- comfy-env init ---> creates template comfy-env.toml
13
- comfy-env generate nodes/cgal/comfy-env.toml ---> nodes/cgal/pixi.toml
14
- comfy-env install ---> installs from comfy
15
- comfy-env install --dry-run
16
-
17
- comfy-env info
18
-
19
- comfy-env doctor
20
- """
1
+ """CLI for comfy-env."""
21
2
 
22
3
  import argparse
23
4
  import sys
@@ -25,139 +6,56 @@ from pathlib import Path
25
6
  from typing import List, Optional
26
7
 
27
8
  from . import __version__
9
+ from .config import ROOT_CONFIG_FILE_NAME, CONFIG_FILE_NAME
28
10
 
29
11
 
30
12
  def main(args: Optional[List[str]] = None) -> int:
31
- """Main entry point for comfy-env CLI."""
32
- parser = argparse.ArgumentParser(
33
- prog="comfy-env",
34
- description="Environment management for ComfyUI custom nodes",
35
- )
36
- parser.add_argument(
37
- "--version", action="version", version=f"comfy-env {__version__}"
38
- )
39
-
40
- subparsers = parser.add_subparsers(dest="command", help="Available commands")
41
-
42
- # init command
43
- init_parser = subparsers.add_parser(
44
- "init",
45
- help="Create a default comfy-env.toml config file",
46
- description="Initialize a new comfy-env.toml configuration file in the current directory",
47
- )
48
- init_parser.add_argument(
49
- "--force", "-f",
50
- action="store_true",
51
- help="Overwrite existing config file",
52
- )
53
-
54
- # generate command
55
- generate_parser = subparsers.add_parser(
56
- "generate",
57
- help="Generate pixi.toml from comfy-env.toml",
58
- description="Parse comfy-env.toml and generate a pixi.toml in the same directory",
59
- )
60
- generate_parser.add_argument(
61
- "config",
62
- type=str,
63
- help="Path to comfy-env.toml",
64
- )
65
- generate_parser.add_argument(
66
- "--force", "-f",
67
- action="store_true",
68
- help="Overwrite existing pixi.toml",
69
- )
70
-
71
- # install command
72
- install_parser = subparsers.add_parser(
73
- "install",
74
- help="Install dependencies from config",
75
- description="Install CUDA wheels and dependencies from comfy-env.toml",
76
- )
77
- install_parser.add_argument(
78
- "--config", "-c",
79
- type=str,
80
- help="Path to config file (default: auto-discover)",
81
- )
82
- install_parser.add_argument(
83
- "--dry-run",
84
- action="store_true",
85
- help="Show what would be installed without installing",
86
- )
87
- install_parser.add_argument(
88
- "--dir", "-d",
89
- type=str,
90
- help="Directory containing the config (default: current directory)",
91
- )
92
-
93
- # info command
94
- info_parser = subparsers.add_parser(
95
- "info",
96
- help="Show runtime environment information",
97
- description="Display detected Python, CUDA, PyTorch, and GPU information",
98
- )
99
- info_parser.add_argument(
100
- "--json",
101
- action="store_true",
102
- help="Output as JSON",
103
- )
104
-
105
- # doctor command
106
- doctor_parser = subparsers.add_parser(
107
- "doctor",
108
- help="Verify installation and diagnose issues",
109
- description="Check if packages are properly installed and importable",
110
- )
111
- doctor_parser.add_argument(
112
- "--package", "-p",
113
- type=str,
114
- help="Check specific package",
115
- )
116
- doctor_parser.add_argument(
117
- "--config", "-c",
118
- type=str,
119
- help="Path to config file",
120
- )
121
-
122
- # apt-install command
123
- apt_parser = subparsers.add_parser(
124
- "apt-install",
125
- help="Install system packages from [apt] section (Linux only)",
126
- description="Read [apt] packages from comfy-env.toml and install via apt-get",
127
- )
128
- apt_parser.add_argument(
129
- "--config", "-c",
130
- type=str,
131
- help="Path to comfy-env.toml (default: auto-discover)",
132
- )
133
- apt_parser.add_argument(
134
- "--dry-run",
135
- action="store_true",
136
- help="Show what would be installed without installing",
137
- )
13
+ parser = argparse.ArgumentParser(prog="comfy-env", description="Environment management for ComfyUI")
14
+ parser.add_argument("--version", action="version", version=f"comfy-env {__version__}")
15
+ sub = parser.add_subparsers(dest="command", help="Commands")
16
+
17
+ # init
18
+ p = sub.add_parser("init", help=f"Create {ROOT_CONFIG_FILE_NAME}")
19
+ p.add_argument("--force", "-f", action="store_true", help="Overwrite existing")
20
+ p.add_argument("--isolated", action="store_true", help=f"Create {CONFIG_FILE_NAME} instead (for isolated folders)")
21
+
22
+ # generate
23
+ p = sub.add_parser("generate", help="Generate pixi.toml from config")
24
+ p.add_argument("config", type=str, help="Path to config file")
25
+ p.add_argument("--force", "-f", action="store_true", help="Overwrite existing")
26
+
27
+ # install
28
+ p = sub.add_parser("install", help="Install dependencies")
29
+ p.add_argument("--config", "-c", type=str, help="Config path")
30
+ p.add_argument("--dry-run", action="store_true", help="Preview only")
31
+ p.add_argument("--dir", "-d", type=str, help="Node directory")
32
+
33
+ # info
34
+ p = sub.add_parser("info", help="Show runtime info")
35
+ p.add_argument("--json", action="store_true", help="JSON output")
36
+
37
+ # doctor
38
+ p = sub.add_parser("doctor", help="Verify installation")
39
+ p.add_argument("--package", "-p", type=str, help="Check specific package")
40
+ p.add_argument("--config", "-c", type=str, help="Config path")
41
+
42
+ # apt-install
43
+ p = sub.add_parser("apt-install", help="Install apt packages (Linux)")
44
+ p.add_argument("--config", "-c", type=str, help="Config path")
45
+ p.add_argument("--dry-run", action="store_true", help="Preview only")
138
46
 
139
47
  parsed = parser.parse_args(args)
140
-
141
- if parsed.command is None:
48
+ if not parsed.command:
142
49
  parser.print_help()
143
50
  return 0
144
51
 
52
+ commands = {
53
+ "init": cmd_init, "generate": cmd_generate, "install": cmd_install,
54
+ "info": cmd_info, "doctor": cmd_doctor, "apt-install": cmd_apt_install,
55
+ }
56
+
145
57
  try:
146
- if parsed.command == "init":
147
- return cmd_init(parsed)
148
- elif parsed.command == "generate":
149
- return cmd_generate(parsed)
150
- elif parsed.command == "install":
151
- return cmd_install(parsed)
152
- elif parsed.command == "info":
153
- return cmd_info(parsed)
154
- elif parsed.command == "doctor":
155
- return cmd_doctor(parsed)
156
- elif parsed.command == "apt-install":
157
- return cmd_apt_install(parsed)
158
- else:
159
- parser.print_help()
160
- return 1
58
+ return commands.get(parsed.command, lambda _: 1)(parsed)
161
59
  except KeyboardInterrupt:
162
60
  print("\nInterrupted")
163
61
  return 130
@@ -166,114 +64,96 @@ def main(args: Optional[List[str]] = None) -> int:
166
64
  return 1
167
65
 
168
66
 
169
- DEFAULT_CONFIG = """\
170
- # comfy-env.toml - Environment configuration for ComfyUI custom nodes
171
- # Documentation: https://github.com/PozzettiAndrea/comfy-env
67
+ ROOT_DEFAULT_CONFIG = """\
68
+ # comfy-env-root.toml - Main node config
69
+ # PyPI deps go in requirements.txt
70
+
71
+ [cuda]
72
+ packages = []
73
+
74
+ [apt]
75
+ packages = []
76
+
77
+ [dependencies]
78
+ # cgal = "*"
79
+
80
+ [env_vars]
81
+ # KMP_DUPLICATE_LIB_OK = "TRUE"
172
82
 
173
- [system]
174
- # System packages required (apt on Linux, brew on macOS)
175
- linux = []
83
+ [node_reqs]
84
+ # ComfyUI_essentials = "cubiq/ComfyUI_essentials"
85
+ """
176
86
 
177
- [environment]
87
+ ISOLATED_DEFAULT_CONFIG = """\
88
+ # comfy-env.toml - Isolated folder config
178
89
  python = "3.11"
179
- cuda_version = "auto"
180
- pytorch_version = "auto"
181
90
 
182
- [environment.cuda]
183
- # CUDA packages from https://pozzettiandrea.github.io/cuda-wheels/
184
- # Example: nvdiffrast = "0.4.0"
91
+ [dependencies]
92
+ # cgal = "*"
93
+
94
+ [pypi-dependencies]
95
+ # trimesh = { version = "*", extras = ["easy"] }
185
96
 
186
- [environment.packages]
187
- requirements = []
97
+ [env_vars]
98
+ # SOME_VAR = "value"
188
99
  """
189
100
 
190
101
 
191
102
  def cmd_init(args) -> int:
192
- """Handle init command."""
193
- config_path = Path.cwd() / "comfy-env.toml"
103
+ if getattr(args, 'isolated', False):
104
+ config_path = Path.cwd() / CONFIG_FILE_NAME
105
+ content = ISOLATED_DEFAULT_CONFIG
106
+ else:
107
+ config_path = Path.cwd() / ROOT_CONFIG_FILE_NAME
108
+ content = ROOT_DEFAULT_CONFIG
194
109
 
195
110
  if config_path.exists() and not args.force:
196
- print(f"Config file already exists: {config_path}", file=sys.stderr)
197
- print("Use --force to overwrite", file=sys.stderr)
111
+ print(f"Already exists: {config_path}\nUse --force to overwrite", file=sys.stderr)
198
112
  return 1
199
-
200
- config_path.write_text(DEFAULT_CONFIG)
113
+ config_path.write_text(content)
201
114
  print(f"Created {config_path}")
202
115
  return 0
203
116
 
204
117
 
205
118
  def cmd_generate(args) -> int:
206
- """Handle generate command - create pixi.toml from comfy-env.toml."""
207
- from .config.parser import load_config
208
- from .pixi import create_pixi_toml
119
+ from .config import load_config
120
+ from .packages.toml_generator import write_pixi_toml
209
121
 
210
122
  config_path = Path(args.config).resolve()
211
-
212
123
  if not config_path.exists():
213
- print(f"Config file not found: {config_path}", file=sys.stderr)
124
+ print(f"Not found: {config_path}", file=sys.stderr)
214
125
  return 1
215
126
 
216
- if config_path.name != "comfy-env.toml":
217
- print(f"Warning: Expected comfy-env.toml, got {config_path.name}", file=sys.stderr)
218
-
219
127
  node_dir = config_path.parent
220
128
  pixi_path = node_dir / "pixi.toml"
221
-
222
129
  if pixi_path.exists() and not args.force:
223
- print(f"pixi.toml already exists: {pixi_path}", file=sys.stderr)
224
- print("Use --force to overwrite", file=sys.stderr)
130
+ print(f"Already exists: {pixi_path}\nUse --force to overwrite", file=sys.stderr)
225
131
  return 1
226
132
 
227
- # Load the config
228
133
  config = load_config(config_path)
229
- if not config or not config.envs:
230
- print(f"No environments found in {config_path}", file=sys.stderr)
134
+ if not config:
135
+ print(f"Failed to load: {config_path}", file=sys.stderr)
231
136
  return 1
232
137
 
233
- # Use the first environment
234
- env_name = next(iter(config.envs.keys()))
235
- env_config = config.envs[env_name]
236
-
237
138
  print(f"Generating pixi.toml from {config_path}")
238
- print(f" Environment: {env_name}")
239
- print(f" Python: {env_config.python}")
240
-
241
- # Generate pixi.toml
242
- result_path = create_pixi_toml(env_config, node_dir)
243
-
244
- print(f"Created {result_path}")
245
- print()
246
- print("Next steps:")
247
- print(f" cd {node_dir}")
248
- print(" pixi install")
139
+ write_pixi_toml(config, node_dir)
140
+ print(f"Created {pixi_path}\nNext: cd {node_dir} && pixi install")
249
141
  return 0
250
142
 
251
143
 
252
144
  def cmd_install(args) -> int:
253
- """Handle install command."""
254
145
  from .install import install
255
-
256
146
  node_dir = Path(args.dir) if args.dir else Path.cwd()
257
-
258
147
  try:
259
- install(
260
- config=args.config,
261
- node_dir=node_dir,
262
- dry_run=args.dry_run,
263
- )
148
+ install(config=args.config, node_dir=node_dir, dry_run=args.dry_run)
264
149
  return 0
265
- except FileNotFoundError as e:
266
- print(f"Error: {e}", file=sys.stderr)
267
- return 1
268
150
  except Exception as e:
269
- print(f"Installation failed: {e}", file=sys.stderr)
151
+ print(f"Failed: {e}", file=sys.stderr)
270
152
  return 1
271
153
 
272
154
 
273
155
  def cmd_info(args) -> int:
274
- """Handle info command."""
275
- from .pixi import RuntimeEnv
276
-
156
+ from .detection import RuntimeEnv
277
157
  env = RuntimeEnv.detect()
278
158
 
279
159
  if args.json:
@@ -281,149 +161,80 @@ def cmd_info(args) -> int:
281
161
  print(json.dumps(env.as_dict(), indent=2))
282
162
  return 0
283
163
 
284
- print("Runtime Environment")
285
- print("=" * 40)
286
- print(f" OS: {env.os_name}")
287
- print(f" Platform: {env.platform_tag}")
288
- print(f" Python: {env.python_version}")
289
-
290
- if env.cuda_version:
291
- print(f" CUDA: {env.cuda_version}")
292
- else:
293
- print(" CUDA: Not detected")
294
-
295
- if env.torch_version:
296
- print(f" PyTorch: {env.torch_version}")
297
- else:
298
- print(" PyTorch: Not installed")
299
-
164
+ print("Runtime Environment\n" + "=" * 40)
165
+ print(f" OS: {env.os_name}")
166
+ print(f" Platform: {env.platform_tag}")
167
+ print(f" Python: {env.python_version}")
168
+ print(f" CUDA: {env.cuda_version or 'Not detected'}")
169
+ print(f" PyTorch: {env.torch_version or 'Not installed'}")
300
170
  if env.gpu_name:
301
- print(f" GPU: {env.gpu_name}")
302
- if env.gpu_compute:
303
- print(f" Compute: {env.gpu_compute}")
304
-
171
+ print(f" GPU: {env.gpu_name}")
172
+ if env.gpu_compute: print(f" Compute: {env.gpu_compute}")
305
173
  print()
306
174
  return 0
307
175
 
308
176
 
309
177
  def cmd_doctor(args) -> int:
310
- """Handle doctor command."""
311
178
  from .install import verify_installation
312
- from .config.parser import load_config, discover_config
313
-
314
- print("Running diagnostics...")
315
- print("=" * 40)
179
+ from .config import load_config, discover_config
316
180
 
317
- # Check environment
181
+ print("Diagnostics\n" + "=" * 40)
318
182
  print("\n1. Environment")
319
183
  cmd_info(argparse.Namespace(json=False))
320
184
 
321
- # Check packages
322
- print("2. Package Verification")
323
-
185
+ print("2. Packages")
324
186
  packages = []
325
187
  if args.package:
326
188
  packages = [args.package]
327
- elif args.config:
328
- config = load_config(Path(args.config))
329
- if config:
330
- # Get packages from pypi-dependencies
331
- pypi_deps = config.pixi_passthrough.get("pypi-dependencies", {})
332
- packages = list(pypi_deps.keys()) + config.cuda_packages
333
189
  else:
334
- config = discover_config(Path.cwd())
335
- if config:
336
- pypi_deps = config.pixi_passthrough.get("pypi-dependencies", {})
337
- packages = list(pypi_deps.keys()) + config.cuda_packages
190
+ cfg = load_config(Path(args.config)) if args.config else discover_config(Path.cwd())
191
+ if cfg:
192
+ packages = list(cfg.pixi_passthrough.get("pypi-dependencies", {}).keys()) + cfg.cuda_packages
338
193
 
339
194
  if packages:
340
- all_ok = verify_installation(packages)
341
- if all_ok:
342
- print("\nAll packages verified!")
343
- return 0
344
- else:
345
- print("\nSome packages failed verification.")
346
- return 1
347
- else:
348
- print(" No packages to verify (no config found)")
349
- return 0
195
+ return 0 if verify_installation(packages) else 1
196
+ print(" No packages to verify")
197
+ return 0
350
198
 
351
199
 
352
200
  def cmd_apt_install(args) -> int:
353
- """Handle apt-install command - install system packages from [apt] section."""
354
- import os
355
- import shutil
356
- import subprocess
357
- import platform
358
-
201
+ import os, shutil, subprocess, platform
359
202
  if platform.system() != "Linux":
360
- print("apt-install is only supported on Linux", file=sys.stderr)
203
+ print("apt-install: Linux only", file=sys.stderr)
361
204
  return 1
362
205
 
363
- # Find config
206
+ # Check root config first, then regular
364
207
  if args.config:
365
208
  config_path = Path(args.config).resolve()
366
209
  else:
367
- config_path = Path.cwd() / "comfy-env.toml"
210
+ root_path = Path.cwd() / ROOT_CONFIG_FILE_NAME
211
+ config_path = root_path if root_path.exists() else Path.cwd() / CONFIG_FILE_NAME
368
212
 
369
213
  if not config_path.exists():
370
- print(f"Config file not found: {config_path}", file=sys.stderr)
214
+ print(f"Not found: {config_path}", file=sys.stderr)
371
215
  return 1
372
216
 
373
- # Parse config to get apt packages
374
217
  from .config.parser import load_config
375
- config = load_config(config_path)
376
-
377
- if not config.apt_packages:
378
- print("No [apt] packages specified in config")
218
+ packages = load_config(config_path).apt_packages
219
+ if not packages:
220
+ print("No apt packages in config")
379
221
  return 0
380
222
 
381
- packages = config.apt_packages
382
- print(f"Found {len(packages)} apt package(s) to install:")
383
- for pkg in packages:
384
- print(f" - {pkg}")
385
-
386
- # Determine if we need sudo
387
- is_root = os.geteuid() == 0
388
- has_sudo = shutil.which("sudo") is not None
389
- use_sudo = not is_root and has_sudo
390
-
223
+ print(f"Packages: {', '.join(packages)}")
224
+ use_sudo = os.geteuid() != 0 and shutil.which("sudo")
391
225
  prefix = ["sudo"] if use_sudo else []
392
226
 
393
227
  if args.dry_run:
394
- print("\n[Dry run] Would run:")
395
- prefix_str = "sudo " if use_sudo else ""
396
- print(f" {prefix_str}apt-get update && {prefix_str}apt-get install -y {' '.join(packages)}")
228
+ print(f"Would run: {'sudo ' if use_sudo else ''}apt-get install -y {' '.join(packages)}")
397
229
  return 0
398
230
 
399
- if not is_root and not has_sudo:
400
- print("\nError: Need root privileges to install apt packages.", file=sys.stderr)
401
- print("Run manually with:", file=sys.stderr)
402
- print(f" sudo apt-get update && sudo apt-get install -y {' '.join(packages)}", file=sys.stderr)
231
+ if os.geteuid() != 0 and not shutil.which("sudo"):
232
+ print("Need root. Run: sudo apt-get install -y " + " ".join(packages), file=sys.stderr)
403
233
  return 1
404
234
 
405
- # Run apt-get update
406
- print("\nUpdating package lists...")
407
- result = subprocess.run(
408
- prefix + ["apt-get", "update"],
409
- capture_output=False,
410
- )
411
- if result.returncode != 0:
412
- print("Warning: apt-get update failed, continuing anyway...")
413
-
414
- # Run apt-get install
415
- print(f"\nInstalling: {' '.join(packages)}")
416
- result = subprocess.run(
417
- prefix + ["apt-get", "install", "-y"] + packages,
418
- capture_output=False,
419
- )
420
-
421
- if result.returncode == 0:
422
- print("\nSystem packages installed successfully!")
423
- return 0
424
- else:
425
- print("\nFailed to install some packages", file=sys.stderr)
426
- return result.returncode
235
+ subprocess.run(prefix + ["apt-get", "update"], capture_output=False)
236
+ result = subprocess.run(prefix + ["apt-get", "install", "-y"] + packages, capture_output=False)
237
+ return result.returncode
427
238
 
428
239
 
429
240
  if __name__ == "__main__":
@@ -1,17 +1,25 @@
1
- """Config parsing for comfy-env."""
1
+ """Config layer - Configuration parsing and types."""
2
2
 
3
- from .parser import (
3
+ from .types import (
4
4
  ComfyEnvConfig,
5
+ NodeDependency,
5
6
  NodeReq,
7
+ )
8
+ from .parser import (
9
+ ROOT_CONFIG_FILE_NAME,
10
+ CONFIG_FILE_NAME,
6
11
  load_config,
7
12
  discover_config,
8
- CONFIG_FILE_NAME,
13
+ parse_config,
9
14
  )
10
15
 
11
16
  __all__ = [
12
17
  "ComfyEnvConfig",
18
+ "NodeDependency",
13
19
  "NodeReq",
20
+ "ROOT_CONFIG_FILE_NAME",
21
+ "CONFIG_FILE_NAME",
14
22
  "load_config",
15
23
  "discover_config",
16
- "CONFIG_FILE_NAME",
24
+ "parse_config",
17
25
  ]