comfy-ui-api-workflow 0.0.1__tar.gz → 0.0.2__tar.gz

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 (203) hide show
  1. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/.gitignore +1 -0
  2. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/PKG-INFO +2 -2
  3. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/README.md +1 -1
  4. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/__about__.py +1 -0
  5. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/audio.py +60 -0
  6. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/dynamic.py +222 -0
  7. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/image/__init__.py +135 -0
  8. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/image/batch.py +553 -0
  9. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/image/detection.py +448 -1
  10. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/image/filters.py +69 -0
  11. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/image/geometry_estimation.py +174 -0
  12. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/image/mask.py +608 -0
  13. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/image/shader.py +419 -0
  14. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/image/transform.py +160 -0
  15. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/model/conditioning/bernini.py +122 -0
  16. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/model/conditioning/boogu.py +134 -0
  17. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/model/conditioning/hidream.py +660 -0
  18. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/model/conditioning/joyimage.py +68 -0
  19. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/model/conditioning/mage.py +155 -0
  20. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/model/conditioning/ming_image.py +80 -0
  21. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/model/conditioning/minimax.py +298 -0
  22. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/model/conditioning/qwen_image.py +247 -0
  23. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/infinite_talk.py +133 -0
  24. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/model/latent/batch.py +410 -0
  25. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/model/latent/seedvr.py +76 -0
  26. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/model/loaders.py +1611 -0
  27. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/patch/__init__.py +109 -0
  28. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/partner/audio/fish_audio.py +80 -0
  29. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/partner/video/luma.py +67 -0
  30. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/partner/video/runway.py +131 -0
  31. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/text.py +1064 -0
  32. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/three_d/__init__.py +1076 -0
  33. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/three_d/mesh.py +788 -0
  34. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/three_d/splat.py +208 -0
  35. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/utilities/__init__.py +77 -0
  36. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/utilities/logic.py +198 -0
  37. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/utilities/looping.py +440 -0
  38. comfy_ui_api_workflow-0.0.2/comfy_ui_api_workflow/_impl/nodes/video/__init__.py +1076 -0
  39. comfy_ui_api_workflow-0.0.1/comfy_ui_api_workflow/__about__.py +0 -1
  40. comfy_ui_api_workflow-0.0.1/comfy_ui_api_workflow/_impl/nodes/image/batch.py +0 -236
  41. comfy_ui_api_workflow-0.0.1/comfy_ui_api_workflow/_impl/nodes/image/mask.py +0 -291
  42. comfy_ui_api_workflow-0.0.1/comfy_ui_api_workflow/_impl/nodes/model/conditioning/hidream.py +0 -31
  43. comfy_ui_api_workflow-0.0.1/comfy_ui_api_workflow/_impl/nodes/model/conditioning/minimax.py +0 -110
  44. comfy_ui_api_workflow-0.0.1/comfy_ui_api_workflow/_impl/nodes/model/conditioning/qwen_image.py +0 -101
  45. comfy_ui_api_workflow-0.0.1/comfy_ui_api_workflow/_impl/nodes/model/latent/batch.py +0 -93
  46. comfy_ui_api_workflow-0.0.1/comfy_ui_api_workflow/_impl/nodes/model/latent/seedvr.py +0 -16
  47. comfy_ui_api_workflow-0.0.1/comfy_ui_api_workflow/_impl/nodes/model/loaders.py +0 -820
  48. comfy_ui_api_workflow-0.0.1/comfy_ui_api_workflow/_impl/nodes/text.py +0 -506
  49. comfy_ui_api_workflow-0.0.1/comfy_ui_api_workflow/_impl/nodes/three_d/__init__.py +0 -563
  50. comfy_ui_api_workflow-0.0.1/comfy_ui_api_workflow/_impl/nodes/three_d/mesh.py +0 -183
  51. comfy_ui_api_workflow-0.0.1/comfy_ui_api_workflow/_impl/nodes/utilities/logic.py +0 -44
  52. comfy_ui_api_workflow-0.0.1/comfy_ui_api_workflow/_impl/nodes/video/__init__.py +0 -440
  53. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/LICENSE +0 -0
  54. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/__init__.py +0 -0
  55. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/__init__.py +0 -0
  56. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/data_structure.py +0 -0
  57. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/enums.py +0 -0
  58. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/errors/__init__.py +0 -0
  59. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/errors/data_structure.py +0 -0
  60. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/errors/node.py +0 -0
  61. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/errors/output.py +0 -0
  62. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/errors/pipeline.py +0 -0
  63. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/errors/workflow.py +0 -0
  64. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/exceptions.py +0 -0
  65. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/lazy.py +0 -0
  66. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/__init__.py +0 -0
  67. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/advanced/__init__.py +0 -0
  68. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/advanced/debug.py +0 -0
  69. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/advanced/guidance.py +0 -0
  70. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/advanced/hooks/__init__.py +0 -0
  71. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/advanced/hooks/clip.py +0 -0
  72. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/advanced/hooks/combine.py +0 -0
  73. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/advanced/hooks/cond_pair.py +0 -0
  74. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/advanced/hooks/cond_single.py +0 -0
  75. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/advanced/hooks/create.py +0 -0
  76. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/advanced/hooks/scheduling.py +0 -0
  77. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/advanced/multigpu.py +0 -0
  78. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/base.py +0 -0
  79. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/experimental/__init__.py +0 -0
  80. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/experimental/attention_experiments.py +0 -0
  81. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/experimental/stable_cascade.py +0 -0
  82. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/image/adjustments.py +0 -0
  83. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/image/background_removal.py +0 -0
  84. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/image/color.py +0 -0
  85. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/image/compositing.py +0 -0
  86. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/image/post_processors.py +0 -0
  87. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/image/pre_processors.py +0 -0
  88. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/image/upscaling.py +0 -0
  89. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/image/video.py +0 -0
  90. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/__init__.py +0 -0
  91. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/__init__.py +0 -0
  92. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/ace.py +0 -0
  93. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/autoregressive.py +0 -0
  94. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/controlnet.py +0 -0
  95. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/cosmos.py +0 -0
  96. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/flux.py +0 -0
  97. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/gligen.py +0 -0
  98. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/hunyuan_3d.py +0 -0
  99. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/hunyuan_image.py +0 -0
  100. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/hunyuan_video.py +0 -0
  101. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/instructpix2pix.py +0 -0
  102. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/kandinsky.py +0 -0
  103. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/lotus.py +0 -0
  104. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/ltxv.py +0 -0
  105. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/lumina.py +0 -0
  106. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/minimax_music.py +0 -0
  107. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/photomaker.py +0 -0
  108. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/pixart.py +0 -0
  109. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/stable_audio.py +0 -0
  110. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/stable_cascade.py +0 -0
  111. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/stable_diffusion.py +0 -0
  112. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/stable_diffusion_upscaler.py +0 -0
  113. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/stable_video.py +0 -0
  114. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/stable_video_3d.py +0 -0
  115. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/stable_zero123.py +0 -0
  116. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/transform.py +0 -0
  117. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/trellis.py +0 -0
  118. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/triposplat.py +0 -0
  119. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/void.py +0 -0
  120. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/__init__.py +0 -0
  121. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/animate.py +0 -0
  122. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/camera.py +0 -0
  123. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/dancer.py +0 -0
  124. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/fun_control.py +0 -0
  125. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/fun_inpaint.py +0 -0
  126. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/humo.py +0 -0
  127. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/move.py +0 -0
  128. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/phantom_subject.py +0 -0
  129. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/scail.py +0 -0
  130. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/sound.py +0 -0
  131. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/wan/vace.py +0 -0
  132. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/yue2.py +0 -0
  133. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/conditioning/z_image.py +0 -0
  134. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/__init__.py +0 -0
  135. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/ace.py +0 -0
  136. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/advanced/__init__.py +0 -0
  137. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/advanced/operations.py +0 -0
  138. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/autoregressive.py +0 -0
  139. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/chroma_radiance.py +0 -0
  140. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/cosmos.py +0 -0
  141. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/flux.py +0 -0
  142. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/hidream.py +0 -0
  143. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/hunyuan_3d.py +0 -0
  144. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/hunyuan_image.py +0 -0
  145. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/hunyuan_video.py +0 -0
  146. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/ltxv.py +0 -0
  147. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/minimax.py +0 -0
  148. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/minimax_music.py +0 -0
  149. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/mochi.py +0 -0
  150. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/qwen.py +0 -0
  151. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/stable_cascade.py +0 -0
  152. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/stable_diffusion.py +0 -0
  153. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/transform.py +0 -0
  154. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/trellis.py +0 -0
  155. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/triposplat.py +0 -0
  156. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/void.py +0 -0
  157. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/latent/yue2.py +0 -0
  158. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/merging/__init__.py +0 -0
  159. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/merging/model_specific.py +0 -0
  160. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/patch/anima.py +0 -0
  161. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/patch/chroma_radiance.py +0 -0
  162. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/patch/flux.py +0 -0
  163. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/patch/hidream.py +0 -0
  164. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/patch/ltxv.py +0 -0
  165. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/patch/minimax.py +0 -0
  166. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/patch/qwen.py +0 -0
  167. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/patch/sensenova.py +0 -0
  168. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/patch/stable_cascade.py +0 -0
  169. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/patch/stable_diffusion.py +0 -0
  170. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/patch/supir.py +0 -0
  171. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/patch/unet.py +0 -0
  172. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/patch/wan.py +0 -0
  173. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/sampling/__init__.py +0 -0
  174. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/sampling/custom.py +0 -0
  175. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/sampling/guiders.py +0 -0
  176. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/sampling/noise.py +0 -0
  177. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/sampling/samplers.py +0 -0
  178. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/sampling/schedulers.py +0 -0
  179. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/sampling/sigmas.py +0 -0
  180. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/model/training.py +0 -0
  181. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/partner/__init__.py +0 -0
  182. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/partner/audio/__init__.py +0 -0
  183. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/partner/audio/elevenlabs.py +0 -0
  184. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/partner/image/__init__.py +0 -0
  185. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/partner/image/bytedance.py +0 -0
  186. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/partner/image/krea.py +0 -0
  187. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/partner/image/luma.py +0 -0
  188. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/partner/image/recraft.py +0 -0
  189. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/partner/text/__init__.py +0 -0
  190. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/partner/text/gemini.py +0 -0
  191. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/partner/text/openai.py +0 -0
  192. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/partner/video/__init__.py +0 -0
  193. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/partner/video/bytedance.py +0 -0
  194. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/partner/video/pixverse.py +0 -0
  195. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/three_d/texturing.py +0 -0
  196. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/utilities/primitive.py +0 -0
  197. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/validation.py +0 -0
  198. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/video/batch.py +0 -0
  199. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/video/preprocessors.py +0 -0
  200. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/nodes/video/transform.py +0 -0
  201. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/pipeline.py +0 -0
  202. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/comfy_ui_api_workflow/_impl/workflow.py +0 -0
  203. {comfy_ui_api_workflow-0.0.1 → comfy_ui_api_workflow-0.0.2}/pyproject.toml +0 -0
@@ -1,4 +1,5 @@
1
1
  # Custom
2
+ dynamic-nodes.tdd.md
2
3
  .venv
3
4
  dist
4
5
  video_wan2_2_14B_i2v.json
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: comfy-ui-api-workflow
3
- Version: 0.0.1
3
+ Version: 0.0.2
4
4
  Summary: Run ComfyUI workflows through the ComfyUI API.
5
5
  Project-URL: Documentation, https://github.com/fabioantonioastore/comfy-ui-api-workflow#readme
6
6
  Project-URL: Issues, https://github.com/fabioantonioastore/comfy-ui-api-workflow/issues
@@ -27,7 +27,7 @@ Description-Content-Type: text/markdown
27
27
  Build [ComfyUI](https://github.com/comfyanonymous/ComfyUI) workflows in Python
28
28
  and export them in the API format that ComfyUI's `POST /prompt` endpoint runs.
29
29
 
30
- - **618 ComfyUI nodes as Python classes**, from `KSampler` to Wan, LTXV, Flux,
30
+ - **665 ComfyUI nodes as Python classes**, from `KSampler` to Wan, LTXV, Flux,
31
31
  3D and partner API nodes.
32
32
  - **Checked as you build**: input types, `min`/`max` ranges, combo choices,
33
33
  output names, socket types (no `LATENT` into a `CLIP` input) and cycles. A bad
@@ -3,7 +3,7 @@
3
3
  Build [ComfyUI](https://github.com/comfyanonymous/ComfyUI) workflows in Python
4
4
  and export them in the API format that ComfyUI's `POST /prompt` endpoint runs.
5
5
 
6
- - **618 ComfyUI nodes as Python classes**, from `KSampler` to Wan, LTXV, Flux,
6
+ - **665 ComfyUI nodes as Python classes**, from `KSampler` to Wan, LTXV, Flux,
7
7
  3D and partner API nodes.
8
8
  - **Checked as you build**: input types, `min`/`max` ranges, combo choices,
9
9
  output names, socket types (no `LATENT` into a `CLIP` input) and cycles. A bad
@@ -0,0 +1 @@
1
+ version = "0.0.2"
@@ -2,6 +2,7 @@ from typing import Any, Literal, get_args
2
2
 
3
3
  from .base import BaseNode
4
4
  from .validation import validate_choice, validate_not_empty, validate_range
5
+ from .dynamic import Choice, Combo, DynamicInputs, validate_dynamic
5
6
 
6
7
 
7
8
  class LoadAudio(BaseNode):
@@ -258,3 +259,62 @@ class AudioEqualizer3Band(BaseNode):
258
259
  validate_range("mid_q", self.mid_q, 0.1, 10.0)
259
260
  validate_range("high_gain_dB", self.high_gain_dB, -24.0, 24.0)
260
261
  validate_range("high_freq", self.high_freq, 1000, 15_000)
262
+
263
+
264
+ SaveAudioAdvanced_Formats = Literal["flac", "mp3", "opus"]
265
+
266
+
267
+ SaveAudioAdvanced_Format_Qualitys = Literal["V0", "128k", "320k", "64k", "96k", "192k"]
268
+
269
+
270
+ class SaveAudioAdvanced(DynamicInputs, BaseNode):
271
+ __slots__ = (
272
+ "audio",
273
+ "filename_prefix",
274
+ "format",
275
+ "format_quality",
276
+ )
277
+ CATEGORY = "audio"
278
+ OUTPUTS = {"audio": 0}
279
+ RETURN_TYPES = ("AUDIO",)
280
+ INPUT_NAMES = {"format_quality": "format.quality"}
281
+ INPUT_SOCKET_TYPES = {
282
+ "audio": "AUDIO",
283
+ "filename_prefix": "STRING",
284
+ "format": "COMFY_DYNAMICCOMBO_V3",
285
+ "format_quality": "COMBO",
286
+ }
287
+ DYNAMIC_INPUTS = {
288
+ "format": Combo(
289
+ {
290
+ "flac": {},
291
+ "mp3": {"format_quality": Choice(("V0", "128k", "320k"), default="V0")},
292
+ "opus": {
293
+ "format_quality": Choice(
294
+ ("64k", "96k", "128k", "192k", "320k"), default="128k"
295
+ )
296
+ },
297
+ }
298
+ )
299
+ }
300
+
301
+ def __init__(
302
+ self,
303
+ node_id: str,
304
+ audio: tuple[str, int],
305
+ filename_prefix: str | tuple[str, int] = "audio/ComfyUI",
306
+ format: SaveAudioAdvanced_Formats = "flac",
307
+ format_quality: (
308
+ SaveAudioAdvanced_Format_Qualitys | tuple[str, int] | None
309
+ ) = None,
310
+ ) -> None:
311
+ super().__init__(node_id=node_id)
312
+ self.audio = audio
313
+ self.filename_prefix = filename_prefix
314
+ self.format = format
315
+ if format_quality is not None:
316
+ self.format_quality = format_quality
317
+ self.__validate()
318
+
319
+ def __validate(self) -> None:
320
+ validate_dynamic(self)
@@ -0,0 +1,222 @@
1
+ from collections.abc import Callable, Iterator
2
+ from typing import Any, ClassVar
3
+
4
+ from ..errors.node import InvalidNodeParameterValue
5
+ from .base import _api_value
6
+ from .validation import (
7
+ validate_bool,
8
+ validate_choice,
9
+ validate_not_empty,
10
+ validate_range,
11
+ )
12
+
13
+ _NO_DEFAULT = object()
14
+
15
+
16
+ # An input that only exists inside a branch of a dynamic combo or a row of a
17
+ # dynamic group. One with a default is sent with it when not given, as the
18
+ # ComfyUI frontend does; ComfyUI rejects a prompt missing a required input.
19
+ class Value:
20
+ __slots__ = ("default", "required", "check")
21
+
22
+ def __init__(
23
+ self,
24
+ default: Any = _NO_DEFAULT,
25
+ required: bool = True,
26
+ check: Callable[[str, Any], None] | None = None,
27
+ ) -> None:
28
+ self.default = default
29
+ self.required = required
30
+ self.check = check
31
+
32
+ def validate(self, name: str, value: Any) -> None:
33
+ if self.check is not None:
34
+ self.check(name, value)
35
+
36
+
37
+ def Number(
38
+ default: Any = _NO_DEFAULT,
39
+ low: int | float | None = None,
40
+ high: int | float | None = None,
41
+ required: bool = True,
42
+ ) -> Value:
43
+ def check(name: str, value: Any) -> None:
44
+ validate_range(name, value, low, high)
45
+
46
+ return Value(default, required, check)
47
+
48
+
49
+ def Choice(
50
+ options: tuple[Any, ...], default: Any = _NO_DEFAULT, required: bool = True
51
+ ) -> Value:
52
+ choices = frozenset(options)
53
+
54
+ def check(name: str, value: Any) -> None:
55
+ validate_choice(name, value, choices)
56
+
57
+ return Value(default, required, check)
58
+
59
+
60
+ def ServerChoice(required: bool = True) -> Value:
61
+ return Value(required=required, check=validate_not_empty)
62
+
63
+
64
+ def Flag(default: Any = _NO_DEFAULT, required: bool = True) -> Value:
65
+ return Value(default, required, validate_bool)
66
+
67
+
68
+ def Text(default: Any = _NO_DEFAULT, required: bool = True) -> Value:
69
+ return Value(default, required)
70
+
71
+
72
+ def Link(required: bool = True) -> Value:
73
+ return Value(required=required)
74
+
75
+
76
+ def _one_of(keys: list[str]) -> str:
77
+ return repr(keys[0]) if len(keys) == 1 else f"one of {keys}"
78
+
79
+
80
+ # A dynamic combo: each option opens its own inputs, sent as "<combo>.<input>"
81
+ # and set here as <combo>_<input>. An attribute can be in several branches, each
82
+ # with its own default and checks; the first option is the default one.
83
+ class Combo:
84
+ __slots__ = ("branches",)
85
+
86
+ def __init__(self, branches: dict[str, dict[str, "Value | Combo"]]) -> None:
87
+ self.branches = branches
88
+
89
+ @property
90
+ def default(self) -> str:
91
+ return next(iter(self.branches))
92
+
93
+ def attributes(self, branch: str | None = None) -> set[str]:
94
+ keys = self.branches if branch is None else (branch,)
95
+ found: set[str] = set()
96
+ for key in keys:
97
+ for name, spec in self.branches[key].items():
98
+ found.add(name)
99
+ if isinstance(spec, Combo):
100
+ found |= spec.attributes()
101
+ return found
102
+
103
+ def validate(self, node: Any, name: str, value: Any) -> None:
104
+ validate_choice(name, value, frozenset(self.branches))
105
+ for attribute in sorted(self.attributes() - self.attributes(value)):
106
+ if getattr(node, attribute, None) is not None:
107
+ keys = [
108
+ key for key in self.branches if attribute in self.attributes(key)
109
+ ]
110
+ raise InvalidNodeParameterValue(
111
+ f"{attribute} only applies when {name} is {_one_of(keys)}"
112
+ )
113
+ for attribute, spec in self.branches[value].items():
114
+ given = getattr(node, attribute, None)
115
+ if isinstance(spec, Combo):
116
+ chosen = spec.default if given is None else given
117
+ spec.validate(node, attribute, chosen)
118
+ elif given is not None:
119
+ spec.validate(attribute, given)
120
+ elif spec.required and spec.default is _NO_DEFAULT:
121
+ raise InvalidNodeParameterValue(
122
+ f"{attribute} is required when {name} is {value!r}"
123
+ )
124
+
125
+ def defaults(self, node: Any, value: Any) -> Iterator[tuple[str, Any]]:
126
+ for attribute, spec in self.branches[value].items():
127
+ given = getattr(node, attribute, None)
128
+ if isinstance(spec, Combo):
129
+ if given is None:
130
+ given = spec.default
131
+ yield attribute, given
132
+ yield from spec.defaults(node, given)
133
+ elif given is None and spec.default is not _NO_DEFAULT:
134
+ yield attribute, spec.default
135
+
136
+
137
+ # A dynamic group: rows of the same fields, sent as "<group>.<row>.<field>" and
138
+ # set here as <group>_<row>_<field>. A row is used when any of its fields is set;
139
+ # the rows a node needs at least have their required fields as constructor
140
+ # parameters, so they are always there.
141
+ class Group:
142
+ __slots__ = ("rows", "fields")
143
+
144
+ def __init__(self, rows: int, fields: dict[str, Value]) -> None:
145
+ self.rows = rows
146
+ self.fields = fields
147
+
148
+ def attribute(self, name: str, row: int, field: str) -> str:
149
+ return f"{name}_{row}_{field}"
150
+
151
+ def used_rows(self, node: Any, name: str) -> list[int]:
152
+ return [
153
+ row
154
+ for row in range(self.rows)
155
+ if any(
156
+ getattr(node, self.attribute(name, row, field), None) is not None
157
+ for field in self.fields
158
+ )
159
+ ]
160
+
161
+ def validate(self, node: Any, name: str) -> None:
162
+ for row in self.used_rows(node, name):
163
+ for field, spec in self.fields.items():
164
+ attribute = self.attribute(name, row, field)
165
+ given = getattr(node, attribute, None)
166
+ if given is not None:
167
+ spec.validate(attribute, given)
168
+ elif spec.required and spec.default is _NO_DEFAULT:
169
+ raise InvalidNodeParameterValue(
170
+ f"{attribute} is required in row {row} of {name}"
171
+ )
172
+
173
+ def defaults(self, node: Any, name: str) -> Iterator[tuple[str, Any]]:
174
+ for row in self.used_rows(node, name):
175
+ for field, spec in self.fields.items():
176
+ attribute = self.attribute(name, row, field)
177
+ if (
178
+ getattr(node, attribute, None) is None
179
+ and spec.default is not _NO_DEFAULT
180
+ ):
181
+ yield attribute, spec.default
182
+
183
+
184
+ def validate_dynamic(node: Any) -> None:
185
+ for name, spec in type(node).DYNAMIC_INPUTS.items():
186
+ if isinstance(spec, Group):
187
+ spec.validate(node, name)
188
+ else:
189
+ spec.validate(node, name, getattr(node, name))
190
+
191
+
192
+ # Mixed in before BaseNode by the nodes with dynamic combos or groups: the
193
+ # ComfyUI format also carries the defaults of the chosen branches and rows,
194
+ # which are not stored, so changing a branch never leaves stale inputs behind.
195
+ class DynamicInputs:
196
+ __slots__ = ()
197
+ DYNAMIC_INPUTS: ClassVar[dict[str, Combo | Group]] = {}
198
+
199
+ def get_comfy_ui_workflow_format(self) -> dict[str, Any]:
200
+ node_type = type(self)
201
+ values = self.inputs() # type: ignore
202
+ for name, spec in node_type.DYNAMIC_INPUTS.items():
203
+ if isinstance(spec, Group):
204
+ values.update(spec.defaults(self, name))
205
+ else:
206
+ values.update(spec.defaults(self, getattr(self, name)))
207
+ order = [
208
+ name
209
+ for cls in reversed(node_type.__mro__)
210
+ for name in cls.__dict__.get("__slots__", ())
211
+ ]
212
+ inputs = {
213
+ node_type.INPUT_NAMES.get(name, name): _api_value(values[name]) # type: ignore
214
+ for name in order
215
+ if name in values
216
+ }
217
+ return {
218
+ self.node_id: { # type: ignore
219
+ "class_type": node_type.CLASS_TYPE, # type: ignore
220
+ "inputs": inputs,
221
+ }
222
+ }
@@ -8,6 +8,7 @@ from ..validation import (
8
8
  validate_range,
9
9
  )
10
10
  from ...lazy import submodules_of
11
+ from ..dynamic import Choice, Combo, DynamicInputs, Number, validate_dynamic
11
12
 
12
13
 
13
14
  class SaveImage(BaseNode):
@@ -598,4 +599,138 @@ class SaveImageWebsocket(BaseNode):
598
599
  self.images = images
599
600
 
600
601
 
602
+ SaveImageAdvanced_Formats = Literal["png", "exr", "avif"]
603
+
604
+
605
+ SaveImageAdvanced_Format_Bit_Depths = Literal[
606
+ "8-bit",
607
+ "16-bit",
608
+ "32-bit float",
609
+ "16-bit float",
610
+ "auto",
611
+ "8-bit YUV420",
612
+ "10-bit YUV420",
613
+ ]
614
+
615
+
616
+ SaveImageAdvanced_Format_Input_Color_Spaces = Literal["sRGB", "HDR", "linear", "HDR PQ"]
617
+
618
+
619
+ SaveImageAdvanced_Format_Save_Modes = Literal["still images", "animated"]
620
+
621
+
622
+ class SaveImageAdvanced(DynamicInputs, BaseNode):
623
+ __slots__ = (
624
+ "images",
625
+ "filename_prefix",
626
+ "format",
627
+ "format_bit_depth",
628
+ "format_input_color_space",
629
+ "format_crf",
630
+ "format_save_mode",
631
+ "format_save_mode_fps",
632
+ "format_save_mode_loop_count",
633
+ )
634
+ CATEGORY = "image"
635
+ OUTPUTS = {"images": 0}
636
+ RETURN_TYPES = ("IMAGE",)
637
+ INPUT_NAMES = {
638
+ "format_bit_depth": "format.bit_depth",
639
+ "format_input_color_space": "format.input_color_space",
640
+ "format_crf": "format.crf",
641
+ "format_save_mode": "format.save_mode",
642
+ "format_save_mode_fps": "format.save_mode.fps",
643
+ "format_save_mode_loop_count": "format.save_mode.loop_count",
644
+ }
645
+ INPUT_SOCKET_TYPES = {
646
+ "images": "IMAGE",
647
+ "filename_prefix": "STRING",
648
+ "format": "COMFY_DYNAMICCOMBO_V3",
649
+ "format_bit_depth": "COMBO",
650
+ "format_input_color_space": "COMBO",
651
+ "format_crf": "INT",
652
+ "format_save_mode": "COMFY_DYNAMICCOMBO_V3",
653
+ "format_save_mode_fps": "FLOAT",
654
+ "format_save_mode_loop_count": "INT",
655
+ }
656
+ DYNAMIC_INPUTS = {
657
+ "format": Combo(
658
+ {
659
+ "png": {
660
+ "format_bit_depth": Choice(("8-bit", "16-bit"), default="8-bit"),
661
+ "format_input_color_space": Choice(("sRGB",), default="sRGB"),
662
+ },
663
+ "exr": {
664
+ "format_bit_depth": Choice(
665
+ ("32-bit float", "16-bit float"), default="16-bit float"
666
+ ),
667
+ "format_input_color_space": Choice(
668
+ ("sRGB", "HDR", "linear"), default="sRGB"
669
+ ),
670
+ },
671
+ "avif": {
672
+ "format_bit_depth": Choice(
673
+ ("auto", "8-bit YUV420", "10-bit YUV420"), default="auto"
674
+ ),
675
+ "format_input_color_space": Choice(
676
+ ("sRGB", "HDR", "HDR PQ"), default="sRGB"
677
+ ),
678
+ "format_crf": Number(default=18, low=1, high=63),
679
+ "format_save_mode": Combo(
680
+ {
681
+ "still images": {},
682
+ "animated": {
683
+ "format_save_mode_fps": Number(
684
+ default=6.0, low=0.01, high=1000.0
685
+ ),
686
+ "format_save_mode_loop_count": Number(
687
+ default=0, low=0, high=1000
688
+ ),
689
+ },
690
+ }
691
+ ),
692
+ },
693
+ }
694
+ )
695
+ }
696
+
697
+ def __init__(
698
+ self,
699
+ node_id: str,
700
+ images: tuple[str, int],
701
+ filename_prefix: str | tuple[str, int] = "ComfyUI",
702
+ format: SaveImageAdvanced_Formats = "png",
703
+ format_bit_depth: (
704
+ SaveImageAdvanced_Format_Bit_Depths | tuple[str, int] | None
705
+ ) = None,
706
+ format_input_color_space: (
707
+ SaveImageAdvanced_Format_Input_Color_Spaces | tuple[str, int] | None
708
+ ) = None,
709
+ format_crf: int | tuple[str, int] | None = None,
710
+ format_save_mode: SaveImageAdvanced_Format_Save_Modes | None = None,
711
+ format_save_mode_fps: float | tuple[str, int] | None = None,
712
+ format_save_mode_loop_count: int | tuple[str, int] | None = None,
713
+ ) -> None:
714
+ super().__init__(node_id=node_id)
715
+ self.images = images
716
+ self.filename_prefix = filename_prefix
717
+ self.format = format
718
+ if format_bit_depth is not None:
719
+ self.format_bit_depth = format_bit_depth
720
+ if format_input_color_space is not None:
721
+ self.format_input_color_space = format_input_color_space
722
+ if format_crf is not None:
723
+ self.format_crf = format_crf
724
+ if format_save_mode is not None:
725
+ self.format_save_mode = format_save_mode
726
+ if format_save_mode_fps is not None:
727
+ self.format_save_mode_fps = format_save_mode_fps
728
+ if format_save_mode_loop_count is not None:
729
+ self.format_save_mode_loop_count = format_save_mode_loop_count
730
+ self.__validate()
731
+
732
+ def __validate(self) -> None:
733
+ validate_dynamic(self)
734
+
735
+
601
736
  __getattr__ = submodules_of(__name__)