RioShiina commited on
Commit
3119b7f
·
verified ·
1 Parent(s): 8ffc2e2

Upgrade to Gradio 6

Browse files
.gitignore ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+
5
+ # Environments & IDE
6
+ .env
7
+ .venv/
8
+ env/
9
+ venv/
10
+ .idea/
11
+ .vscode/
12
+
13
+ # Temporary files
14
+ *.tmp
15
+ *.temp
README.md CHANGED
@@ -4,7 +4,6 @@ emoji: 🖼
4
  colorFrom: purple
5
  colorTo: red
6
  sdk: gradio
7
- sdk_version: "5.50.0"
8
  app_file: app.py
9
  python_version: 3.12
10
  short_description: Multi-task image generator with dynamic, chainable workflows
 
4
  colorFrom: purple
5
  colorTo: red
6
  sdk: gradio
 
7
  app_file: app.py
8
  python_version: 3.12
9
  short_description: Multi-task image generator with dynamic, chainable workflows
app.py CHANGED
@@ -49,7 +49,7 @@ def dummy_gpu_for_startup():
49
  return "Startup check passed."
50
 
51
 
52
- def main():
53
  from comfy_integration import setup as setup_comfyui
54
  from utils.app_utils import load_ipadapter_presets
55
 
@@ -80,7 +80,6 @@ def main():
80
  load_ipadapter_presets()
81
  print("--- ✅ IPAdapter setup complete. ---")
82
 
83
-
84
  print("--- Environment configured. Proceeding with module imports. ---")
85
  from ui.layout import build_ui
86
  from ui.events import attach_event_handlers
@@ -90,10 +89,10 @@ def main():
90
  print(f"✅ Working directory is stable: {os.getcwd()}")
91
 
92
  demo = build_ui(attach_event_handlers)
 
93
 
94
- print("--- Launching Gradio Interface ---")
95
- demo.queue().launch(mcp_server=True)
96
-
97
 
98
  if __name__ == "__main__":
99
- main()
 
 
49
  return "Startup check passed."
50
 
51
 
52
+ def create_app():
53
  from comfy_integration import setup as setup_comfyui
54
  from utils.app_utils import load_ipadapter_presets
55
 
 
80
  load_ipadapter_presets()
81
  print("--- ✅ IPAdapter setup complete. ---")
82
 
 
83
  print("--- Environment configured. Proceeding with module imports. ---")
84
  from ui.layout import build_ui
85
  from ui.events import attach_event_handlers
 
89
  print(f"✅ Working directory is stable: {os.getcwd()}")
90
 
91
  demo = build_ui(attach_event_handlers)
92
+ return demo
93
 
94
+ demo = create_app()
 
 
95
 
96
  if __name__ == "__main__":
97
+ print("--- Launching Gradio Interface ---")
98
+ demo.queue().launch(mcp_server=True, footer_links=["api", "gradio", "settings"])
core/pipelines/pipeline_input_processor.py CHANGED
@@ -5,7 +5,10 @@ import gradio as gr
5
  from PIL import Image, ImageChops
6
  from typing import Dict, Any, List
7
 
8
- from core.settings import INPUT_DIR, MULTIPLIERS_MAP, LORA_DIR, EMBEDDING_DIR, VAE_DIR
 
 
 
9
  from utils.app_utils import (
10
  sanitize_filename,
11
  get_lora_path,
@@ -21,6 +24,10 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
21
  task_type = ui_inputs['task_type']
22
  temp_files_to_clean = []
23
 
 
 
 
 
24
  multiplier = MULTIPLIERS_MAP.get(workflow_model_type, 8)
25
  img_w, img_h = 0, 0
26
  if task_type == 'txt2img':
@@ -53,7 +60,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
53
 
54
  lora_data = ui_inputs.get('lora_data', [])
55
  active_loras_for_gpu, active_loras_for_meta = [], []
56
- if lora_data:
57
  sources, ids, scales, files = lora_data[0::4], lora_data[1::4], lora_data[2::4], lora_data[3::4]
58
  for i, (source, lora_id, scale, _) in enumerate(zip(sources, ids, scales, files)):
59
  if scale > 0 and lora_id and lora_id.strip():
@@ -145,7 +152,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
145
 
146
  embedding_data = ui_inputs.get('embedding_data', [])
147
  embedding_filenames = []
148
- if embedding_data:
149
  emb_sources, emb_ids, emb_files = embedding_data[0::3], embedding_data[1::3], embedding_data[2::3]
150
  for i, (source, emb_id, _) in enumerate(zip(emb_sources, emb_ids, emb_files)):
151
  if emb_id and emb_id.strip():
@@ -165,7 +172,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
165
 
166
  controlnet_data = ui_inputs.get('controlnet_data', [])
167
  active_controlnets = []
168
- if controlnet_data:
169
  (cn_images, _, _, cn_strengths, cn_filepaths) = [controlnet_data[i::5] for i in range(5)]
170
  for i in range(len(cn_images)):
171
  if cn_images[i] and cn_strengths[i] > 0 and cn_filepaths[i] and cn_filepaths[i] != "None":
@@ -181,7 +188,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
181
 
182
  anima_controlnet_lllite_data = ui_inputs.get('anima_controlnet_lllite_data', [])
183
  active_anima_controlnets = []
184
- if anima_controlnet_lllite_data:
185
  (cn_images, _, _, cn_strengths, cn_filepaths, cn_starts, cn_ends) = [anima_controlnet_lllite_data[i::7] for i in range(7)]
186
  for i in range(len(cn_images)):
187
  if cn_images[i] and cn_strengths[i] > 0 and cn_filepaths[i] and cn_filepaths[i] != "None":
@@ -197,7 +204,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
197
 
198
  diffsynth_controlnet_data = ui_inputs.get('diffsynth_controlnet_data', [])
199
  active_diffsynth_controlnets = []
200
- if diffsynth_controlnet_data:
201
  (cn_images, _, _, cn_strengths, cn_filepaths) = [diffsynth_controlnet_data[i::5] for i in range(5)]
202
  for i in range(len(cn_images)):
203
  if cn_images[i] and cn_strengths[i] > 0 and cn_filepaths[i] and cn_filepaths[i] != "None":
@@ -213,7 +220,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
213
 
214
  krea2_controlnet_data = ui_inputs.get('krea2_controlnet_data', [])
215
  active_krea2_controlnets = []
216
- if krea2_controlnet_data:
217
  (cn_images, _, _, cn_strengths, cn_filepaths) = [krea2_controlnet_data[i::5] for i in range(5)]
218
  for i in range(len(cn_images)):
219
  if cn_images[i] and cn_strengths[i] > 0 and cn_filepaths[i] and cn_filepaths[i] != "None":
@@ -229,7 +236,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
229
 
230
  ipadapter_data = ui_inputs.get('ipadapter_data', [])
231
  active_ipadapters = []
232
- if ipadapter_data:
233
  num_ipa_units = (len(ipadapter_data) - 5) // 3
234
  final_preset, final_weight, final_lora_strength, final_embeds_scaling, final_combine_method = ipadapter_data[-5:]
235
  ipa_images, ipa_weights, ipa_lora_strengths = [ipadapter_data[i*num_ipa_units:(i+1)*num_ipa_units] for i in range(3)]
@@ -260,7 +267,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
260
 
261
  flux1_ipadapter_data = ui_inputs.get('flux1_ipadapter_data', [])
262
  active_flux1_ipadapters = []
263
- if flux1_ipadapter_data:
264
  num_units = len(flux1_ipadapter_data) // 4
265
  f_images = flux1_ipadapter_data[0*num_units : 1*num_units]
266
  f_weights = flux1_ipadapter_data[1*num_units : 2*num_units]
@@ -289,7 +296,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
289
 
290
  sd3_ipadapter_data = ui_inputs.get('sd3_ipadapter_chain', [])
291
  active_sd3_ipadapters = []
292
- if sd3_ipadapter_data:
293
  num_units = len(sd3_ipadapter_data) // 4
294
  s_images = sd3_ipadapter_data[0*num_units : 1*num_units]
295
  s_weights = sd3_ipadapter_data[1*num_units : 2*num_units]
@@ -311,7 +318,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
311
 
312
  style_data = ui_inputs.get('style_data', [])
313
  active_styles = []
314
- if style_data:
315
  num_units = len(style_data) // 2
316
  st_images = style_data[0*num_units : 1*num_units]
317
  st_strengths = style_data[1*num_units : 2*num_units]
@@ -331,7 +338,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
331
 
332
  reference_latent_data = ui_inputs.get('reference_latent_data', [])
333
  active_reference_latents = []
334
- if reference_latent_data:
335
  for img in reference_latent_data:
336
  if img:
337
  if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
@@ -342,7 +349,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
342
 
343
  hidream_o1_reference_data = ui_inputs.get('hidream_o1_reference_data', [])
344
  active_hidream_o1_reference = []
345
- if hidream_o1_reference_data:
346
  for img in hidream_o1_reference_data:
347
  if img:
348
  if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
@@ -353,7 +360,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
353
 
354
  joyai_reference_data = ui_inputs.get('joyai_reference_data', [])
355
  active_joyai_reference = []
356
- if joyai_reference_data:
357
  for img in joyai_reference_data:
358
  if img:
359
  if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
@@ -364,7 +371,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
364
 
365
  krea2_identity_edit_data = ui_inputs.get('krea2_identity_edit_data', [])
366
  active_krea2_identity_edit = []
367
- if krea2_identity_edit_data:
368
  for img in krea2_identity_edit_data:
369
  if img:
370
  if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
@@ -375,7 +382,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
375
 
376
  krea2_reference_edit_data = ui_inputs.get('krea2_reference_edit_data', [])
377
  active_krea2_reference_edit = []
378
- if krea2_reference_edit_data:
379
  for img in krea2_reference_edit_data:
380
  if img:
381
  if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
@@ -386,7 +393,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
386
 
387
  qwen_image_edit_data = ui_inputs.get('qwen_image_edit_data', [])
388
  active_qwen_image_edit = []
389
- if qwen_image_edit_data:
390
  for img in qwen_image_edit_data:
391
  if img:
392
  if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
@@ -397,7 +404,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
397
 
398
  boogu_edit_data = ui_inputs.get('boogu_edit_data', [])
399
  active_boogu_edit = []
400
- if boogu_edit_data:
401
  for img in boogu_edit_data:
402
  if img:
403
  if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
@@ -408,7 +415,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
408
 
409
  reference_image_data = ui_inputs.get('reference_image_data', [])
410
  active_reference_images = []
411
- if reference_image_data:
412
  for img in reference_image_data:
413
  if img:
414
  if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
@@ -420,7 +427,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
420
  vae_source = ui_inputs.get('vae_source')
421
  vae_id = ui_inputs.get('vae_id')
422
  vae_name_override = None
423
- if vae_source and vae_source != "None":
424
  if vae_source == "File":
425
  vae_name_override = sanitize_filename(vae_id)
426
  local_path = os.path.join(VAE_DIR, vae_name_override)
@@ -435,7 +442,7 @@ def process_pipeline_inputs(ui_inputs: Dict[str, Any], progress: gr.Progress, wo
435
 
436
  conditioning_data = ui_inputs.get('conditioning_data', [])
437
  active_conditioning = []
438
- if conditioning_data:
439
  num_units = len(conditioning_data) // 6
440
  prompts, widths, heights, xs, ys, strengths = [conditioning_data[i*num_units : (i+1)*num_units] for i in range(6)]
441
  for i in range(num_units):
 
5
  from PIL import Image, ImageChops
6
  from typing import Dict, Any, List
7
 
8
+ from core.settings import (
9
+ INPUT_DIR, MULTIPLIERS_MAP, LORA_DIR, EMBEDDING_DIR, VAE_DIR,
10
+ FEATURES_CONFIG, TASK_FEATURES_CONFIG
11
+ )
12
  from utils.app_utils import (
13
  sanitize_filename,
14
  get_lora_path,
 
24
  task_type = ui_inputs['task_type']
25
  temp_files_to_clean = []
26
 
27
+ arch_enabled_chains = FEATURES_CONFIG.get(workflow_model_type, {}).get('enabled_chains', [])
28
+ task_enabled_chains = TASK_FEATURES_CONFIG.get(task_type, {}).get('enabled_chains', [])
29
+ enabled_chains = set([c for c in arch_enabled_chains if c in task_enabled_chains])
30
+
31
  multiplier = MULTIPLIERS_MAP.get(workflow_model_type, 8)
32
  img_w, img_h = 0, 0
33
  if task_type == 'txt2img':
 
60
 
61
  lora_data = ui_inputs.get('lora_data', [])
62
  active_loras_for_gpu, active_loras_for_meta = [], []
63
+ if 'lora' in enabled_chains and lora_data:
64
  sources, ids, scales, files = lora_data[0::4], lora_data[1::4], lora_data[2::4], lora_data[3::4]
65
  for i, (source, lora_id, scale, _) in enumerate(zip(sources, ids, scales, files)):
66
  if scale > 0 and lora_id and lora_id.strip():
 
152
 
153
  embedding_data = ui_inputs.get('embedding_data', [])
154
  embedding_filenames = []
155
+ if 'embedding' in enabled_chains and embedding_data:
156
  emb_sources, emb_ids, emb_files = embedding_data[0::3], embedding_data[1::3], embedding_data[2::3]
157
  for i, (source, emb_id, _) in enumerate(zip(emb_sources, emb_ids, emb_files)):
158
  if emb_id and emb_id.strip():
 
172
 
173
  controlnet_data = ui_inputs.get('controlnet_data', [])
174
  active_controlnets = []
175
+ if 'controlnet' in enabled_chains and controlnet_data:
176
  (cn_images, _, _, cn_strengths, cn_filepaths) = [controlnet_data[i::5] for i in range(5)]
177
  for i in range(len(cn_images)):
178
  if cn_images[i] and cn_strengths[i] > 0 and cn_filepaths[i] and cn_filepaths[i] != "None":
 
188
 
189
  anima_controlnet_lllite_data = ui_inputs.get('anima_controlnet_lllite_data', [])
190
  active_anima_controlnets = []
191
+ if 'anima_controlnet_lllite' in enabled_chains and anima_controlnet_lllite_data:
192
  (cn_images, _, _, cn_strengths, cn_filepaths, cn_starts, cn_ends) = [anima_controlnet_lllite_data[i::7] for i in range(7)]
193
  for i in range(len(cn_images)):
194
  if cn_images[i] and cn_strengths[i] > 0 and cn_filepaths[i] and cn_filepaths[i] != "None":
 
204
 
205
  diffsynth_controlnet_data = ui_inputs.get('diffsynth_controlnet_data', [])
206
  active_diffsynth_controlnets = []
207
+ if 'diffsynth_controlnet' in enabled_chains and diffsynth_controlnet_data:
208
  (cn_images, _, _, cn_strengths, cn_filepaths) = [diffsynth_controlnet_data[i::5] for i in range(5)]
209
  for i in range(len(cn_images)):
210
  if cn_images[i] and cn_strengths[i] > 0 and cn_filepaths[i] and cn_filepaths[i] != "None":
 
220
 
221
  krea2_controlnet_data = ui_inputs.get('krea2_controlnet_data', [])
222
  active_krea2_controlnets = []
223
+ if 'krea2_controlnet' in enabled_chains and krea2_controlnet_data:
224
  (cn_images, _, _, cn_strengths, cn_filepaths) = [krea2_controlnet_data[i::5] for i in range(5)]
225
  for i in range(len(cn_images)):
226
  if cn_images[i] and cn_strengths[i] > 0 and cn_filepaths[i] and cn_filepaths[i] != "None":
 
236
 
237
  ipadapter_data = ui_inputs.get('ipadapter_data', [])
238
  active_ipadapters = []
239
+ if 'ipadapter' in enabled_chains and ipadapter_data:
240
  num_ipa_units = (len(ipadapter_data) - 5) // 3
241
  final_preset, final_weight, final_lora_strength, final_embeds_scaling, final_combine_method = ipadapter_data[-5:]
242
  ipa_images, ipa_weights, ipa_lora_strengths = [ipadapter_data[i*num_ipa_units:(i+1)*num_ipa_units] for i in range(3)]
 
267
 
268
  flux1_ipadapter_data = ui_inputs.get('flux1_ipadapter_data', [])
269
  active_flux1_ipadapters = []
270
+ if 'flux1_ipadapter' in enabled_chains and flux1_ipadapter_data:
271
  num_units = len(flux1_ipadapter_data) // 4
272
  f_images = flux1_ipadapter_data[0*num_units : 1*num_units]
273
  f_weights = flux1_ipadapter_data[1*num_units : 2*num_units]
 
296
 
297
  sd3_ipadapter_data = ui_inputs.get('sd3_ipadapter_chain', [])
298
  active_sd3_ipadapters = []
299
+ if 'sd3_ipadapter' in enabled_chains and sd3_ipadapter_data:
300
  num_units = len(sd3_ipadapter_data) // 4
301
  s_images = sd3_ipadapter_data[0*num_units : 1*num_units]
302
  s_weights = sd3_ipadapter_data[1*num_units : 2*num_units]
 
318
 
319
  style_data = ui_inputs.get('style_data', [])
320
  active_styles = []
321
+ if 'style' in enabled_chains and style_data:
322
  num_units = len(style_data) // 2
323
  st_images = style_data[0*num_units : 1*num_units]
324
  st_strengths = style_data[1*num_units : 2*num_units]
 
338
 
339
  reference_latent_data = ui_inputs.get('reference_latent_data', [])
340
  active_reference_latents = []
341
+ if 'reference_latent' in enabled_chains and reference_latent_data:
342
  for img in reference_latent_data:
343
  if img:
344
  if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
 
349
 
350
  hidream_o1_reference_data = ui_inputs.get('hidream_o1_reference_data', [])
351
  active_hidream_o1_reference = []
352
+ if 'hidream_o1_reference' in enabled_chains and hidream_o1_reference_data:
353
  for img in hidream_o1_reference_data:
354
  if img:
355
  if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
 
360
 
361
  joyai_reference_data = ui_inputs.get('joyai_reference_data', [])
362
  active_joyai_reference = []
363
+ if 'joyai_image' in enabled_chains and joyai_reference_data:
364
  for img in joyai_reference_data:
365
  if img:
366
  if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
 
371
 
372
  krea2_identity_edit_data = ui_inputs.get('krea2_identity_edit_data', [])
373
  active_krea2_identity_edit = []
374
+ if 'krea2_identity_edit' in enabled_chains and krea2_identity_edit_data:
375
  for img in krea2_identity_edit_data:
376
  if img:
377
  if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
 
382
 
383
  krea2_reference_edit_data = ui_inputs.get('krea2_reference_edit_data', [])
384
  active_krea2_reference_edit = []
385
+ if 'krea2_style_reference' in enabled_chains and krea2_reference_edit_data:
386
  for img in krea2_reference_edit_data:
387
  if img:
388
  if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
 
393
 
394
  qwen_image_edit_data = ui_inputs.get('qwen_image_edit_data', [])
395
  active_qwen_image_edit = []
396
+ if 'qwen_image_edit' in enabled_chains and qwen_image_edit_data:
397
  for img in qwen_image_edit_data:
398
  if img:
399
  if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
 
404
 
405
  boogu_edit_data = ui_inputs.get('boogu_edit_data', [])
406
  active_boogu_edit = []
407
+ if 'boogu_image_edit' in enabled_chains and boogu_edit_data:
408
  for img in boogu_edit_data:
409
  if img:
410
  if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
 
415
 
416
  reference_image_data = ui_inputs.get('reference_image_data', [])
417
  active_reference_images = []
418
+ if 'reference_image' in enabled_chains and reference_image_data:
419
  for img in reference_image_data:
420
  if img:
421
  if not os.path.exists(INPUT_DIR): os.makedirs(INPUT_DIR)
 
427
  vae_source = ui_inputs.get('vae_source')
428
  vae_id = ui_inputs.get('vae_id')
429
  vae_name_override = None
430
+ if 'vae' in enabled_chains and vae_source and vae_source != "None":
431
  if vae_source == "File":
432
  vae_name_override = sanitize_filename(vae_id)
433
  local_path = os.path.join(VAE_DIR, vae_name_override)
 
442
 
443
  conditioning_data = ui_inputs.get('conditioning_data', [])
444
  active_conditioning = []
445
+ if 'conditioning' in enabled_chains and conditioning_data:
446
  num_units = len(conditioning_data) // 6
447
  prompts, widths, heights, xs, ys, strengths = [conditioning_data[i*num_units : (i+1)*num_units] for i in range(6)]
448
  for i in range(num_units):
core/pipelines/sd_image_pipeline.py CHANGED
@@ -70,7 +70,11 @@ class SdImagePipeline(BasePipeline):
70
 
71
  required_models = self.get_required_models(model_display_name=model_display_name)
72
 
73
- is_pid_enabled = (ui_inputs.get('pid_settings', 'OFF') == 'ON' and task_type == 'txt2img')
 
 
 
 
74
  if is_pid_enabled:
75
  import yaml
76
  pid_config_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'yaml', 'pid.yaml')
@@ -149,7 +153,7 @@ class SdImagePipeline(BasePipeline):
149
  assembler = WorkflowAssembler(recipe_path, dynamic_values=dynamic_values)
150
 
151
  hidream_o1_smoothing_data = []
152
- if workflow_model_type == 'hidream-o1' and model_display_name == "HiDream-O1-Image":
153
  hidream_o1_smoothing_data.append({})
154
 
155
  workflow_inputs = {
@@ -159,8 +163,7 @@ class SdImagePipeline(BasePipeline):
159
  "sampler_name": ui_inputs['sampler'], "scheduler": ui_inputs['scheduler'],
160
  "batch_size": ui_inputs['batch_size'],
161
  "denoise": ui_inputs['denoise'],
162
- "vae_name": ui_inputs.get('vae_name'),
163
- "guidance": ui_inputs.get('guidance', 3.5),
164
  "lora_chain": active_loras_for_gpu,
165
  "controlnet_chain": active_controlnets if not active_anima_controlnets else [],
166
  "anima_controlnet_lllite_chain": active_anima_controlnets,
@@ -179,7 +182,7 @@ class SdImagePipeline(BasePipeline):
179
  "qwen_image_edit_chain": active_qwen_image_edit,
180
  "boogu_image_edit_chain": active_boogu_edit,
181
  "reference_image_chain": active_reference_images,
182
- "vae_chain": [ui_inputs.get('vae_name')] if ui_inputs.get('vae_name') else [],
183
  "hidream_o1_smoothing_chain": hidream_o1_smoothing_data,
184
  "pid_chain": [ui_inputs.get('pid_settings', 'OFF')] if is_pid_enabled else [],
185
  "scheduler_width": ui_inputs.get('width', 1024),
 
70
 
71
  required_models = self.get_required_models(model_display_name=model_display_name)
72
 
73
+ arch_enabled_chains = FEATURES_CONFIG.get(workflow_model_type, {}).get('enabled_chains', [])
74
+ task_enabled_chains = TASK_FEATURES_CONFIG.get(task_type, {}).get('enabled_chains', [])
75
+ enabled_chains = set([c for c in arch_enabled_chains if c in task_enabled_chains])
76
+
77
+ is_pid_enabled = (ui_inputs.get('pid_settings', 'OFF') == 'ON' and 'pid' in enabled_chains and task_type == 'txt2img')
78
  if is_pid_enabled:
79
  import yaml
80
  pid_config_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'yaml', 'pid.yaml')
 
153
  assembler = WorkflowAssembler(recipe_path, dynamic_values=dynamic_values)
154
 
155
  hidream_o1_smoothing_data = []
156
+ if 'hidream_o1_smoothing' in enabled_chains and model_display_name == "HiDream-O1-Image":
157
  hidream_o1_smoothing_data.append({})
158
 
159
  workflow_inputs = {
 
163
  "sampler_name": ui_inputs['sampler'], "scheduler": ui_inputs['scheduler'],
164
  "batch_size": ui_inputs['batch_size'],
165
  "denoise": ui_inputs['denoise'],
166
+ "vae_name": ui_inputs.get('vae_name') if 'vae' in enabled_chains else None,
 
167
  "lora_chain": active_loras_for_gpu,
168
  "controlnet_chain": active_controlnets if not active_anima_controlnets else [],
169
  "anima_controlnet_lllite_chain": active_anima_controlnets,
 
182
  "qwen_image_edit_chain": active_qwen_image_edit,
183
  "boogu_image_edit_chain": active_boogu_edit,
184
  "reference_image_chain": active_reference_images,
185
+ "vae_chain": [ui_inputs.get('vae_name')] if (ui_inputs.get('vae_name') and 'vae' in enabled_chains) else [],
186
  "hidream_o1_smoothing_chain": hidream_o1_smoothing_data,
187
  "pid_chain": [ui_inputs.get('pid_settings', 'OFF')] if is_pid_enabled else [],
188
  "scheduler_width": ui_inputs.get('width', 1024),
core/pipelines/workflow_recipes/_partials/conditioning/flux1.yaml CHANGED
@@ -22,6 +22,8 @@ nodes:
22
  flux_guidance:
23
  class_type: FluxGuidance
24
  title: "FluxGuidance"
 
 
25
 
26
  connections:
27
  - from: "unet_loader:0"
@@ -72,5 +74,4 @@ ui_map:
72
  unet_name: "unet_loader:unet_name"
73
  vae_name: "vae_loader:vae_name"
74
  clip1_name: "clip_loader:clip_name1"
75
- clip2_name: "clip_loader:clip_name2"
76
- guidance: "flux_guidance:guidance"
 
22
  flux_guidance:
23
  class_type: FluxGuidance
24
  title: "FluxGuidance"
25
+ params:
26
+ guidance: 3.5
27
 
28
  connections:
29
  - from: "unet_loader:0"
 
74
  unet_name: "unet_loader:unet_name"
75
  vae_name: "vae_loader:vae_name"
76
  clip1_name: "clip_loader:clip_name1"
77
+ clip2_name: "clip_loader:clip_name2"
 
core/settings.py CHANGED
@@ -38,7 +38,8 @@ _FILE_LIST_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'file_list.yaml')
38
  _IPADAPTER_LIST_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'ipadapter.yaml')
39
  _CONSTANTS_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'constants.yaml')
40
  _MODEL_ARCHITECTURES_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'model_architectures.yaml')
41
- _IMAGE_GEN_FEATURES_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'image_gen_features.yaml')
 
42
  _MODEL_DEFAULTS_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'model_defaults.yaml')
43
 
44
  def load_constants_from_yaml(filepath=_CONSTANTS_PATH):
@@ -55,13 +56,20 @@ def load_architectures_config(filepath=_MODEL_ARCHITECTURES_PATH):
55
  with open(filepath, 'r', encoding='utf-8') as f:
56
  return yaml.safe_load(f)
57
 
58
- def load_features_config(filepath=_IMAGE_GEN_FEATURES_PATH):
59
  if not os.path.exists(filepath):
60
  print(f"Warning: Features file not found at {filepath}.")
61
  return {}
62
  with open(filepath, 'r', encoding='utf-8') as f:
63
  return yaml.safe_load(f)
64
 
 
 
 
 
 
 
 
65
  def load_model_defaults(filepath=_MODEL_DEFAULTS_PATH):
66
  if not os.path.exists(filepath):
67
  print(f"Warning: Model defaults file not found at {filepath}.")
@@ -195,6 +203,7 @@ try:
195
  MULTIPLIERS_MAP = _constants.get('MULTIPLIERS_MAP', {})
196
  ARCHITECTURES_CONFIG = load_architectures_config()
197
  FEATURES_CONFIG = load_features_config()
 
198
  MODEL_DEFAULTS_CONFIG = load_model_defaults()
199
  except Exception as e:
200
  print(f"FATAL: Could not load constants from YAML. Error: {e}")
@@ -204,4 +213,5 @@ except Exception as e:
204
  MULTIPLIERS_MAP = {}
205
  ARCHITECTURES_CONFIG = {}
206
  FEATURES_CONFIG = {}
 
207
  MODEL_DEFAULTS_CONFIG = {}
 
38
  _IPADAPTER_LIST_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'ipadapter.yaml')
39
  _CONSTANTS_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'constants.yaml')
40
  _MODEL_ARCHITECTURES_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'model_architectures.yaml')
41
+ _MODEL_ARCH_FEATURES_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'model_architecture_features.yaml')
42
+ _TASK_FEATURES_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'task_features.yaml')
43
  _MODEL_DEFAULTS_PATH = os.path.join(_PROJECT_ROOT, 'yaml', 'model_defaults.yaml')
44
 
45
  def load_constants_from_yaml(filepath=_CONSTANTS_PATH):
 
56
  with open(filepath, 'r', encoding='utf-8') as f:
57
  return yaml.safe_load(f)
58
 
59
+ def load_features_config(filepath=_MODEL_ARCH_FEATURES_PATH):
60
  if not os.path.exists(filepath):
61
  print(f"Warning: Features file not found at {filepath}.")
62
  return {}
63
  with open(filepath, 'r', encoding='utf-8') as f:
64
  return yaml.safe_load(f)
65
 
66
+ def load_task_features_config(filepath=_TASK_FEATURES_PATH):
67
+ if not os.path.exists(filepath):
68
+ print(f"Warning: Task features file not found at {filepath}.")
69
+ return {}
70
+ with open(filepath, 'r', encoding='utf-8') as f:
71
+ return yaml.safe_load(f)
72
+
73
  def load_model_defaults(filepath=_MODEL_DEFAULTS_PATH):
74
  if not os.path.exists(filepath):
75
  print(f"Warning: Model defaults file not found at {filepath}.")
 
203
  MULTIPLIERS_MAP = _constants.get('MULTIPLIERS_MAP', {})
204
  ARCHITECTURES_CONFIG = load_architectures_config()
205
  FEATURES_CONFIG = load_features_config()
206
+ TASK_FEATURES_CONFIG = load_task_features_config()
207
  MODEL_DEFAULTS_CONFIG = load_model_defaults()
208
  except Exception as e:
209
  print(f"FATAL: Could not load constants from YAML. Error: {e}")
 
213
  MULTIPLIERS_MAP = {}
214
  ARCHITECTURES_CONFIG = {}
215
  FEATURES_CONFIG = {}
216
+ TASK_FEATURES_CONFIG = {}
217
  MODEL_DEFAULTS_CONFIG = {}
mcp_tools/common.py CHANGED
@@ -20,8 +20,9 @@ _YAML_DIR = os.path.join(_PROJECT_ROOT, "yaml")
20
  _MODEL_ARCHITECTURES_PATH = os.path.join(_YAML_DIR, "model_architectures.yaml")
21
  _MODEL_LIST_PATH = os.path.join(_YAML_DIR, "model_list.yaml")
22
  _MODEL_DEFAULTS_PATH = os.path.join(_YAML_DIR, "model_defaults.yaml")
23
- _IMAGE_GEN_FEATURES_PATH = os.path.join(_YAML_DIR, "image_gen_features.yaml")
24
  _CHAIN_FEATURES_PATH = os.path.join(_YAML_DIR, "chain_features.yaml")
 
25
  _CONSTANTS_PATH = os.path.join(_YAML_DIR, "constants.yaml")
26
 
27
 
 
20
  _MODEL_ARCHITECTURES_PATH = os.path.join(_YAML_DIR, "model_architectures.yaml")
21
  _MODEL_LIST_PATH = os.path.join(_YAML_DIR, "model_list.yaml")
22
  _MODEL_DEFAULTS_PATH = os.path.join(_YAML_DIR, "model_defaults.yaml")
23
+ _IMAGE_GEN_FEATURES_PATH = os.path.join(_YAML_DIR, "model_architecture_features.yaml")
24
  _CHAIN_FEATURES_PATH = os.path.join(_YAML_DIR, "chain_features.yaml")
25
+ _TASK_FEATURES_PATH = os.path.join(_YAML_DIR, "task_features.yaml")
26
  _CONSTANTS_PATH = os.path.join(_YAML_DIR, "constants.yaml")
27
 
28
 
mcp_tools/get_feature_list.py CHANGED
@@ -1,6 +1,6 @@
1
  import os
2
  from copy import deepcopy
3
- from .common import _load_yaml, _CHAIN_FEATURES_PATH, _YAML_DIR
4
  from .error_schema import make_not_found_error
5
 
6
 
@@ -79,14 +79,35 @@ def _get_default_example_chain_item(chain_name: str, chain_data: dict) -> dict:
79
  return item
80
 
81
 
82
- def _build_feature_entry(chain_name: str, chain_data: dict, include_schema: bool = False) -> dict:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  example_item = _get_default_example_chain_item(chain_name, chain_data)
84
  entry = {
85
  "feature_name": chain_name,
86
  "chains": chain_data.get("chains", chain_name),
87
  "display_name": chain_data.get("display_name", chain_name),
88
  "description": chain_data.get("description", ""),
89
- "supported_tasks": chain_data.get("supported_tasks", []),
90
  "max_count": chain_data.get("max_count", 1),
91
  "usage_guideline": chain_data.get("usage_guideline", ""),
92
  "example_chain_item": example_item,
@@ -158,6 +179,7 @@ def handle_get_feature_list(feature_name: str | list[str] = "") -> list | dict:
158
  returns complete feature details INCLUDING parameters_schema for the requested feature(s).
159
  """
160
  chain_features = _load_yaml(_CHAIN_FEATURES_PATH)
 
161
 
162
  targets = []
163
  is_single_string_query = False
@@ -174,7 +196,7 @@ def handle_get_feature_list(feature_name: str | list[str] = "") -> list | dict:
174
  # Case 1: Empty input -> return summary list of all features (without parameters_schema)
175
  if not targets:
176
  return [
177
- _build_feature_entry(name, data, include_schema=False)
178
  for name, data in chain_features.items()
179
  ]
180
 
@@ -200,7 +222,7 @@ def handle_get_feature_list(feature_name: str | list[str] = "") -> list | dict:
200
 
201
  # Case 3: Return full info including parameters_schema
202
  results = [
203
- _build_feature_entry(target, chain_features[target], include_schema=True)
204
  for target in resolved_targets
205
  ]
206
 
 
1
  import os
2
  from copy import deepcopy
3
+ from .common import _load_yaml, _CHAIN_FEATURES_PATH, _TASK_FEATURES_PATH, _YAML_DIR
4
  from .error_schema import make_not_found_error
5
 
6
 
 
79
  return item
80
 
81
 
82
+ def _get_supported_tasks_for_feature(chain_name: str, chain_data: dict, task_features: dict) -> list:
83
+ feat_chains = chain_data.get("chains", chain_name)
84
+ if isinstance(feat_chains, str):
85
+ target_chains = {feat_chains, chain_name}
86
+ elif isinstance(feat_chains, (list, tuple, set)):
87
+ target_chains = set(feat_chains) | {chain_name}
88
+ else:
89
+ target_chains = {chain_name}
90
+
91
+ supported = []
92
+ for task_name, task_data in task_features.items():
93
+ if not isinstance(task_data, dict):
94
+ continue
95
+ enabled_chains = task_data.get("enabled_chains", [])
96
+ if any(c in enabled_chains for c in target_chains):
97
+ supported.append(task_name)
98
+ return supported
99
+
100
+
101
+ def _build_feature_entry(chain_name: str, chain_data: dict, task_features: dict = None, include_schema: bool = False) -> dict:
102
+ if task_features is None:
103
+ task_features = _load_yaml(_TASK_FEATURES_PATH)
104
  example_item = _get_default_example_chain_item(chain_name, chain_data)
105
  entry = {
106
  "feature_name": chain_name,
107
  "chains": chain_data.get("chains", chain_name),
108
  "display_name": chain_data.get("display_name", chain_name),
109
  "description": chain_data.get("description", ""),
110
+ "supported_tasks": _get_supported_tasks_for_feature(chain_name, chain_data, task_features),
111
  "max_count": chain_data.get("max_count", 1),
112
  "usage_guideline": chain_data.get("usage_guideline", ""),
113
  "example_chain_item": example_item,
 
179
  returns complete feature details INCLUDING parameters_schema for the requested feature(s).
180
  """
181
  chain_features = _load_yaml(_CHAIN_FEATURES_PATH)
182
+ task_features = _load_yaml(_TASK_FEATURES_PATH)
183
 
184
  targets = []
185
  is_single_string_query = False
 
196
  # Case 1: Empty input -> return summary list of all features (without parameters_schema)
197
  if not targets:
198
  return [
199
+ _build_feature_entry(name, data, task_features, include_schema=False)
200
  for name, data in chain_features.items()
201
  ]
202
 
 
222
 
223
  # Case 3: Return full info including parameters_schema
224
  results = [
225
+ _build_feature_entry(target, chain_features[target], task_features, include_schema=True)
226
  for target in resolved_targets
227
  ]
228
 
mcp_tools/mcp_gradio_integration.py CHANGED
@@ -56,6 +56,7 @@ def cleanup_dependencies_api_names(demo):
56
  api_name = getattr(fn, "api_name", None)
57
  if api_name not in HIGH_LEVEL_MCP_API_NAMES:
58
  fn.show_api = False
 
59
 
60
  deps = getattr(demo, "dependencies", None)
61
  if deps is None and hasattr(demo, "config") and isinstance(demo.config, dict):
@@ -67,6 +68,7 @@ def cleanup_dependencies_api_names(demo):
67
  api_name = dep.get("api_name")
68
  if api_name not in HIGH_LEVEL_MCP_API_NAMES:
69
  dep["show_api"] = False
 
70
 
71
  print("[MCP Protection] Cleaned up demo dependencies. Suppressed atomic API endpoints.")
72
 
 
56
  api_name = getattr(fn, "api_name", None)
57
  if api_name not in HIGH_LEVEL_MCP_API_NAMES:
58
  fn.show_api = False
59
+ fn.api_name = False
60
 
61
  deps = getattr(demo, "dependencies", None)
62
  if deps is None and hasattr(demo, "config") and isinstance(demo.config, dict):
 
68
  api_name = dep.get("api_name")
69
  if api_name not in HIGH_LEVEL_MCP_API_NAMES:
70
  dep["show_api"] = False
71
+ dep["api_name"] = False
72
 
73
  print("[MCP Protection] Cleaned up demo dependencies. Suppressed atomic API endpoints.")
74
 
requirements.txt CHANGED
@@ -1,5 +1,5 @@
1
  comfyui-frontend-package==1.49.6
2
- comfyui-workflow-templates==0.11.41
3
  comfyui-embedded-docs==0.5.10
4
  torch
5
  torchsde
 
1
  comfyui-frontend-package==1.49.6
2
+ comfyui-workflow-templates==0.11.44
3
  comfyui-embedded-docs==0.5.10
4
  torch
5
  torchsde
ui/events/change_handlers.py CHANGED
@@ -3,6 +3,7 @@ from core.settings import (
3
  MODEL_TYPE_MAP,
4
  MODEL_MAP_CHECKPOINT,
5
  FEATURES_CONFIG,
 
6
  ARCHITECTURES_CONFIG,
7
  MODEL_DEFAULTS_CONFIG,
8
  ARCH_CATEGORIES_MAP
@@ -17,7 +18,7 @@ from .config_loaders import (
17
  load_ipadapter_config
18
  )
19
 
20
- def make_update_fn(m_comp, cat_comp, ar_comp, width_comp, height_comp, cn_types, cn_series, cn_filepaths, anima_cn_types, anima_cn_series, anima_cn_filepaths, diffsynth_cn_types, diffsynth_cn_series, diffsynth_cn_filepaths, krea2_cn_types, krea2_cn_series, krea2_cn_filepaths, ipa_preset, lora_acc, cn_acc, anima_cn_acc, diffsynth_cn_acc, krea2_cn_acc, ipa_acc, sd3_ipa_acc, flux1_ipa_acc, style_acc, embed_acc, cond_acc, ref_latent_acc, hidream_o1_ref_acc, guidance_comp, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp, pid_acc=None, vae_acc=None, joyai_ref_acc=None, krea2_identity_edit_acc=None, krea2_reference_edit_acc=None, qwen_image_edit_acc=None, boogu_edit_acc=None, ref_img_acc=None):
21
  def update_fn(*args):
22
  arch = args[0]
23
  category = args[1]
@@ -53,7 +54,20 @@ def make_update_fn(m_comp, cat_comp, ar_comp, width_comp, height_comp, cn_types,
53
  arch_model_type = architectures_dict.get(m_type, {}).get("model_type", m_type.lower().replace(" ", "").replace(".", ""))
54
 
55
  arch_features = FEATURES_CONFIG.get(arch_model_type, {})
56
- enabled_chains = arch_features.get('enabled_chains', [])
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
  if lora_acc: updates[lora_acc] = gr.update(visible=('lora' in enabled_chains))
59
  if cn_acc: updates[cn_acc] = gr.update(visible=('controlnet' in enabled_chains))
@@ -76,9 +90,6 @@ def make_update_fn(m_comp, cat_comp, ar_comp, width_comp, height_comp, cn_types,
76
  if ref_img_acc: updates[ref_img_acc] = gr.update(visible=('reference_image' in enabled_chains))
77
  if pid_acc: updates[pid_acc] = gr.update(visible=('pid' in enabled_chains))
78
  if vae_acc: updates[vae_acc] = gr.update(visible=('vae' in enabled_chains))
79
-
80
- if guidance_comp:
81
- updates[guidance_comp] = gr.update(visible=(arch_model_type == "flux1"))
82
 
83
  if ar_comp:
84
  res_key = arch_model_type
@@ -146,7 +157,7 @@ def make_update_fn(m_comp, cat_comp, ar_comp, width_comp, height_comp, cn_types,
146
  return update_fn
147
 
148
 
149
- def make_model_change_fn(cat_comp_ref, ar_comp, width_comp, height_comp, cn_types, cn_series, cn_filepaths, anima_cn_types, anima_cn_series, anima_cn_filepaths, diffsynth_cn_types, diffsynth_cn_series, diffsynth_cn_filepaths, krea2_cn_types, krea2_cn_series, krea2_cn_filepaths, arch_comp_ref, ipa_preset, lora_acc, cn_acc, anima_cn_acc, diffsynth_cn_acc, krea2_cn_acc, ipa_acc, sd3_ipa_acc, flux1_ipa_acc, style_acc, embed_acc, cond_acc, ref_latent_acc, hidream_o1_ref_acc, guidance_comp, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp, pid_acc=None, vae_acc=None, joyai_ref_acc=None, krea2_identity_edit_acc=None, krea2_reference_edit_acc=None, qwen_image_edit_acc=None, boogu_edit_acc=None, ref_img_acc=None):
150
  def change_fn(*args):
151
  model_name = args[0]
152
  idx = 1
@@ -187,7 +198,23 @@ def make_model_change_fn(cat_comp_ref, ar_comp, width_comp, height_comp, cn_type
187
  arch_model_type = architectures_dict.get(m_type, {}).get("model_type", m_type.lower().replace(" ", "").replace(".", ""))
188
 
189
  arch_features = FEATURES_CONFIG.get(arch_model_type, {})
190
- enabled_chains = arch_features.get('enabled_chains', [])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
 
192
  if lora_acc: updates[lora_acc] = gr.update(visible=('lora' in enabled_chains))
193
  if cn_acc: updates[cn_acc] = gr.update(visible=('controlnet' in enabled_chains))
@@ -210,9 +237,6 @@ def make_model_change_fn(cat_comp_ref, ar_comp, width_comp, height_comp, cn_type
210
  if ref_img_acc: updates[ref_img_acc] = gr.update(visible=('reference_image' in enabled_chains))
211
  if pid_acc: updates[pid_acc] = gr.update(visible=('pid' in enabled_chains))
212
  if vae_acc: updates[vae_acc] = gr.update(visible=('vae' in enabled_chains))
213
-
214
- if guidance_comp:
215
- updates[guidance_comp] = gr.update(visible=(arch_model_type == "flux1"))
216
 
217
  if ar_comp:
218
  res_key = arch_model_type
@@ -292,7 +316,7 @@ def initialize_all_cn_dropdowns(ui_components):
292
  krea2_all_types, krea2_default_type, krea2_series_choices, krea2_default_series, krea2_filepath = get_krea2_cn_defaults()
293
 
294
  updates = {}
295
- for prefix in ["txt2img", "img2img", "inpaint", "outpaint", "hires_fix"]:
296
  if f'controlnet_types_{prefix}' in ui_components:
297
  for type_dd in ui_components[f'controlnet_types_{prefix}']:
298
  updates[type_dd] = gr.update(choices=all_types, value=default_type)
@@ -348,7 +372,7 @@ def initialize_all_ipa_dropdowns(ui_components):
348
  lora_strength_update = gr.update(visible=is_faceid_default)
349
 
350
  updates = {}
351
- for prefix in ["txt2img", "img2img", "inpaint", "outpaint", "hires_fix"]:
352
  if f'ipadapter_final_preset_{prefix}' in ui_components:
353
  for lora_strength_slider in ui_components[f'ipadapter_lora_strengths_{prefix}']:
354
  updates[lora_strength_slider] = lora_strength_update
 
3
  MODEL_TYPE_MAP,
4
  MODEL_MAP_CHECKPOINT,
5
  FEATURES_CONFIG,
6
+ TASK_FEATURES_CONFIG,
7
  ARCHITECTURES_CONFIG,
8
  MODEL_DEFAULTS_CONFIG,
9
  ARCH_CATEGORIES_MAP
 
18
  load_ipadapter_config
19
  )
20
 
21
+ def make_update_fn(m_comp, cat_comp, ar_comp, width_comp, height_comp, cn_types, cn_series, cn_filepaths, anima_cn_types, anima_cn_series, anima_cn_filepaths, diffsynth_cn_types, diffsynth_cn_series, diffsynth_cn_filepaths, krea2_cn_types, krea2_cn_series, krea2_cn_filepaths, ipa_preset, lora_acc, cn_acc, anima_cn_acc, diffsynth_cn_acc, krea2_cn_acc, ipa_acc, sd3_ipa_acc, flux1_ipa_acc, style_acc, embed_acc, cond_acc, ref_latent_acc, hidream_o1_ref_acc, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp, pid_acc=None, vae_acc=None, joyai_ref_acc=None, krea2_identity_edit_acc=None, krea2_reference_edit_acc=None, qwen_image_edit_acc=None, boogu_edit_acc=None, ref_img_acc=None, task_type=None, type_comp=None):
22
  def update_fn(*args):
23
  arch = args[0]
24
  category = args[1]
 
54
  arch_model_type = architectures_dict.get(m_type, {}).get("model_type", m_type.lower().replace(" ", "").replace(".", ""))
55
 
56
  arch_features = FEATURES_CONFIG.get(arch_model_type, {})
57
+ arch_enabled_chains = arch_features.get('enabled_chains', [])
58
+
59
+ # Determine current task type for task-level feature filtering
60
+ current_task = task_type # static task_type for standalone prefixes
61
+ if type_comp is not None:
62
+ # unified imagegen: task type comes from extra arg
63
+ type_arg_idx = 3 if ar_comp else 2
64
+ if len(args) > type_arg_idx:
65
+ type_val = args[type_arg_idx]
66
+ type_map = {'Txt2Img': 'txt2img', 'Img2Img': 'img2img', 'Inpaint': 'inpaint', 'Outpaint': 'outpaint', 'Hires. Fix': 'hires_fix'}
67
+ current_task = type_map.get(type_val, 'txt2img')
68
+
69
+ task_enabled_chains = TASK_FEATURES_CONFIG.get(current_task, {}).get('enabled_chains', []) if current_task else arch_enabled_chains
70
+ enabled_chains = [c for c in arch_enabled_chains if c in task_enabled_chains]
71
 
72
  if lora_acc: updates[lora_acc] = gr.update(visible=('lora' in enabled_chains))
73
  if cn_acc: updates[cn_acc] = gr.update(visible=('controlnet' in enabled_chains))
 
90
  if ref_img_acc: updates[ref_img_acc] = gr.update(visible=('reference_image' in enabled_chains))
91
  if pid_acc: updates[pid_acc] = gr.update(visible=('pid' in enabled_chains))
92
  if vae_acc: updates[vae_acc] = gr.update(visible=('vae' in enabled_chains))
 
 
 
93
 
94
  if ar_comp:
95
  res_key = arch_model_type
 
157
  return update_fn
158
 
159
 
160
+ def make_model_change_fn(cat_comp_ref, ar_comp, width_comp, height_comp, cn_types, cn_series, cn_filepaths, anima_cn_types, anima_cn_series, anima_cn_filepaths, diffsynth_cn_types, diffsynth_cn_series, diffsynth_cn_filepaths, krea2_cn_types, krea2_cn_series, krea2_cn_filepaths, arch_comp_ref, ipa_preset, lora_acc, cn_acc, anima_cn_acc, diffsynth_cn_acc, krea2_cn_acc, ipa_acc, sd3_ipa_acc, flux1_ipa_acc, style_acc, embed_acc, cond_acc, ref_latent_acc, hidream_o1_ref_acc, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp, pid_acc=None, vae_acc=None, joyai_ref_acc=None, krea2_identity_edit_acc=None, krea2_reference_edit_acc=None, qwen_image_edit_acc=None, boogu_edit_acc=None, ref_img_acc=None, task_type=None, type_comp=None):
161
  def change_fn(*args):
162
  model_name = args[0]
163
  idx = 1
 
198
  arch_model_type = architectures_dict.get(m_type, {}).get("model_type", m_type.lower().replace(" ", "").replace(".", ""))
199
 
200
  arch_features = FEATURES_CONFIG.get(arch_model_type, {})
201
+ arch_enabled_chains = arch_features.get('enabled_chains', [])
202
+
203
+ # Determine current task type for task-level feature filtering
204
+ current_task = task_type # static task_type for standalone prefixes
205
+ if type_comp is not None:
206
+ # unified imagegen: task type comes from extra arg after model, arch, cat, ar
207
+ type_arg_idx = 1
208
+ if arch_comp_ref: type_arg_idx += 1
209
+ if cat_comp_ref: type_arg_idx += 1
210
+ if ar_comp: type_arg_idx += 1
211
+ if len(args) > type_arg_idx:
212
+ type_val = args[type_arg_idx]
213
+ type_map = {'Txt2Img': 'txt2img', 'Img2Img': 'img2img', 'Inpaint': 'inpaint', 'Outpaint': 'outpaint', 'Hires. Fix': 'hires_fix'}
214
+ current_task = type_map.get(type_val, 'txt2img')
215
+
216
+ task_enabled_chains = TASK_FEATURES_CONFIG.get(current_task, {}).get('enabled_chains', []) if current_task else arch_enabled_chains
217
+ enabled_chains = [c for c in arch_enabled_chains if c in task_enabled_chains]
218
 
219
  if lora_acc: updates[lora_acc] = gr.update(visible=('lora' in enabled_chains))
220
  if cn_acc: updates[cn_acc] = gr.update(visible=('controlnet' in enabled_chains))
 
237
  if ref_img_acc: updates[ref_img_acc] = gr.update(visible=('reference_image' in enabled_chains))
238
  if pid_acc: updates[pid_acc] = gr.update(visible=('pid' in enabled_chains))
239
  if vae_acc: updates[vae_acc] = gr.update(visible=('vae' in enabled_chains))
 
 
 
240
 
241
  if ar_comp:
242
  res_key = arch_model_type
 
316
  krea2_all_types, krea2_default_type, krea2_series_choices, krea2_default_series, krea2_filepath = get_krea2_cn_defaults()
317
 
318
  updates = {}
319
+ for prefix in ["imagegen", "txt2img", "img2img", "inpaint", "outpaint", "hires_fix"]:
320
  if f'controlnet_types_{prefix}' in ui_components:
321
  for type_dd in ui_components[f'controlnet_types_{prefix}']:
322
  updates[type_dd] = gr.update(choices=all_types, value=default_type)
 
372
  lora_strength_update = gr.update(visible=is_faceid_default)
373
 
374
  updates = {}
375
+ for prefix in ["imagegen", "txt2img", "img2img", "inpaint", "outpaint", "hires_fix"]:
376
  if f'ipadapter_final_preset_{prefix}' in ui_components:
377
  for lora_strength_slider in ui_components[f'ipadapter_lora_strengths_{prefix}']:
378
  updates[lora_strength_slider] = lora_strength_update
ui/events/main.py CHANGED
@@ -29,15 +29,16 @@ from .change_handlers import (
29
  from .run_handlers import create_run_event
30
 
31
  def attach_event_handlers(ui_components, demo):
32
- for prefix, task_type in [
33
- ("txt2img", "txt2img"), ("img2img", "img2img"), ("inpaint", "inpaint"),
34
- ("outpaint", "outpaint"), ("hires_fix", "hires_fix"),
35
- ]:
 
 
36
 
37
  arch_comp = ui_components.get(f'model_arch_{prefix}')
38
  cat_comp = ui_components.get(f'model_cat_{prefix}')
39
  model_comp = ui_components.get(f'base_model_{prefix}')
40
- guidance_comp = ui_components.get(f'guidance_{prefix}') or ui_components.get(f'{prefix}_guidance')
41
  aspect_ratio_comp = ui_components.get(f'aspect_ratio_{prefix}') or ui_components.get(f'{prefix}_aspect_ratio_dropdown')
42
  width_comp = ui_components.get(f'width_{prefix}') or ui_components.get(f'{prefix}_width')
43
  height_comp = ui_components.get(f'height_{prefix}') or ui_components.get(f'{prefix}_height')
@@ -94,7 +95,6 @@ def attach_event_handlers(ui_components, demo):
94
 
95
  if arch_comp and cat_comp and model_comp:
96
  outputs = [model_comp, cat_comp]
97
- if guidance_comp: outputs.append(guidance_comp)
98
  if aspect_ratio_comp: outputs.append(aspect_ratio_comp)
99
  outputs.extend(cn_types_list + cn_series_list + cn_filepaths_list)
100
  outputs.extend(anima_cn_types_list + anima_cn_series_list + anima_cn_filepaths_list)
@@ -132,12 +132,15 @@ def attach_event_handlers(ui_components, demo):
132
  diffsynth_cn_types_list, diffsynth_cn_series_list, diffsynth_cn_filepaths_list,
133
  krea2_cn_types_list, krea2_cn_series_list, krea2_cn_filepaths_list,
134
  ipa_preset_list, lora_accordion, cn_accordion, anima_cn_accordion, diffsynth_cn_accordion, krea2_cn_accordion, ipa_accordion, sd3_ipa_accordion, flux1_ipa_accordion, style_accordion, embedding_accordion, conditioning_accordion,
135
- ref_latent_accordion, hidream_o1_ref_accordion, guidance_comp, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp,
136
- pid_acc=pid_accordion, vae_acc=vae_accordion, joyai_ref_acc=joyai_ref_accordion, krea2_identity_edit_acc=krea2_identity_edit_accordion, krea2_reference_edit_acc=krea2_reference_edit_accordion, qwen_image_edit_acc=qwen_image_edit_accordion, boogu_edit_acc=boogu_edit_accordion, ref_img_acc=ref_img_accordion
 
137
  )
138
  inputs = [arch_comp, cat_comp]
139
  if aspect_ratio_comp:
140
  inputs.append(aspect_ratio_comp)
 
 
141
  arch_comp.change(fn=update_fn, inputs=inputs, outputs=outputs)
142
  cat_comp.change(fn=update_fn, inputs=inputs, outputs=outputs)
143
 
@@ -145,7 +148,6 @@ def attach_event_handlers(ui_components, demo):
145
  outputs2 = []
146
  if arch_comp: outputs2.append(arch_comp)
147
  if cat_comp: outputs2.append(cat_comp)
148
- if guidance_comp: outputs2.append(guidance_comp)
149
  if aspect_ratio_comp: outputs2.append(aspect_ratio_comp)
150
  outputs2.extend(cn_types_list + cn_series_list + cn_filepaths_list)
151
  outputs2.extend(anima_cn_types_list + anima_cn_series_list + anima_cn_filepaths_list)
@@ -188,9 +190,12 @@ def attach_event_handlers(ui_components, demo):
188
  diffsynth_cn_types_list, diffsynth_cn_series_list, diffsynth_cn_filepaths_list,
189
  krea2_cn_types_list, krea2_cn_series_list, krea2_cn_filepaths_list,
190
  arch_comp, ipa_preset_list, lora_accordion, cn_accordion, anima_cn_accordion, diffsynth_cn_accordion, krea2_cn_accordion, ipa_accordion, sd3_ipa_accordion, flux1_ipa_accordion, style_accordion, embedding_accordion, conditioning_accordion,
191
- ref_latent_accordion, hidream_o1_ref_accordion, guidance_comp, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp,
192
- pid_acc=pid_accordion, vae_acc=vae_accordion, joyai_ref_acc=joyai_ref_accordion, krea2_identity_edit_acc=krea2_identity_edit_accordion, krea2_reference_edit_acc=krea2_reference_edit_accordion, qwen_image_edit_acc=qwen_image_edit_accordion, boogu_edit_acc=boogu_edit_accordion, ref_img_acc=ref_img_accordion
 
193
  )
 
 
194
  model_comp.change(fn=change_fn, inputs=inputs2, outputs=outputs2)
195
 
196
  create_lora_event_handlers(prefix, ui_components)
@@ -214,6 +219,164 @@ def attach_event_handlers(ui_components, demo):
214
  create_reference_image_event_handlers(prefix, ui_components)
215
  create_run_event(prefix, task_type, ui_components)
216
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217
  if 'view_mode_inpaint' in ui_components:
218
  def toggle_inpaint_fullscreen_view(view_mode):
219
  is_fullscreen = (view_mode == "Fullscreen View")
@@ -255,7 +418,7 @@ def attach_event_handlers(ui_components, demo):
255
  )
256
 
257
  all_load_outputs = []
258
- for prefix in ["txt2img", "img2img", "inpaint", "outpaint", "hires_fix"]:
259
  if f'controlnet_types_{prefix}' in ui_components:
260
  all_load_outputs.extend(ui_components[f'controlnet_types_{prefix}'])
261
  all_load_outputs.extend(ui_components[f'controlnet_series_{prefix}'])
@@ -283,7 +446,7 @@ def attach_event_handlers(ui_components, demo):
283
  outputs=all_load_outputs
284
  )
285
 
286
- for prefix in ["txt2img", "img2img", "inpaint", "outpaint", "hires_fix"]:
287
  aspect_ratio_dropdown = ui_components.get(f'aspect_ratio_{prefix}') or ui_components.get(f'{prefix}_aspect_ratio_dropdown')
288
  width_component = ui_components.get(f'width_{prefix}') or ui_components.get(f'{prefix}_width')
289
  height_component = ui_components.get(f'height_{prefix}') or ui_components.get(f'{prefix}_height')
 
29
  from .run_handlers import create_run_event
30
 
31
  def attach_event_handlers(ui_components, demo):
32
+ prefixes = ["imagegen", "txt2img", "img2img", "inpaint", "outpaint", "hires_fix"]
33
+ active_prefixes = [p for p in prefixes if f'base_model_{p}' in ui_components]
34
+
35
+ for prefix in active_prefixes:
36
+ task_type = prefix if prefix != "imagegen" else None
37
+ type_comp = ui_components.get(f'type_{prefix}') # for unified imagegen UI
38
 
39
  arch_comp = ui_components.get(f'model_arch_{prefix}')
40
  cat_comp = ui_components.get(f'model_cat_{prefix}')
41
  model_comp = ui_components.get(f'base_model_{prefix}')
 
42
  aspect_ratio_comp = ui_components.get(f'aspect_ratio_{prefix}') or ui_components.get(f'{prefix}_aspect_ratio_dropdown')
43
  width_comp = ui_components.get(f'width_{prefix}') or ui_components.get(f'{prefix}_width')
44
  height_comp = ui_components.get(f'height_{prefix}') or ui_components.get(f'{prefix}_height')
 
95
 
96
  if arch_comp and cat_comp and model_comp:
97
  outputs = [model_comp, cat_comp]
 
98
  if aspect_ratio_comp: outputs.append(aspect_ratio_comp)
99
  outputs.extend(cn_types_list + cn_series_list + cn_filepaths_list)
100
  outputs.extend(anima_cn_types_list + anima_cn_series_list + anima_cn_filepaths_list)
 
132
  diffsynth_cn_types_list, diffsynth_cn_series_list, diffsynth_cn_filepaths_list,
133
  krea2_cn_types_list, krea2_cn_series_list, krea2_cn_filepaths_list,
134
  ipa_preset_list, lora_accordion, cn_accordion, anima_cn_accordion, diffsynth_cn_accordion, krea2_cn_accordion, ipa_accordion, sd3_ipa_accordion, flux1_ipa_accordion, style_accordion, embedding_accordion, conditioning_accordion,
135
+ ref_latent_accordion, hidream_o1_ref_accordion, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp,
136
+ pid_acc=pid_accordion, vae_acc=vae_accordion, joyai_ref_acc=joyai_ref_accordion, krea2_identity_edit_acc=krea2_identity_edit_accordion, krea2_reference_edit_acc=krea2_reference_edit_accordion, qwen_image_edit_acc=qwen_image_edit_accordion, boogu_edit_acc=boogu_edit_accordion, ref_img_acc=ref_img_accordion,
137
+ task_type=task_type, type_comp=type_comp
138
  )
139
  inputs = [arch_comp, cat_comp]
140
  if aspect_ratio_comp:
141
  inputs.append(aspect_ratio_comp)
142
+ if type_comp:
143
+ inputs.append(type_comp)
144
  arch_comp.change(fn=update_fn, inputs=inputs, outputs=outputs)
145
  cat_comp.change(fn=update_fn, inputs=inputs, outputs=outputs)
146
 
 
148
  outputs2 = []
149
  if arch_comp: outputs2.append(arch_comp)
150
  if cat_comp: outputs2.append(cat_comp)
 
151
  if aspect_ratio_comp: outputs2.append(aspect_ratio_comp)
152
  outputs2.extend(cn_types_list + cn_series_list + cn_filepaths_list)
153
  outputs2.extend(anima_cn_types_list + anima_cn_series_list + anima_cn_filepaths_list)
 
190
  diffsynth_cn_types_list, diffsynth_cn_series_list, diffsynth_cn_filepaths_list,
191
  krea2_cn_types_list, krea2_cn_series_list, krea2_cn_filepaths_list,
192
  arch_comp, ipa_preset_list, lora_accordion, cn_accordion, anima_cn_accordion, diffsynth_cn_accordion, krea2_cn_accordion, ipa_accordion, sd3_ipa_accordion, flux1_ipa_accordion, style_accordion, embedding_accordion, conditioning_accordion,
193
+ ref_latent_accordion, hidream_o1_ref_accordion, prompt_comp, neg_prompt_comp, steps_comp, cfg_comp, sampler_comp, scheduler_comp,
194
+ pid_acc=pid_accordion, vae_acc=vae_accordion, joyai_ref_acc=joyai_ref_accordion, krea2_identity_edit_acc=krea2_identity_edit_accordion, krea2_reference_edit_acc=krea2_reference_edit_accordion, qwen_image_edit_acc=qwen_image_edit_accordion, boogu_edit_acc=boogu_edit_accordion, ref_img_acc=ref_img_accordion,
195
+ task_type=task_type, type_comp=type_comp
196
  )
197
+ if type_comp:
198
+ inputs2.append(type_comp)
199
  model_comp.change(fn=change_fn, inputs=inputs2, outputs=outputs2)
200
 
201
  create_lora_event_handlers(prefix, ui_components)
 
219
  create_reference_image_event_handlers(prefix, ui_components)
220
  create_run_event(prefix, task_type, ui_components)
221
 
222
+ # Dynamic Type toggle event for unified imagegen UI
223
+ if 'type_imagegen' in ui_components:
224
+ def on_type_change(type_val, model_name):
225
+ from core.settings import MODEL_TYPE_MAP, FEATURES_CONFIG, TASK_FEATURES_CONFIG, ARCHITECTURES_CONFIG
226
+ is_txt2img = (type_val == "Txt2Img")
227
+ is_img2img = (type_val == "Img2Img")
228
+ is_inpaint = (type_val == "Inpaint")
229
+ is_outpaint = (type_val == "Outpaint")
230
+ is_hires_fix = (type_val == "Hires. Fix")
231
+
232
+ denoise_val = 0.7 if is_img2img else (1.0 if is_inpaint else (0.55 if is_hires_fix else 0.7))
233
+ run_text = "Run Inpaint" if is_inpaint else ("Run Outpaint" if is_outpaint else ("Run Hires. Fix" if is_hires_fix else "Run"))
234
+
235
+ prompt_lines = 6 if is_inpaint else 3
236
+ gallery_cols = 2 if is_txt2img else 1
237
+ gallery_height = 627 if is_txt2img else (505 if is_img2img else (510 if is_inpaint else (685 if is_outpaint else 610)))
238
+
239
+ updates = {
240
+ ui_components['image_input_col_imagegen']: gr.update(visible=not is_txt2img),
241
+ ui_components['input_image_imagegen']: gr.update(visible=(is_img2img or is_outpaint or is_hires_fix)),
242
+ ui_components['inpaint_box_imagegen']: gr.update(visible=is_inpaint),
243
+ ui_components['prompt_imagegen']: gr.update(lines=prompt_lines),
244
+ ui_components['neg_prompt_imagegen']: gr.update(lines=prompt_lines),
245
+ ui_components['aspect_ratio_row_imagegen']: gr.update(visible=is_txt2img),
246
+ ui_components['width_height_row_imagegen']: gr.update(visible=is_txt2img),
247
+ ui_components['denoise_row_imagegen']: gr.update(visible=(is_img2img or is_inpaint or is_hires_fix)),
248
+ ui_components['denoise_imagegen']: gr.update(value=denoise_val),
249
+ ui_components['grow_mask_by_imagegen']: gr.update(visible=is_inpaint),
250
+ ui_components['outpaint_pads_col_imagegen']: gr.update(visible=is_outpaint),
251
+ ui_components['hires_upscaler_row_imagegen']: gr.update(visible=is_hires_fix),
252
+ ui_components['run_imagegen']: gr.update(value=run_text),
253
+ ui_components['result_imagegen']: gr.update(columns=gallery_cols, height=gallery_height),
254
+ }
255
+
256
+ # Re-evaluate feature accordion visibility based on task + architecture intersection
257
+ type_map = {'Txt2Img': 'txt2img', 'Img2Img': 'img2img', 'Inpaint': 'inpaint', 'Outpaint': 'outpaint', 'Hires. Fix': 'hires_fix'}
258
+ current_task = type_map.get(type_val, 'txt2img')
259
+
260
+ m_type = MODEL_TYPE_MAP.get(model_name, "SDXL") if model_name else "SDXL"
261
+ architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {})
262
+ arch_model_type = architectures_dict.get(m_type, {}).get("model_type", m_type.lower().replace(" ", "").replace(".", ""))
263
+
264
+ arch_enabled_chains = FEATURES_CONFIG.get(arch_model_type, {}).get('enabled_chains', [])
265
+ task_enabled_chains = TASK_FEATURES_CONFIG.get(current_task, {}).get('enabled_chains', [])
266
+ enabled_chains = [c for c in arch_enabled_chains if c in task_enabled_chains]
267
+
268
+ prefix = 'imagegen'
269
+ accordion_chain_map = {
270
+ f'lora_accordion_{prefix}': 'lora',
271
+ f'controlnet_accordion_{prefix}': 'controlnet',
272
+ f'anima_controlnet_lllite_accordion_{prefix}': 'anima_controlnet_lllite',
273
+ f'diffsynth_controlnet_accordion_{prefix}': 'diffsynth_controlnet',
274
+ f'krea2_controlnet_accordion_{prefix}': 'krea2_controlnet',
275
+ f'ipadapter_accordion_{prefix}': 'ipadapter',
276
+ f'sd3_ipadapter_accordion_{prefix}': 'sd3_ipadapter',
277
+ f'flux1_ipadapter_accordion_{prefix}': 'flux1_ipadapter',
278
+ f'style_accordion_{prefix}': 'style',
279
+ f'embedding_accordion_{prefix}': 'embedding',
280
+ f'conditioning_accordion_{prefix}': 'conditioning',
281
+ f'reference_latent_accordion_{prefix}': 'reference_latent',
282
+ f'hidream_o1_reference_accordion_{prefix}': 'hidream_o1_reference',
283
+ f'joyai_reference_accordion_{prefix}': 'joyai_image',
284
+ f'krea2_identity_edit_accordion_{prefix}': 'krea2_identity_edit',
285
+ f'krea2_reference_edit_accordion_{prefix}': 'krea2_style_reference',
286
+ f'qwen_image_edit_accordion_{prefix}': 'qwen_image_edit',
287
+ f'boogu_edit_accordion_{prefix}': 'boogu_image_edit',
288
+ f'reference_image_accordion_{prefix}': 'reference_image',
289
+ f'pid_accordion_{prefix}': 'pid',
290
+ f'vae_accordion_{prefix}': 'vae',
291
+ }
292
+ for comp_key, chain_name in accordion_chain_map.items():
293
+ comp = ui_components.get(comp_key)
294
+ if comp:
295
+ updates[comp] = gr.update(visible=(chain_name in enabled_chains))
296
+
297
+ return updates
298
+
299
+ type_change_outputs = [
300
+ ui_components['image_input_col_imagegen'],
301
+ ui_components['input_image_imagegen'],
302
+ ui_components['inpaint_box_imagegen'],
303
+ ui_components['prompt_imagegen'],
304
+ ui_components['neg_prompt_imagegen'],
305
+ ui_components['aspect_ratio_row_imagegen'],
306
+ ui_components['width_height_row_imagegen'],
307
+ ui_components['denoise_row_imagegen'],
308
+ ui_components['denoise_imagegen'],
309
+ ui_components['grow_mask_by_imagegen'],
310
+ ui_components['outpaint_pads_col_imagegen'],
311
+ ui_components['hires_upscaler_row_imagegen'],
312
+ ui_components['run_imagegen'],
313
+ ui_components['result_imagegen'],
314
+ ]
315
+ # Add feature accordion outputs for task-based visibility
316
+ accordion_keys = [
317
+ 'lora_accordion_imagegen', 'controlnet_accordion_imagegen',
318
+ 'anima_controlnet_lllite_accordion_imagegen', 'diffsynth_controlnet_accordion_imagegen',
319
+ 'krea2_controlnet_accordion_imagegen', 'ipadapter_accordion_imagegen',
320
+ 'sd3_ipadapter_accordion_imagegen', 'flux1_ipadapter_accordion_imagegen',
321
+ 'style_accordion_imagegen', 'embedding_accordion_imagegen',
322
+ 'conditioning_accordion_imagegen', 'reference_latent_accordion_imagegen',
323
+ 'hidream_o1_reference_accordion_imagegen', 'joyai_reference_accordion_imagegen',
324
+ 'krea2_identity_edit_accordion_imagegen', 'krea2_reference_edit_accordion_imagegen',
325
+ 'qwen_image_edit_accordion_imagegen', 'boogu_edit_accordion_imagegen',
326
+ 'reference_image_accordion_imagegen', 'pid_accordion_imagegen', 'vae_accordion_imagegen',
327
+ ]
328
+ for key in accordion_keys:
329
+ if key in ui_components:
330
+ type_change_outputs.append(ui_components[key])
331
+ ui_components['type_imagegen'].change(
332
+ fn=on_type_change,
333
+ inputs=[ui_components['type_imagegen'], ui_components['base_model_imagegen']],
334
+ outputs=type_change_outputs,
335
+ show_progress=False
336
+ )
337
+
338
+ # Fullscreen view toggle for imagegen
339
+ if 'view_mode_imagegen' in ui_components:
340
+ def toggle_imagegen_fullscreen_view(view_mode):
341
+ is_fullscreen = (view_mode == "Fullscreen View")
342
+ other_elements_visible = not is_fullscreen
343
+ editor_height = 800 if is_fullscreen else 272
344
+
345
+ updates = {
346
+ ui_components['type_imagegen']: gr.update(visible=other_elements_visible),
347
+ ui_components['prompts_col_imagegen']: gr.update(visible=other_elements_visible),
348
+ ui_components['params_and_gallery_row_imagegen']: gr.update(visible=other_elements_visible),
349
+ ui_components['accordion_wrapper_imagegen']: gr.update(visible=other_elements_visible),
350
+ ui_components['input_image_dict_imagegen']: gr.update(height=editor_height),
351
+ }
352
+
353
+ model_and_run_rows = ui_components.get('model_and_run_row_imagegen', [])
354
+ for row in model_and_run_rows:
355
+ updates[row] = gr.update(visible=other_elements_visible)
356
+
357
+ return updates
358
+
359
+ output_components = [ui_components['type_imagegen']]
360
+ model_and_run_rows = ui_components.get('model_and_run_row_imagegen', [])
361
+ if isinstance(model_and_run_rows, list):
362
+ output_components.extend(model_and_run_rows)
363
+ else:
364
+ output_components.append(model_and_run_rows)
365
+
366
+ output_components.extend([
367
+ ui_components['prompts_col_imagegen'],
368
+ ui_components['params_and_gallery_row_imagegen'],
369
+ ui_components['accordion_wrapper_imagegen'],
370
+ ui_components['input_image_dict_imagegen']
371
+ ])
372
+
373
+ ui_components['view_mode_imagegen'].change(
374
+ fn=toggle_imagegen_fullscreen_view,
375
+ inputs=[ui_components['view_mode_imagegen']],
376
+ outputs=output_components,
377
+ show_progress=False
378
+ )
379
+
380
  if 'view_mode_inpaint' in ui_components:
381
  def toggle_inpaint_fullscreen_view(view_mode):
382
  is_fullscreen = (view_mode == "Fullscreen View")
 
418
  )
419
 
420
  all_load_outputs = []
421
+ for prefix in prefixes:
422
  if f'controlnet_types_{prefix}' in ui_components:
423
  all_load_outputs.extend(ui_components[f'controlnet_types_{prefix}'])
424
  all_load_outputs.extend(ui_components[f'controlnet_series_{prefix}'])
 
446
  outputs=all_load_outputs
447
  )
448
 
449
+ for prefix in prefixes:
450
  aspect_ratio_dropdown = ui_components.get(f'aspect_ratio_{prefix}') or ui_components.get(f'{prefix}_aspect_ratio_dropdown')
451
  width_component = ui_components.get(f'width_{prefix}') or ui_components.get(f'{prefix}_width')
452
  height_component = ui_components.get(f'height_{prefix}') or ui_components.get(f'{prefix}_height')
ui/events/run_handlers.py CHANGED
@@ -1,7 +1,21 @@
1
  import gradio as gr
2
  from core.generation_logic import generate_image_wrapper
3
 
4
- def create_run_event(prefix: str, task_type: str, ui_components: dict):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  run_inputs_map = {
6
  'model_display_name': ui_components[f'base_model_{prefix}'],
7
  'positive_prompt': ui_components.get(f'prompt_{prefix}') or ui_components.get(f'{prefix}_positive_prompt'),
@@ -13,29 +27,47 @@ def create_run_event(prefix: str, task_type: str, ui_components: dict):
13
  'sampler': ui_components.get(f'sampler_{prefix}') or ui_components.get(f'{prefix}_sampler_name'),
14
  'scheduler': ui_components.get(f'scheduler_{prefix}') or ui_components.get(f'{prefix}_scheduler'),
15
  'zero_gpu_duration': ui_components.get(f'zero_gpu_{prefix}'),
16
- 'guidance': ui_components.get(f'guidance_{prefix}'),
17
- 'task_type': gr.State(task_type)
18
  }
 
 
 
 
 
19
 
20
  if ui_components.get(f'pid_settings_{prefix}'):
21
  run_inputs_map['pid_settings'] = ui_components[f'pid_settings_{prefix}']
22
 
23
- if task_type not in ['img2img', 'inpaint']:
24
- run_inputs_map.update({
25
- 'width': ui_components.get(f'width_{prefix}') or ui_components.get(f'{prefix}_width'),
26
- 'height': ui_components.get(f'height_{prefix}') or ui_components.get(f'{prefix}_height')
27
- })
28
 
29
- task_specific_map = {
30
- 'img2img': {'img2img_image': f'input_image_{prefix}', 'img2img_denoise': f'denoise_{prefix}'},
31
- 'inpaint': {'inpaint_image_dict': f'input_image_dict_{prefix}', 'grow_mask_by': f'grow_mask_by_{prefix}', 'inpaint_denoise': f'denoise_{prefix}'},
32
- 'outpaint': {'outpaint_image': f'input_image_{prefix}', 'left': f'left_{prefix}', 'top': f'top_{prefix}', 'right': f'right_{prefix}', 'bottom': f'bottom_{prefix}', 'feathering': f'feathering_{prefix}'},
33
- 'hires_fix': {'hires_image': f'input_image_{prefix}', 'hires_upscaler': f'hires_upscaler_{prefix}', 'hires_scale_by': f'hires_scale_by_{prefix}', 'hires_denoise': f'denoise_{prefix}'}
34
- }
35
- if task_type in task_specific_map:
36
- for key, comp_name in task_specific_map[task_type].items():
37
- if comp_name in ui_components:
38
- run_inputs_map[key] = ui_components[comp_name]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
  lora_data_components = ui_components.get(f'all_lora_components_flat_{prefix}', [])
41
  controlnet_data_components = ui_components.get(f'all_controlnet_components_flat_{prefix}', [])
@@ -103,6 +135,9 @@ def create_run_event(prefix: str, task_type: str, ui_components: dict):
103
  assign_chain_data('boogu_edit_data', boogu_edit_data_components)
104
  assign_chain_data('reference_image_data', reference_image_data_components)
105
 
 
 
 
106
  return ui_dict
107
 
108
  run_btn = ui_components.get(f'run_{prefix}') or ui_components.get(f'{prefix}_run_button')
 
1
  import gradio as gr
2
  from core.generation_logic import generate_image_wrapper
3
 
4
+ TYPE_TASK_MAP = {
5
+ 'Txt2Img': 'txt2img',
6
+ 'Img2Img': 'img2img',
7
+ 'Inpaint': 'inpaint',
8
+ 'Outpaint': 'outpaint',
9
+ 'Hires. Fix': 'hires_fix'
10
+ }
11
+
12
+ def create_run_event(prefix: str, task_type: str = None, ui_components: dict = None):
13
+ if ui_components is None and isinstance(task_type, dict):
14
+ ui_components = task_type
15
+ task_type = None
16
+
17
+ type_comp = ui_components.get(f'type_{prefix}')
18
+
19
  run_inputs_map = {
20
  'model_display_name': ui_components[f'base_model_{prefix}'],
21
  'positive_prompt': ui_components.get(f'prompt_{prefix}') or ui_components.get(f'{prefix}_positive_prompt'),
 
27
  'sampler': ui_components.get(f'sampler_{prefix}') or ui_components.get(f'{prefix}_sampler_name'),
28
  'scheduler': ui_components.get(f'scheduler_{prefix}') or ui_components.get(f'{prefix}_scheduler'),
29
  'zero_gpu_duration': ui_components.get(f'zero_gpu_{prefix}'),
 
 
30
  }
31
+
32
+ if type_comp:
33
+ run_inputs_map['ui_type'] = type_comp
34
+ elif task_type:
35
+ run_inputs_map['task_type'] = gr.State(task_type)
36
 
37
  if ui_components.get(f'pid_settings_{prefix}'):
38
  run_inputs_map['pid_settings'] = ui_components[f'pid_settings_{prefix}']
39
 
40
+ # Generic / Txt2Img inputs
41
+ if ui_components.get(f'width_{prefix}') or ui_components.get(f'{prefix}_width'):
42
+ run_inputs_map['width'] = ui_components.get(f'width_{prefix}') or ui_components.get(f'{prefix}_width')
43
+ if ui_components.get(f'height_{prefix}') or ui_components.get(f'{prefix}_height'):
44
+ run_inputs_map['height'] = ui_components.get(f'height_{prefix}') or ui_components.get(f'{prefix}_height')
45
 
46
+ # Task specific inputs
47
+ if ui_components.get(f'input_image_{prefix}'):
48
+ run_inputs_map['img2img_image'] = ui_components[f'input_image_{prefix}']
49
+ run_inputs_map['outpaint_image'] = ui_components[f'input_image_{prefix}']
50
+ run_inputs_map['hires_image'] = ui_components[f'input_image_{prefix}']
51
+
52
+ if ui_components.get(f'denoise_{prefix}'):
53
+ run_inputs_map['denoise'] = ui_components[f'denoise_{prefix}']
54
+ run_inputs_map['img2img_denoise'] = ui_components[f'denoise_{prefix}']
55
+ run_inputs_map['inpaint_denoise'] = ui_components[f'denoise_{prefix}']
56
+ run_inputs_map['hires_denoise'] = ui_components[f'denoise_{prefix}']
57
+
58
+ if ui_components.get(f'input_image_dict_{prefix}'):
59
+ run_inputs_map['inpaint_image_dict'] = ui_components[f'input_image_dict_{prefix}']
60
+ if ui_components.get(f'grow_mask_by_{prefix}'):
61
+ run_inputs_map['grow_mask_by'] = ui_components[f'grow_mask_by_{prefix}']
62
+
63
+ if ui_components.get(f'left_{prefix}'): run_inputs_map['left'] = ui_components[f'left_{prefix}']
64
+ if ui_components.get(f'right_{prefix}'): run_inputs_map['right'] = ui_components[f'right_{prefix}']
65
+ if ui_components.get(f'top_{prefix}'): run_inputs_map['top'] = ui_components[f'top_{prefix}']
66
+ if ui_components.get(f'bottom_{prefix}'): run_inputs_map['bottom'] = ui_components[f'bottom_{prefix}']
67
+ if ui_components.get(f'feathering_{prefix}'): run_inputs_map['feathering'] = ui_components[f'feathering_{prefix}']
68
+
69
+ if ui_components.get(f'hires_upscaler_{prefix}'): run_inputs_map['hires_upscaler'] = ui_components[f'hires_upscaler_{prefix}']
70
+ if ui_components.get(f'hires_scale_by_{prefix}'): run_inputs_map['hires_scale_by'] = ui_components[f'hires_scale_by_{prefix}']
71
 
72
  lora_data_components = ui_components.get(f'all_lora_components_flat_{prefix}', [])
73
  controlnet_data_components = ui_components.get(f'all_controlnet_components_flat_{prefix}', [])
 
135
  assign_chain_data('boogu_edit_data', boogu_edit_data_components)
136
  assign_chain_data('reference_image_data', reference_image_data_components)
137
 
138
+ if 'ui_type' in ui_dict:
139
+ ui_dict['task_type'] = TYPE_TASK_MAP.get(ui_dict['ui_type'], 'txt2img')
140
+
141
  return ui_dict
142
 
143
  run_btn = ui_components.get(f'run_{prefix}') or ui_components.get(f'{prefix}_run_button')
ui/{shared/inpaint_ui.py → imagegen_ui.py} RENAMED
@@ -1,125 +1,197 @@
1
- import gradio as gr
2
- from core.settings import MODEL_MAP_CHECKPOINT, MODEL_DEFAULTS_CONFIG
3
- from .ui_components import (
4
- create_base_parameter_ui, create_lora_settings_ui,
5
- create_controlnet_ui, create_anima_controlnet_lllite_ui, create_diffsynth_controlnet_ui, create_krea2_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
6
- create_conditioning_ui, create_vae_override_ui,
7
- create_model_architecture_filter_ui, create_category_filter_ui,
8
- create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
9
- create_reference_latent_ui, create_hidream_o1_reference_ui, create_joyai_reference_ui, create_reference_image_ui, create_krea2_identity_edit_ui, create_krea2_reference_edit_ui, create_qwen_image_edit_ui, create_boogu_edit_ui
10
- )
11
-
12
- default_vals = MODEL_DEFAULTS_CONFIG.get('Default', {})
13
- DEFAULT_STEPS = default_vals.get('steps', 20)
14
- DEFAULT_CFG = default_vals.get('cfg', 5.0)
15
- DEFAULT_SAMPLER = default_vals.get('sampler_name', 'euler')
16
- DEFAULT_SCHEDULER = default_vals.get('scheduler', 'simple')
17
- DEFAULT_POS_PROMPT = default_vals.get('positive_prompt', '')
18
- DEFAULT_NEG_PROMPT = default_vals.get('negative_prompt', '')
19
-
20
- def create_ui():
21
- prefix = "inpaint"
22
- components = {}
23
-
24
- with gr.Column():
25
- with gr.Row() as arch_row:
26
- components.update(create_model_architecture_filter_ui(prefix))
27
-
28
- with gr.Row() as model_and_run_row:
29
- components.update(create_category_filter_ui(prefix))
30
- components[f'base_model_{prefix}'] = gr.Dropdown(
31
- label="Base Model",
32
- choices=list(MODEL_MAP_CHECKPOINT.keys()),
33
- value=list(MODEL_MAP_CHECKPOINT.keys())[0],
34
- scale=3,
35
- allow_custom_value=True
36
- )
37
- with gr.Column(scale=1):
38
- components[f'run_{prefix}'] = gr.Button("Run Inpaint", variant="primary")
39
-
40
- components[f'model_and_run_row_{prefix}'] = [arch_row, model_and_run_row]
41
-
42
- with gr.Row() as main_content_row:
43
- with gr.Column(scale=1) as editor_column:
44
- components[f'view_mode_{prefix}'] = gr.Radio(
45
- ["Normal View", "Fullscreen View"],
46
- label="Editor View",
47
- value="Normal View",
48
- interactive=True
49
- )
50
- components[f'input_image_dict_{prefix}'] = gr.ImageEditor(
51
- type="pil",
52
- label="Image & Mask (No Scaling)",
53
- height=272
54
- )
55
- components[f'editor_column_{prefix}'] = editor_column
56
-
57
- with gr.Column(scale=2) as prompts_column:
58
- components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=6, value=DEFAULT_POS_PROMPT)
59
- components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=6, value=DEFAULT_NEG_PROMPT)
60
- components[f'prompts_column_{prefix}'] = prompts_column
61
-
62
- with gr.Row() as params_and_gallery_row:
63
- with gr.Column(scale=1):
64
- from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
65
- with gr.Row():
66
- components[f'denoise_{prefix}'] = gr.Slider(
67
- label="Denoise", minimum=0.0, maximum=1.0, step=0.05, value=1.0
68
- )
69
- components[f'grow_mask_by_{prefix}'] = gr.Slider(
70
- label="Grow Mask By", minimum=0, maximum=64, step=1, value=6
71
- )
72
- with gr.Row():
73
- components[f'sampler_{prefix}'] = gr.Dropdown(
74
- label="Sampler",
75
- choices=SAMPLER_CHOICES,
76
- value=DEFAULT_SAMPLER if DEFAULT_SAMPLER in SAMPLER_CHOICES else (SAMPLER_CHOICES[0] if SAMPLER_CHOICES else 'euler')
77
- )
78
- components[f'scheduler_{prefix}'] = gr.Dropdown(
79
- label="Scheduler",
80
- choices=SCHEDULER_CHOICES,
81
- value=DEFAULT_SCHEDULER if DEFAULT_SCHEDULER in SCHEDULER_CHOICES else (SCHEDULER_CHOICES[0] if SCHEDULER_CHOICES else 'simple')
82
- )
83
- with gr.Row():
84
- components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=DEFAULT_STEPS)
85
- components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=DEFAULT_CFG)
86
- with gr.Row():
87
- components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
88
- components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
89
- with gr.Row():
90
- components[f'guidance_{prefix}'] = gr.Slider(label="Guidance (FLUX)", minimum=1.0, maximum=10.0, step=0.1, value=3.5, visible=False, interactive=True)
91
- components[f'zero_gpu_{prefix}'] = gr.Number(label="ZeroGPU Duration (s)", value=None, placeholder="Default: 60s, Max: 120s", info="Optional: Set how long to reserve the GPU.")
92
-
93
- components[f'width_{prefix}'] = gr.State(value=512)
94
- components[f'height_{prefix}'] = gr.State(value=512)
95
-
96
- with gr.Column(scale=1):
97
- components[f'result_{prefix}'] = gr.Gallery(label="Result", show_label=False, columns=1, object_fit="contain", height=510)
98
-
99
- components[f'params_and_gallery_row_{prefix}'] = params_and_gallery_row
100
-
101
- with gr.Column() as accordion_wrapper:
102
-
103
- components.update(create_lora_settings_ui(prefix))
104
- components.update(create_controlnet_ui(prefix))
105
- components.update(create_anima_controlnet_lllite_ui(prefix))
106
- components.update(create_diffsynth_controlnet_ui(prefix))
107
- components.update(create_krea2_controlnet_ui(prefix))
108
- components.update(create_ipadapter_ui(prefix))
109
- components.update(create_flux1_ipadapter_ui(prefix))
110
- components.update(create_sd3_ipadapter_ui(prefix))
111
- components.update(create_style_ui(prefix))
112
- components.update(create_embedding_ui(prefix))
113
- components.update(create_conditioning_ui(prefix))
114
- components.update(create_reference_latent_ui(prefix))
115
- components.update(create_hidream_o1_reference_ui(prefix))
116
- components.update(create_joyai_reference_ui(prefix))
117
- components.update(create_krea2_identity_edit_ui(prefix))
118
- components.update(create_krea2_reference_edit_ui(prefix))
119
- components.update(create_qwen_image_edit_ui(prefix))
120
- components.update(create_boogu_edit_ui(prefix))
121
- components.update(create_reference_image_ui(prefix))
122
- components.update(create_vae_override_ui(prefix))
123
- components[f'accordion_wrapper_{prefix}'] = accordion_wrapper
124
-
125
- return components
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from core.settings import MODEL_MAP_CHECKPOINT, MODEL_DEFAULTS_CONFIG
3
+ from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
4
+ from .shared.ui_components import (
5
+ RESOLUTION_MAP,
6
+ create_lora_settings_ui,
7
+ create_controlnet_ui, create_anima_controlnet_lllite_ui, create_diffsynth_controlnet_ui, create_krea2_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
8
+ create_conditioning_ui, create_vae_override_ui,
9
+ create_model_architecture_filter_ui, create_category_filter_ui,
10
+ create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
11
+ create_reference_latent_ui, create_hidream_o1_reference_ui, create_joyai_reference_ui, create_reference_image_ui, create_krea2_identity_edit_ui, create_krea2_reference_edit_ui, create_qwen_image_edit_ui, create_boogu_edit_ui,
12
+ create_pid_ui
13
+ )
14
+
15
+ default_vals = MODEL_DEFAULTS_CONFIG.get('Default', {})
16
+ DEFAULT_STEPS = default_vals.get('steps', 20)
17
+ DEFAULT_CFG = default_vals.get('cfg', 5.0)
18
+ DEFAULT_SAMPLER = default_vals.get('sampler_name', 'euler')
19
+ DEFAULT_SCHEDULER = default_vals.get('scheduler', 'simple')
20
+ DEFAULT_POS_PROMPT = default_vals.get('positive_prompt', '')
21
+ DEFAULT_NEG_PROMPT = default_vals.get('negative_prompt', '')
22
+
23
+ TYPE_CHOICES = ["Txt2Img", "Img2Img", "Inpaint", "Outpaint", "Hires. Fix"]
24
+
25
+ def create_ui():
26
+ """Creates the unified UI components for ImageGen."""
27
+ prefix = "imagegen"
28
+ components = {}
29
+
30
+ with gr.Column():
31
+ components[f'type_{prefix}'] = gr.Radio(
32
+ choices=TYPE_CHOICES,
33
+ value="Txt2Img",
34
+ label="Task",
35
+ interactive=True
36
+ )
37
+
38
+ with gr.Row() as arch_row:
39
+ components.update(create_model_architecture_filter_ui(prefix))
40
+ components[f'arch_row_{prefix}'] = arch_row
41
+
42
+ with gr.Row() as model_and_run_row:
43
+ components.update(create_category_filter_ui(prefix))
44
+ components[f'base_model_{prefix}'] = gr.Dropdown(
45
+ label="Base Model",
46
+ choices=list(MODEL_MAP_CHECKPOINT.keys()),
47
+ value=list(MODEL_MAP_CHECKPOINT.keys())[0],
48
+ scale=3,
49
+ allow_custom_value=True
50
+ )
51
+ with gr.Column(scale=1):
52
+ components[f'run_{prefix}'] = gr.Button("Run", variant="primary")
53
+ components[f'model_and_run_row_{prefix}'] = [arch_row, model_and_run_row]
54
+
55
+ with gr.Row() as inputs_prompts_row:
56
+ with gr.Column(scale=1, visible=False) as image_input_col:
57
+ components[f'input_image_{prefix}'] = gr.Image(
58
+ type="pil",
59
+ label="Input Image (No Scaling)",
60
+ height=255,
61
+ visible=False
62
+ )
63
+ with gr.Column(visible=False) as inpaint_box:
64
+ components[f'view_mode_{prefix}'] = gr.Radio(
65
+ ["Normal View", "Fullscreen View"],
66
+ label="Editor View",
67
+ value="Normal View",
68
+ interactive=True
69
+ )
70
+ components[f'input_image_dict_{prefix}'] = gr.ImageEditor(
71
+ type="pil",
72
+ label="Image & Mask (No Scaling)",
73
+ height=272
74
+ )
75
+ components[f'inpaint_box_{prefix}'] = inpaint_box
76
+ components[f'image_input_col_{prefix}'] = image_input_col
77
+
78
+ with gr.Column(scale=2) as prompts_col:
79
+ components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3, value=DEFAULT_POS_PROMPT)
80
+ components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3, value=DEFAULT_NEG_PROMPT)
81
+ components[f'prompts_col_{prefix}'] = prompts_col
82
+ components[f'inputs_prompts_row_{prefix}'] = inputs_prompts_row
83
+
84
+ with gr.Row() as params_and_gallery_row:
85
+ with gr.Column(scale=1) as params_col:
86
+ # Txt2Img parameters
87
+ with gr.Row(visible=True) as aspect_ratio_row:
88
+ components[f'aspect_ratio_{prefix}'] = gr.Dropdown(
89
+ label="Aspect Ratio",
90
+ choices=list(RESOLUTION_MAP.get('sdxl', {}).keys()),
91
+ value="1:1 (Square)",
92
+ interactive=True,
93
+ allow_custom_value=True
94
+ )
95
+ components[f'aspect_ratio_row_{prefix}'] = aspect_ratio_row
96
+
97
+ with gr.Row(visible=True) as width_height_row:
98
+ components[f'width_{prefix}'] = gr.Number(label="Width", value=1024, interactive=True)
99
+ components[f'height_{prefix}'] = gr.Number(label="Height", value=1024, interactive=True)
100
+ components[f'width_height_row_{prefix}'] = width_height_row
101
+
102
+ # Img2Img / Inpaint / Hires. Fix Denoise parameter & Inpaint Grow Mask By parameter
103
+ with gr.Row(visible=False) as denoise_row:
104
+ components[f'denoise_{prefix}'] = gr.Slider(
105
+ label="Denoise Strength",
106
+ minimum=0.0,
107
+ maximum=1.0,
108
+ step=0.01,
109
+ value=0.7
110
+ )
111
+ components[f'grow_mask_by_{prefix}'] = gr.Slider(
112
+ label="Grow Mask By",
113
+ minimum=0,
114
+ maximum=64,
115
+ step=1,
116
+ value=6,
117
+ visible=False
118
+ )
119
+ components[f'denoise_row_{prefix}'] = denoise_row
120
+
121
+ # Outpaint Pad & Feathering parameters
122
+ with gr.Column(visible=False) as outpaint_pads_col:
123
+ with gr.Row():
124
+ components[f'left_{prefix}'] = gr.Slider(label="Pad Left", minimum=0, maximum=512, step=64, value=64)
125
+ components[f'right_{prefix}'] = gr.Slider(label="Pad Right", minimum=0, maximum=512, step=64, value=64)
126
+ with gr.Row():
127
+ components[f'top_{prefix}'] = gr.Slider(label="Pad Top", minimum=0, maximum=512, step=64, value=64)
128
+ components[f'bottom_{prefix}'] = gr.Slider(label="Pad Bottom", minimum=0, maximum=512, step=64, value=64)
129
+ components[f'feathering_{prefix}'] = gr.Slider(label="Feathering / Grow Mask", minimum=0, maximum=100, step=1, value=10)
130
+ components[f'outpaint_pads_col_{prefix}'] = outpaint_pads_col
131
+
132
+ # Hires. Fix Upscaler parameters
133
+ with gr.Row(visible=False) as hires_upscaler_row:
134
+ components[f'hires_upscaler_{prefix}'] = gr.Dropdown(
135
+ label="Upscaler",
136
+ choices=["nearest-exact", "bilinear", "area", "bicubic", "bislerp"],
137
+ value="nearest-exact"
138
+ )
139
+ components[f'hires_scale_by_{prefix}'] = gr.Slider(
140
+ label="Upscale by",
141
+ minimum=1.0,
142
+ maximum=4.0,
143
+ step=0.1,
144
+ value=1.5
145
+ )
146
+ components[f'hires_upscaler_row_{prefix}'] = hires_upscaler_row
147
+
148
+ # Common parameters
149
+ with gr.Row():
150
+ components[f'sampler_{prefix}'] = gr.Dropdown(
151
+ label="Sampler",
152
+ choices=SAMPLER_CHOICES,
153
+ value=DEFAULT_SAMPLER if DEFAULT_SAMPLER in SAMPLER_CHOICES else (SAMPLER_CHOICES[0] if SAMPLER_CHOICES else 'euler')
154
+ )
155
+ components[f'scheduler_{prefix}'] = gr.Dropdown(
156
+ label="Scheduler",
157
+ choices=SCHEDULER_CHOICES,
158
+ value=DEFAULT_SCHEDULER if DEFAULT_SCHEDULER in SCHEDULER_CHOICES else (SCHEDULER_CHOICES[0] if SCHEDULER_CHOICES else 'simple')
159
+ )
160
+ with gr.Row():
161
+ components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=DEFAULT_STEPS)
162
+ components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=DEFAULT_CFG)
163
+ with gr.Row():
164
+ components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
165
+ components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
166
+ with gr.Row():
167
+ components[f'zero_gpu_{prefix}'] = gr.Number(label="ZeroGPU Duration (s)", value=60, placeholder="Default: 60s, Max: 120s", info="Optional: Set how long to reserve the GPU. Longer jobs may need more time.")
168
+
169
+ with gr.Column(scale=1):
170
+ components[f'result_{prefix}'] = gr.Gallery(label="Result", show_label=False, columns=2, object_fit="contain", height=627)
171
+ components[f'params_and_gallery_row_{prefix}'] = params_and_gallery_row
172
+
173
+ with gr.Column() as accordion_wrapper:
174
+ components.update(create_lora_settings_ui(prefix))
175
+ components.update(create_controlnet_ui(prefix))
176
+ components.update(create_anima_controlnet_lllite_ui(prefix))
177
+ components.update(create_diffsynth_controlnet_ui(prefix))
178
+ components.update(create_krea2_controlnet_ui(prefix))
179
+ components.update(create_ipadapter_ui(prefix))
180
+ components.update(create_flux1_ipadapter_ui(prefix))
181
+ components.update(create_sd3_ipadapter_ui(prefix))
182
+ components.update(create_embedding_ui(prefix))
183
+ components.update(create_style_ui(prefix))
184
+ components.update(create_conditioning_ui(prefix))
185
+ components.update(create_reference_latent_ui(prefix))
186
+ components.update(create_hidream_o1_reference_ui(prefix))
187
+ components.update(create_joyai_reference_ui(prefix))
188
+ components.update(create_krea2_identity_edit_ui(prefix))
189
+ components.update(create_krea2_reference_edit_ui(prefix))
190
+ components.update(create_qwen_image_edit_ui(prefix))
191
+ components.update(create_boogu_edit_ui(prefix))
192
+ components.update(create_reference_image_ui(prefix))
193
+ components.update(create_vae_override_ui(prefix))
194
+ components.update(create_pid_ui(prefix))
195
+ components[f'accordion_wrapper_{prefix}'] = accordion_wrapper
196
+
197
+ return components
ui/layout.py CHANGED
@@ -2,7 +2,7 @@ import os
2
  import gradio as gr
3
  from core.settings import *
4
 
5
- from .shared import txt2img_ui, img2img_ui, inpaint_ui, outpaint_ui, hires_fix_ui
6
 
7
  MAX_DYNAMIC_CONTROLS = 10
8
 
@@ -14,26 +14,9 @@ def build_ui(event_handler_function):
14
  gr.Markdown(
15
  "This demo is a streamlined version of the [Comfy web UI](https://github.com/RioShiina47/comfy-webui)'s [ImageGen](https://huggingface.co/spaces/RioShiina/ImageGen) functionality. Support [High-Level MCP](https://rioshiina-imagegen.hf.space/gradio_api/mcp/) 🤖"
16
  )
17
- with gr.Tabs(elem_id="tabs_container") as tabs:
18
- with gr.TabItem("Txt2Img", id=0):
19
- ui_components.update(txt2img_ui.create_ui())
20
-
21
- with gr.TabItem("Img2Img", id=1):
22
- ui_components.update(img2img_ui.create_ui())
23
-
24
- with gr.TabItem("Inpaint", id=2):
25
- ui_components.update(inpaint_ui.create_ui())
26
-
27
- with gr.TabItem("Outpaint", id=3):
28
- ui_components.update(outpaint_ui.create_ui())
29
-
30
- with gr.TabItem("Hires. Fix", id=4):
31
- ui_components.update(hires_fix_ui.create_ui())
32
-
33
- ui_components["tabs"] = tabs
34
- ui_components["image_gen_tabs"] = tabs
35
 
36
- gr.Markdown("<div style='text-align: center; margin-top: 20px;'>Made by RioShiina with ❤️<br><a href='https://github.com/RioShiina47' target='_blank'>GitHub</a> | <a href='https://huggingface.co/RioShiina' target='_blank'>Hugging Face</a> | <a href='https://civitai.com/user/RioShiina' target='_blank'>Civitai</a></div>")
37
 
38
  event_handler_function(ui_components, demo)
39
 
@@ -54,5 +37,6 @@ def build_ui(event_handler_function):
54
  for fn in demo.fns.values():
55
  if getattr(fn, "api_name", None) not in high_level_names:
56
  fn.show_api = False
 
57
 
58
  return demo
 
2
  import gradio as gr
3
  from core.settings import *
4
 
5
+ from .imagegen_ui import create_ui as create_imagegen_ui
6
 
7
  MAX_DYNAMIC_CONTROLS = 10
8
 
 
14
  gr.Markdown(
15
  "This demo is a streamlined version of the [Comfy web UI](https://github.com/RioShiina47/comfy-webui)'s [ImageGen](https://huggingface.co/spaces/RioShiina/ImageGen) functionality. Support [High-Level MCP](https://rioshiina-imagegen.hf.space/gradio_api/mcp/) 🤖"
16
  )
17
+ ui_components.update(create_imagegen_ui())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
+ gr.Markdown("<div style='text-align: left; margin-top: 20px;'>Made by RioShiina with ❤️<br><a href='https://github.com/RioShiina47' target='_blank'>GitHub</a> | <a href='https://huggingface.co/RioShiina' target='_blank'>Hugging Face</a> | <a href='https://civitai.com/user/RioShiina' target='_blank'>Civitai</a></div>")
20
 
21
  event_handler_function(ui_components, demo)
22
 
 
37
  for fn in demo.fns.values():
38
  if getattr(fn, "api_name", None) not in high_level_names:
39
  fn.show_api = False
40
+ fn.api_name = False
41
 
42
  return demo
ui/shared/hires_fix_ui.py DELETED
@@ -1,111 +0,0 @@
1
- import gradio as gr
2
- from core.settings import MODEL_MAP_CHECKPOINT, MODEL_DEFAULTS_CONFIG
3
- from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
4
- from .ui_components import (
5
- create_lora_settings_ui,
6
- create_controlnet_ui, create_anima_controlnet_lllite_ui, create_diffsynth_controlnet_ui, create_krea2_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
7
- create_conditioning_ui, create_vae_override_ui,
8
- create_model_architecture_filter_ui, create_category_filter_ui,
9
- create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
10
- create_reference_latent_ui, create_hidream_o1_reference_ui, create_joyai_reference_ui, create_reference_image_ui, create_krea2_identity_edit_ui, create_krea2_reference_edit_ui, create_qwen_image_edit_ui, create_boogu_edit_ui
11
- )
12
-
13
- default_vals = MODEL_DEFAULTS_CONFIG.get('Default', {})
14
- DEFAULT_STEPS = default_vals.get('steps', 20)
15
- DEFAULT_CFG = default_vals.get('cfg', 5.0)
16
- DEFAULT_SAMPLER = default_vals.get('sampler_name', 'euler')
17
- DEFAULT_SCHEDULER = default_vals.get('scheduler', 'simple')
18
- DEFAULT_POS_PROMPT = default_vals.get('positive_prompt', '')
19
- DEFAULT_NEG_PROMPT = default_vals.get('negative_prompt', '')
20
-
21
- def create_ui():
22
- prefix = "hires_fix"
23
- components = {}
24
-
25
- with gr.Column():
26
- components.update(create_model_architecture_filter_ui(prefix))
27
-
28
- with gr.Row():
29
- components.update(create_category_filter_ui(prefix))
30
- components[f'base_model_{prefix}'] = gr.Dropdown(
31
- label="Base Model",
32
- choices=list(MODEL_MAP_CHECKPOINT.keys()),
33
- value=list(MODEL_MAP_CHECKPOINT.keys())[0],
34
- scale=3,
35
- allow_custom_value=True
36
- )
37
- with gr.Column(scale=1):
38
- components[f'run_{prefix}'] = gr.Button("Run Hires. Fix", variant="primary")
39
-
40
- with gr.Row():
41
- with gr.Column(scale=1):
42
- components[f'input_image_{prefix}'] = gr.Image(type="pil", label="Input Image (No Scaling)", height=255)
43
- with gr.Column(scale=2):
44
- components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3, value=DEFAULT_POS_PROMPT)
45
- components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3, value=DEFAULT_NEG_PROMPT)
46
-
47
- with gr.Row():
48
- with gr.Column(scale=1):
49
- with gr.Row():
50
- components[f'hires_upscaler_{prefix}'] = gr.Dropdown(
51
- label="Upscaler",
52
- choices=["nearest-exact", "bilinear", "area", "bicubic", "bislerp"],
53
- value="nearest-exact"
54
- )
55
- components[f'hires_scale_by_{prefix}'] = gr.Slider(
56
- label="Upscale by", minimum=1.0, maximum=4.0, step=0.1, value=1.5
57
- )
58
-
59
- with gr.Row():
60
- components[f'denoise_{prefix}'] = gr.Slider(label="Denoise Strength", minimum=0.0, maximum=1.0, step=0.01, value=0.55)
61
-
62
- with gr.Row():
63
- components[f'sampler_{prefix}'] = gr.Dropdown(
64
- label="Sampler",
65
- choices=SAMPLER_CHOICES,
66
- value=DEFAULT_SAMPLER if DEFAULT_SAMPLER in SAMPLER_CHOICES else (SAMPLER_CHOICES[0] if SAMPLER_CHOICES else 'euler')
67
- )
68
- components[f'scheduler_{prefix}'] = gr.Dropdown(
69
- label="Scheduler",
70
- choices=SCHEDULER_CHOICES,
71
- value=DEFAULT_SCHEDULER if DEFAULT_SCHEDULER in SCHEDULER_CHOICES else (SCHEDULER_CHOICES[0] if SCHEDULER_CHOICES else 'simple')
72
- )
73
- with gr.Row():
74
- components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=DEFAULT_STEPS)
75
- components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=DEFAULT_CFG)
76
- with gr.Row():
77
- components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
78
- components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
79
- with gr.Row():
80
- components[f'guidance_{prefix}'] = gr.Slider(label="Guidance (FLUX)", minimum=1.0, maximum=10.0, step=0.1, value=3.5, visible=False, interactive=True)
81
- components[f'zero_gpu_{prefix}'] = gr.Number(label="ZeroGPU Duration (s)", value=None, placeholder="Default: 60s, Max: 120s", info="Optional: Set how long to reserve the GPU.")
82
-
83
- components[f'width_{prefix}'] = gr.State(value=512)
84
- components[f'height_{prefix}'] = gr.State(value=512)
85
-
86
- with gr.Column(scale=1):
87
- components[f'result_{prefix}'] = gr.Gallery(label="Result", show_label=False, columns=1, object_fit="contain", height=610)
88
-
89
-
90
- components.update(create_lora_settings_ui(prefix))
91
- components.update(create_controlnet_ui(prefix))
92
- components.update(create_anima_controlnet_lllite_ui(prefix))
93
- components.update(create_diffsynth_controlnet_ui(prefix))
94
- components.update(create_krea2_controlnet_ui(prefix))
95
- components.update(create_ipadapter_ui(prefix))
96
- components.update(create_flux1_ipadapter_ui(prefix))
97
- components.update(create_sd3_ipadapter_ui(prefix))
98
- components.update(create_style_ui(prefix))
99
- components.update(create_embedding_ui(prefix))
100
- components.update(create_conditioning_ui(prefix))
101
- components.update(create_reference_latent_ui(prefix))
102
- components.update(create_hidream_o1_reference_ui(prefix))
103
- components.update(create_joyai_reference_ui(prefix))
104
- components.update(create_krea2_identity_edit_ui(prefix))
105
- components.update(create_krea2_reference_edit_ui(prefix))
106
- components.update(create_qwen_image_edit_ui(prefix))
107
- components.update(create_boogu_edit_ui(prefix))
108
- components.update(create_reference_image_ui(prefix))
109
- components.update(create_vae_override_ui(prefix))
110
-
111
- return components
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/shared/img2img_ui.py DELETED
@@ -1,92 +0,0 @@
1
- import gradio as gr
2
- from core.settings import MODEL_MAP_CHECKPOINT, MODEL_DEFAULTS_CONFIG
3
- from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
4
- from .ui_components import (
5
- create_lora_settings_ui,
6
- create_controlnet_ui, create_anima_controlnet_lllite_ui, create_diffsynth_controlnet_ui, create_krea2_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
7
- create_conditioning_ui, create_vae_override_ui,
8
- create_model_architecture_filter_ui, create_category_filter_ui,
9
- create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
10
- create_reference_latent_ui, create_hidream_o1_reference_ui, create_joyai_reference_ui, create_reference_image_ui, create_krea2_identity_edit_ui, create_krea2_reference_edit_ui, create_qwen_image_edit_ui, create_boogu_edit_ui
11
- )
12
-
13
- default_vals = MODEL_DEFAULTS_CONFIG.get('Default', {})
14
- DEFAULT_STEPS = default_vals.get('steps', 20)
15
- DEFAULT_CFG = default_vals.get('cfg', 5.0)
16
- DEFAULT_SAMPLER = default_vals.get('sampler_name', 'euler')
17
- DEFAULT_SCHEDULER = default_vals.get('scheduler', 'simple')
18
- DEFAULT_POS_PROMPT = default_vals.get('positive_prompt', '')
19
- DEFAULT_NEG_PROMPT = default_vals.get('negative_prompt', '')
20
-
21
- def create_ui():
22
- prefix = "img2img"
23
- components = {}
24
-
25
- with gr.Column():
26
- components.update(create_model_architecture_filter_ui(prefix))
27
-
28
- with gr.Row():
29
- components.update(create_category_filter_ui(prefix))
30
- components[f'base_model_{prefix}'] = gr.Dropdown(label="Base Model", choices=list(MODEL_MAP_CHECKPOINT.keys()), value=list(MODEL_MAP_CHECKPOINT.keys())[0], scale=3, allow_custom_value=True)
31
- with gr.Column(scale=1):
32
- components[f'run_{prefix}'] = gr.Button("Run", variant="primary")
33
-
34
- with gr.Row():
35
- with gr.Column(scale=1):
36
- components[f'input_image_{prefix}'] = gr.Image(type="pil", label="Input Image (No Scaling)", height=255)
37
-
38
- with gr.Column(scale=2):
39
- components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3, value=DEFAULT_POS_PROMPT)
40
- components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3, value=DEFAULT_NEG_PROMPT)
41
-
42
- with gr.Row():
43
- with gr.Column(scale=1):
44
- components[f'denoise_{prefix}'] = gr.Slider(label="Denoise Strength", minimum=0.0, maximum=1.0, step=0.01, value=0.7)
45
-
46
- with gr.Row():
47
- components[f'sampler_{prefix}'] = gr.Dropdown(
48
- label="Sampler",
49
- choices=SAMPLER_CHOICES,
50
- value=DEFAULT_SAMPLER if DEFAULT_SAMPLER in SAMPLER_CHOICES else (SAMPLER_CHOICES[0] if SAMPLER_CHOICES else 'euler')
51
- )
52
- components[f'scheduler_{prefix}'] = gr.Dropdown(
53
- label="Scheduler",
54
- choices=SCHEDULER_CHOICES,
55
- value=DEFAULT_SCHEDULER if DEFAULT_SCHEDULER in SCHEDULER_CHOICES else (SCHEDULER_CHOICES[0] if SCHEDULER_CHOICES else 'simple')
56
- )
57
- with gr.Row():
58
- components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=DEFAULT_STEPS)
59
- components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=DEFAULT_CFG)
60
- with gr.Row():
61
- components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
62
- components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
63
- with gr.Row():
64
- components[f'guidance_{prefix}'] = gr.Slider(label="Guidance (FLUX)", minimum=1.0, maximum=10.0, step=0.1, value=3.5, visible=False, interactive=True)
65
- components[f'zero_gpu_{prefix}'] = gr.Number(label="ZeroGPU Duration (s)", value=None, placeholder="Default: 60s, Max: 120s", info="Optional: Set how long to reserve the GPU. Longer jobs may need more time.")
66
-
67
- with gr.Column(scale=1):
68
- components[f'result_{prefix}'] = gr.Gallery(label="Result", show_label=False, columns=1, object_fit="contain", height=505)
69
-
70
-
71
- components.update(create_lora_settings_ui(prefix))
72
- components.update(create_controlnet_ui(prefix))
73
- components.update(create_anima_controlnet_lllite_ui(prefix))
74
- components.update(create_diffsynth_controlnet_ui(prefix))
75
- components.update(create_krea2_controlnet_ui(prefix))
76
- components.update(create_ipadapter_ui(prefix))
77
- components.update(create_flux1_ipadapter_ui(prefix))
78
- components.update(create_sd3_ipadapter_ui(prefix))
79
- components.update(create_embedding_ui(prefix))
80
- components.update(create_style_ui(prefix))
81
- components.update(create_conditioning_ui(prefix))
82
- components.update(create_reference_latent_ui(prefix))
83
- components.update(create_hidream_o1_reference_ui(prefix))
84
- components.update(create_joyai_reference_ui(prefix))
85
- components.update(create_krea2_identity_edit_ui(prefix))
86
- components.update(create_krea2_reference_edit_ui(prefix))
87
- components.update(create_qwen_image_edit_ui(prefix))
88
- components.update(create_boogu_edit_ui(prefix))
89
- components.update(create_reference_image_ui(prefix))
90
- components.update(create_vae_override_ui(prefix))
91
-
92
- return components
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/shared/outpaint_ui.py DELETED
@@ -1,107 +0,0 @@
1
- import gradio as gr
2
- from core.settings import MODEL_MAP_CHECKPOINT, MODEL_DEFAULTS_CONFIG
3
- from comfy_integration.nodes import SAMPLER_CHOICES, SCHEDULER_CHOICES
4
- from .ui_components import (
5
- create_lora_settings_ui,
6
- create_controlnet_ui, create_anima_controlnet_lllite_ui, create_diffsynth_controlnet_ui, create_krea2_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
7
- create_conditioning_ui, create_vae_override_ui,
8
- create_model_architecture_filter_ui, create_category_filter_ui,
9
- create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
10
- create_reference_latent_ui, create_hidream_o1_reference_ui, create_joyai_reference_ui, create_reference_image_ui, create_krea2_identity_edit_ui, create_krea2_reference_edit_ui, create_qwen_image_edit_ui, create_boogu_edit_ui
11
- )
12
-
13
- default_vals = MODEL_DEFAULTS_CONFIG.get('Default', {})
14
- DEFAULT_STEPS = default_vals.get('steps', 20)
15
- DEFAULT_CFG = default_vals.get('cfg', 5.0)
16
- DEFAULT_SAMPLER = default_vals.get('sampler_name', 'euler')
17
- DEFAULT_SCHEDULER = default_vals.get('scheduler', 'simple')
18
- DEFAULT_POS_PROMPT = default_vals.get('positive_prompt', '')
19
- DEFAULT_NEG_PROMPT = default_vals.get('negative_prompt', '')
20
-
21
- def create_ui():
22
- prefix = "outpaint"
23
- components = {}
24
-
25
- with gr.Column():
26
- components.update(create_model_architecture_filter_ui(prefix))
27
-
28
- with gr.Row():
29
- components.update(create_category_filter_ui(prefix))
30
- components[f'base_model_{prefix}'] = gr.Dropdown(
31
- label="Base Model",
32
- choices=list(MODEL_MAP_CHECKPOINT.keys()),
33
- value=list(MODEL_MAP_CHECKPOINT.keys())[0],
34
- scale=3,
35
- allow_custom_value=True
36
- )
37
- with gr.Column(scale=1):
38
- components[f'run_{prefix}'] = gr.Button("Run Outpaint", variant="primary")
39
-
40
- with gr.Row():
41
- with gr.Column(scale=1):
42
- components[f'input_image_{prefix}'] = gr.Image(type="pil", label="Input Image (No Scaling)", height=255)
43
- with gr.Column(scale=2):
44
- components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3, value=DEFAULT_POS_PROMPT)
45
- components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3, value=DEFAULT_NEG_PROMPT)
46
-
47
- with gr.Row():
48
- with gr.Column(scale=1):
49
- with gr.Row():
50
- components[f'left_{prefix}'] = gr.Slider(label="Pad Left", minimum=0, maximum=512, step=64, value=64)
51
- components[f'right_{prefix}'] = gr.Slider(label="Pad Right", minimum=0, maximum=512, step=64, value=64)
52
- with gr.Row():
53
- components[f'top_{prefix}'] = gr.Slider(label="Pad Top", minimum=0, maximum=512, step=64, value=64)
54
- components[f'bottom_{prefix}'] = gr.Slider(label="Pad Bottom", minimum=0, maximum=512, step=64, value=64)
55
-
56
- components[f'feathering_{prefix}'] = gr.Slider(label="Feathering / Grow Mask", minimum=0, maximum=100, step=1, value=10)
57
-
58
- with gr.Row():
59
- components[f'sampler_{prefix}'] = gr.Dropdown(
60
- label="Sampler",
61
- choices=SAMPLER_CHOICES,
62
- value=DEFAULT_SAMPLER if DEFAULT_SAMPLER in SAMPLER_CHOICES else (SAMPLER_CHOICES[0] if SAMPLER_CHOICES else 'euler')
63
- )
64
- components[f'scheduler_{prefix}'] = gr.Dropdown(
65
- label="Scheduler",
66
- choices=SCHEDULER_CHOICES,
67
- value=DEFAULT_SCHEDULER if DEFAULT_SCHEDULER in SCHEDULER_CHOICES else (SCHEDULER_CHOICES[0] if SCHEDULER_CHOICES else 'simple')
68
- )
69
- with gr.Row():
70
- components[f'steps_{prefix}'] = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=DEFAULT_STEPS)
71
- components[f'cfg_{prefix}'] = gr.Slider(label="CFG Scale", minimum=1.0, maximum=20.0, step=0.1, value=DEFAULT_CFG)
72
- with gr.Row():
73
- components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
74
- components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
75
- with gr.Row():
76
- components[f'guidance_{prefix}'] = gr.Slider(label="Guidance (FLUX)", minimum=1.0, maximum=10.0, step=0.1, value=3.5, visible=False, interactive=True)
77
- components[f'zero_gpu_{prefix}'] = gr.Number(label="ZeroGPU Duration (s)", value=None, placeholder="Default: 60s, Max: 120s", info="Optional: Set how long to reserve the GPU.")
78
-
79
- components[f'width_{prefix}'] = gr.State(value=512)
80
- components[f'height_{prefix}'] = gr.State(value=512)
81
-
82
- with gr.Column(scale=1):
83
- components[f'result_{prefix}'] = gr.Gallery(label="Result", show_label=False, columns=1, object_fit="contain", height=685)
84
-
85
-
86
- components.update(create_lora_settings_ui(prefix))
87
- components.update(create_controlnet_ui(prefix))
88
- components.update(create_anima_controlnet_lllite_ui(prefix))
89
- components.update(create_diffsynth_controlnet_ui(prefix))
90
- components.update(create_krea2_controlnet_ui(prefix))
91
- components.update(create_ipadapter_ui(prefix))
92
- components.update(create_flux1_ipadapter_ui(prefix))
93
- components.update(create_sd3_ipadapter_ui(prefix))
94
- components.update(create_style_ui(prefix))
95
- components.update(create_embedding_ui(prefix))
96
- components.update(create_conditioning_ui(prefix))
97
- components.update(create_reference_latent_ui(prefix))
98
- components.update(create_hidream_o1_reference_ui(prefix))
99
- components.update(create_joyai_reference_ui(prefix))
100
- components.update(create_krea2_identity_edit_ui(prefix))
101
- components.update(create_krea2_reference_edit_ui(prefix))
102
- components.update(create_qwen_image_edit_ui(prefix))
103
- components.update(create_boogu_edit_ui(prefix))
104
- components.update(create_reference_image_ui(prefix))
105
- components.update(create_vae_override_ui(prefix))
106
-
107
- return components
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/shared/txt2img_ui.py DELETED
@@ -1,66 +0,0 @@
1
- import gradio as gr
2
- from core.settings import MODEL_MAP_CHECKPOINT
3
- from .ui_components import (
4
- create_base_parameter_ui, create_lora_settings_ui,
5
- create_controlnet_ui, create_anima_controlnet_lllite_ui, create_diffsynth_controlnet_ui, create_krea2_controlnet_ui, create_ipadapter_ui, create_embedding_ui,
6
- create_conditioning_ui, create_vae_override_ui,
7
- create_model_architecture_filter_ui, create_category_filter_ui,
8
- create_sd3_ipadapter_ui, create_flux1_ipadapter_ui, create_style_ui,
9
- create_reference_latent_ui, create_hidream_o1_reference_ui, create_joyai_reference_ui, create_reference_image_ui, create_krea2_identity_edit_ui, create_krea2_reference_edit_ui, create_qwen_image_edit_ui, create_boogu_edit_ui,
10
- create_pid_ui
11
- )
12
-
13
- def create_ui():
14
- """Creates the UI components for the Txt2Img tab."""
15
- prefix = "txt2img"
16
- components = {}
17
-
18
- with gr.Column():
19
- components.update(create_model_architecture_filter_ui(prefix))
20
-
21
- with gr.Row():
22
- components.update(create_category_filter_ui(prefix))
23
- components[f'base_model_{prefix}'] = gr.Dropdown(
24
- label="Base Model",
25
- choices=list(MODEL_MAP_CHECKPOINT.keys()),
26
- value=list(MODEL_MAP_CHECKPOINT.keys())[0],
27
- scale=3,
28
- allow_custom_value=True
29
- )
30
- with gr.Column(scale=1):
31
- components[f'run_{prefix}'] = gr.Button("Run", variant="primary")
32
-
33
- components[f'prompt_{prefix}'] = gr.Text(label="Prompt", lines=3)
34
- components[f'neg_prompt_{prefix}'] = gr.Text(label="Negative prompt", lines=3)
35
-
36
- with gr.Row():
37
- with gr.Column(scale=1):
38
- param_defaults = {'w': 1024, 'h': 1024, 'cs_vis': False, 'cs_val': 1}
39
- components.update(create_base_parameter_ui(prefix, param_defaults))
40
- with gr.Column(scale=1):
41
- components[f'result_{prefix}'] = gr.Gallery(label="Result", show_label=False, columns=2, object_fit="contain", height=627)
42
-
43
-
44
- components.update(create_lora_settings_ui(prefix))
45
- components.update(create_controlnet_ui(prefix))
46
- components.update(create_anima_controlnet_lllite_ui(prefix))
47
- components.update(create_diffsynth_controlnet_ui(prefix))
48
- components.update(create_krea2_controlnet_ui(prefix))
49
- components.update(create_ipadapter_ui(prefix))
50
- components.update(create_flux1_ipadapter_ui(prefix))
51
- components.update(create_sd3_ipadapter_ui(prefix))
52
- components.update(create_embedding_ui(prefix))
53
- components.update(create_style_ui(prefix))
54
- components.update(create_conditioning_ui(prefix))
55
- components.update(create_reference_latent_ui(prefix))
56
- components.update(create_hidream_o1_reference_ui(prefix))
57
- components.update(create_joyai_reference_ui(prefix))
58
- components.update(create_krea2_identity_edit_ui(prefix))
59
- components.update(create_krea2_reference_edit_ui(prefix))
60
- components.update(create_qwen_image_edit_ui(prefix))
61
- components.update(create_boogu_edit_ui(prefix))
62
- components.update(create_reference_image_ui(prefix))
63
- components.update(create_vae_override_ui(prefix))
64
- components.update(create_pid_ui(prefix))
65
-
66
- return components
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui/shared/ui_components.py CHANGED
@@ -114,8 +114,7 @@ def create_base_parameter_ui(prefix, defaults=None):
114
  components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
115
  components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
116
  with gr.Row():
117
- components[f'guidance_{prefix}'] = gr.Slider(label="Guidance (FLUX)", minimum=1.0, maximum=10.0, step=0.1, value=3.5, visible=False, interactive=True)
118
- components[f'zero_gpu_{prefix}'] = gr.Number(label="ZeroGPU Duration (s)", value=None, placeholder="Default: 60s, Max: 120s", info="Optional: Set how long to reserve the GPU.")
119
 
120
  return components
121
 
 
114
  components[f'seed_{prefix}'] = gr.Number(label="Seed (-1 for random)", value=-1, precision=0)
115
  components[f'batch_size_{prefix}'] = gr.Slider(label="Batch Size", minimum=1, maximum=16, step=1, value=1)
116
  with gr.Row():
117
+ components[f'zero_gpu_{prefix}'] = gr.Number(label="ZeroGPU Duration (s)", value=60, placeholder="Default: 60s, Max: 120s", info="Optional: Set how long to reserve the GPU.")
 
118
 
119
  return components
120
 
yaml/chain_features.yaml CHANGED
@@ -5,12 +5,6 @@ lora:
5
  chains: lora
6
  display_name: "LoRA Fine-tuning Injector"
7
  description: "Injects LoRA weights into UNet/DiT model and CLIP text encoder for custom style, character, or domain adaptation. Note: For Civitai, specify the Version ID (modelVersionId) instead of the main Model ID."
8
- supported_tasks:
9
- - txt2img
10
- - img2img
11
- - inpaint
12
- - outpaint
13
- - hires_fix
14
  max_count: 5
15
  usage_guideline: "Specify source ('Civitai' or 'Hugging Face'). For Civitai, provide lora_value as the Version ID (modelVersionId). For Hugging Face, provide HF repo file path. Scale (0.0~2.0) controls weight strength."
16
  parameters_schema:
@@ -37,12 +31,6 @@ ipadapter:
37
  chains: ipadapter
38
  display_name: "IP-Adapter Image Prompt"
39
  description: "Uses reference images to guide generation style, composition, structure, or face appearance without prompt text restrictions (SD1.5 & SDXL)."
40
- supported_tasks:
41
- - txt2img
42
- - img2img
43
- - inpaint
44
- - outpaint
45
- - hires_fix
46
  max_count: 5
47
  usage_guideline: "Supply global settings (preset, embeds_scaling, combine_method, final_weight) and up to 5 reference images with individual weights. Preset must match the target model architecture (SD1.5 or SDXL)."
48
  parameters_schema:
@@ -99,12 +87,6 @@ controlnet:
99
  chains: controlnet
100
  display_name: "ControlNet Spatial Guidance"
101
  description: "Applies structural and spatial conditioning (depth, pose, lineart, tile, scribble, canny) to guide output composition."
102
- supported_tasks:
103
- - txt2img
104
- - img2img
105
- - inpaint
106
- - outpaint
107
- - hires_fix
108
  max_count: 5
109
  usage_guideline: "Specify ControlNet type and series (must match requested model architecture e.g., SD1.5, SDXL, SD3.5, FLUX.1, Qwen-Image), pre-processed control image (Base64 Data URI or HTTP/HTTPS URL; system does NOT pre-process raw RGB images), and guidance strength."
110
  parameters_schema:
@@ -134,12 +116,6 @@ conditioning:
134
  chains: conditioning
135
  display_name: "Regional Conditioning / Area Prompt"
136
  description: "Defines rectangular areas (X, Y, Width, Height) and assigns specific text prompts and conditioning strengths to them."
137
- supported_tasks:
138
- - txt2img
139
- - img2img
140
- - inpaint
141
- - outpaint
142
- - hires_fix
143
  max_count: 10
144
  usage_guideline: "Define rectangular spatial areas (X, Y, width, height) and assign specific prompts and strengths to them. Supports up to 10 area prompts."
145
  parameters_schema:
@@ -177,12 +153,6 @@ vae:
177
  chains: vae
178
  display_name: "Custom VAE Loader"
179
  description: "Overrides default VAE model used for latent space encoding and final image decoding."
180
- supported_tasks:
181
- - txt2img
182
- - img2img
183
- - inpaint
184
- - outpaint
185
- - hires_fix
186
  max_count: 1
187
  usage_guideline: "Specify source ('Civitai' or 'Hugging Face'), then provide the vae_value (Civitai Version ID or HF file path)."
188
  parameters_schema:
@@ -203,8 +173,6 @@ pid:
203
  chains: pid
204
  display_name: "PiD High-Resolution Refinement"
205
  description: "Progressive Detail (PiD) upscale injector for fine detail enhancement and resolution upscaling."
206
- supported_tasks:
207
- - txt2img
208
  max_count: 1
209
  usage_guideline: "Enables PiD detail refinement pipeline using a boolean switch ('enabled': true/false)."
210
  parameters_schema:
@@ -221,12 +189,6 @@ flux1_style:
221
  chains: style
222
  display_name: "FLUX.1 Style Reference"
223
  description: "Applies artistic style conditioning from reference images onto FLUX.1 model generated outputs."
224
- supported_tasks:
225
- - txt2img
226
- - img2img
227
- - inpaint
228
- - outpaint
229
- - hires_fix
230
  max_count: 5
231
  usage_guideline: "Supply style reference image(s) (up to 5) encoded as Base64 Data URI or HTTP/HTTPS URL and optional strength."
232
  parameters_schema:
@@ -248,12 +210,6 @@ reference_edit:
248
  chains: reference_latent
249
  display_name: "Reference Edit"
250
  description: "For multimodal models, this feature enables powerful editing and combining capabilities. In txt2img mode, adding a single reference image performs an Image Edit, while adding multiple images performs an Image Combine."
251
- supported_tasks:
252
- - txt2img
253
- - img2img
254
- - inpaint
255
- - outpaint
256
- - hires_fix
257
  max_count: 10
258
  usage_guideline: "Supply reference image(s) encoded as Base64 Data URI or HTTP/HTTPS URL. Passing a single reference image performs an Image Edit, while passing multiple images (up to 10) performs an Image Combine."
259
  parameters_schema:
@@ -269,12 +225,6 @@ mage_flow_reference_edit:
269
  chains: reference_image
270
  display_name: "Mage-Flow Reference Edit"
271
  description: " (Mage-Flow-Edit-Turbo/Mage-Flow-Edit recommended) For multimodal models, this feature enables powerful editing and combining capabilities. In txt2img mode, adding a single reference image performs an Image Edit, while adding multiple images performs an Image Combine."
272
- supported_tasks:
273
- - txt2img
274
- - img2img
275
- - inpaint
276
- - outpaint
277
- - hires_fix
278
  max_count: 10
279
  usage_guideline: "Supply reference image as Base64 Data URI or HTTP/HTTPS URL."
280
  parameters_schema:
@@ -290,12 +240,6 @@ krea2_identity_edit:
290
  chains: krea2_identity_edit
291
  display_name: "KREA2 Identity Edit"
292
  description: "Processed using the lbouaraba/comfyui-krea2edit node. (Krea-2-Turbo recommended, Krea-2-Raw need set ZeroGPU Duration (s) to 120 ) In txt2img mode, adding a single reference image performs an Image Edit, while adding multiple images performs an Image Combine."
293
- supported_tasks:
294
- - txt2img
295
- - img2img
296
- - inpaint
297
- - outpaint
298
- - hires_fix
299
  max_count: 2
300
  usage_guideline: "Supply reference image as Base64 Data URI or HTTP/HTTPS URL."
301
  parameters_schema:
@@ -311,12 +255,6 @@ krea2_style_reference:
311
  chains: krea2_style_reference
312
  display_name: "KREA2 Style Reference"
313
  description: "(Krea-2-Turbo recommended) Add style reference images to perform style reference editing."
314
- supported_tasks:
315
- - txt2img
316
- - img2img
317
- - inpaint
318
- - outpaint
319
- - hires_fix
320
  max_count: 3
321
  usage_guideline: "Supply style reference image as Base64 Data URI or HTTP/HTTPS URL."
322
  parameters_schema:
@@ -332,12 +270,6 @@ diffsynth_controlnet:
332
  chains: diffsynth_controlnet
333
  display_name: "DiffSynth ControlNet"
334
  description: "DiffSynth optimized ControlNet injector for Z-Image models."
335
- supported_tasks:
336
- - txt2img
337
- - img2img
338
- - inpaint
339
- - outpaint
340
- - hires_fix
341
  max_count: 5
342
  usage_guideline: "Supply ControlNet type (e.g., 'Canny'), series (e.g., 'alibaba-pai Controlnet Union 2.1 8steps'), pre-processed control image (Base64 Data URI or HTTP/HTTPS URL; system does NOT pre-process raw RGB images), and optional strength."
343
  parameters_schema:
@@ -365,12 +297,6 @@ boogu_image_edit:
365
  chains: boogu_image_edit
366
  display_name: "Boogu-Image Edit"
367
  description: " (Boogu-Image-Edit-Turbo/Boogu-Image-Edit recommended, Boogu-Image-Edit need set ZeroGPU Duration (s) to 120 ) In txt2img mode, adding a single reference image performs an Image Edit, while adding multiple images performs an Image Combine."
368
- supported_tasks:
369
- - txt2img
370
- - img2img
371
- - inpaint
372
- - outpaint
373
- - hires_fix
374
  max_count: 2
375
  usage_guideline: "Supply reference image as Base64 Data URI or HTTP/HTTPS URL."
376
  parameters_schema:
@@ -386,12 +312,6 @@ joyai_reference_edit:
386
  chains: joyai_image
387
  display_name: "JoyAI Reference Edit"
388
  description: " (JoyAI-Image-Edit recommended) For multimodal models, this feature enables powerful editing and combining capabilities. In txt2img mode, adding a single reference image performs an Image Edit (JoyAI-Image-Edit recommended), while adding multiple images performs an Image Combine (JoyAI-Image-Edit-Plus recommended with ZeroGPU Duration (s) set to 120)."
389
- supported_tasks:
390
- - txt2img
391
- - img2img
392
- - inpaint
393
- - outpaint
394
- - hires_fix
395
  max_count: 2
396
  usage_guideline: "Supply JoyAI reference image as Base64 Data URI or HTTP/HTTPS URL."
397
  parameters_schema:
@@ -407,12 +327,6 @@ qwen_image_edit:
407
  chains: qwen_image_edit
408
  display_name: "Qwen-Image Edit"
409
  description: " (lightx2v/Qwen-Image-Edit-2511-Lightning recommended) In txt2img mode, adding a single reference image performs an Image Edit, while adding multiple images performs an Image Combine."
410
- supported_tasks:
411
- - txt2img
412
- - img2img
413
- - inpaint
414
- - outpaint
415
- - hires_fix
416
  max_count: 3
417
  usage_guideline: "Supply reference image(s) (up to 3) encoded as Base64 Data URI or HTTP/HTTPS URL. Passing a single reference image performs an Image Edit, while passing multiple images performs an Image Combine."
418
  parameters_schema:
@@ -428,12 +342,6 @@ hidream_o1_smoothing:
428
  chains: hidream_o1_smoothing
429
  display_name: "HiDream O1 Smoothing Injector"
430
  description: "HiDream O1 detail smoothing and artifact reduction injector."
431
- supported_tasks:
432
- - txt2img
433
- - img2img
434
- - inpaint
435
- - outpaint
436
- - hires_fix
437
  max_count: 1
438
  usage_guideline: "Configures smoothing factor for HiDream models."
439
  parameters_schema:
@@ -449,12 +357,6 @@ krea2_controlnet:
449
  chains: krea2_controlnet
450
  display_name: "KREA2 ControlNet"
451
  description: "Processed using the facok/comfyui-krea2-controlnet node."
452
- supported_tasks:
453
- - txt2img
454
- - img2img
455
- - inpaint
456
- - outpaint
457
- - hires_fix
458
  max_count: 5
459
  usage_guideline: "Supply ControlNet type (e.g., 'Depth'), series (e.g., 'Patil'), pre-processed control image (Base64 Data URI or HTTP/HTTPS URL; system does NOT pre-process raw RGB images), and optional strength."
460
  parameters_schema:
@@ -489,12 +391,6 @@ anima_controlnet_lllite:
489
  chains: anima_controlnet_lllite
490
  display_name: "Anima ControlNet LLLite"
491
  description: "Anima model-specific lightweight ControlNet."
492
- supported_tasks:
493
- - txt2img
494
- - img2img
495
- - inpaint
496
- - outpaint
497
- - hires_fix
498
  max_count: 5
499
  usage_guideline: "Supply Anima ControlNet LLLite type (e.g., 'Depth'), series (e.g., 'kohya-ss'), pre-processed control image (Base64 Data URI or HTTP/HTTPS URL; system does NOT pre-process raw RGB images), and optional strength."
500
  parameters_schema:
@@ -524,12 +420,6 @@ hidream_o1_reference:
524
  chains: hidream_o1_reference
525
  display_name: "HiDream-O1 Reference Edit"
526
  description: " (HiDream-O1-Image-Dev recommended with resolution set to 4.0MP, e.g., 2048x2048) For HiDream-O1 models, this feature enables reference image editing and combining capabilities. In txt2img mode, adding a single reference image performs an Image Edit, while adding multiple images performs an Image Combine."
527
- supported_tasks:
528
- - txt2img
529
- - img2img
530
- - inpaint
531
- - outpaint
532
- - hires_fix
533
  max_count: 9
534
  usage_guideline: "Supply reference image(s) (up to 9) encoded as Base64 Data URI or HTTP/HTTPS URL. Passing a single reference image performs an Image Edit, while passing multiple images performs an Image Combine."
535
  parameters_schema:
@@ -545,12 +435,6 @@ flux1_ipadapter:
545
  chains: flux1_ipadapter
546
  display_name: "Flux1 IP-Adapter"
547
  description: "FLUX.1 model-specific IP-Adapter implementation."
548
- supported_tasks:
549
- - txt2img
550
- - img2img
551
- - inpaint
552
- - outpaint
553
- - hires_fix
554
  max_count: 5
555
  usage_guideline: "Supply reference image (Base64 Data URI or HTTP/HTTPS URL), optional weight (default 1.0), start_at (default 0.0), and end_at (default 1.0). Up to 5 images supported."
556
  parameters_schema:
@@ -586,12 +470,6 @@ sd3_ipadapter:
586
  chains: sd3_ipadapter
587
  display_name: "SD3 IP-Adapter"
588
  description: "SD3/SD3.5 model-specific IP-Adapter implementation."
589
- supported_tasks:
590
- - txt2img
591
- - img2img
592
- - inpaint
593
- - outpaint
594
- - hires_fix
595
  max_count: 5
596
  usage_guideline: "Supply reference image (Base64 Data URI or HTTP/HTTPS URL), optional weight (default 1.0), start_at (default 0.0), and end_at (default 1.0). Up to 5 images supported."
597
  parameters_schema:
@@ -627,12 +505,6 @@ embedding:
627
  chains: embedding
628
  display_name: "Textual Inversion Embedding Injector"
629
  description: "Downloads Textual Inversion embedding files from Civitai or Hugging Face to the server. Note: This feature ONLY handles file downloading/preparation. To activate the embedding, manually add 'embedding:<filename>' (e.g. 'embedding:civitai_456' for Civitai ID 456, or 'embedding:filename' for Hugging Face) into your prompt or negative_prompt."
630
- supported_tasks:
631
- - txt2img
632
- - img2img
633
- - inpaint
634
- - outpaint
635
- - hires_fix
636
  max_count: 5
637
  usage_guideline: "Specify source ('Civitai' or 'Hugging Face'), and embedding_value (Civitai Version ID or HF repo file path). The file is downloaded to server; manually enter 'embedding:<filename>' in prompt or negative_prompt to activate."
638
  parameters_schema:
 
5
  chains: lora
6
  display_name: "LoRA Fine-tuning Injector"
7
  description: "Injects LoRA weights into UNet/DiT model and CLIP text encoder for custom style, character, or domain adaptation. Note: For Civitai, specify the Version ID (modelVersionId) instead of the main Model ID."
 
 
 
 
 
 
8
  max_count: 5
9
  usage_guideline: "Specify source ('Civitai' or 'Hugging Face'). For Civitai, provide lora_value as the Version ID (modelVersionId). For Hugging Face, provide HF repo file path. Scale (0.0~2.0) controls weight strength."
10
  parameters_schema:
 
31
  chains: ipadapter
32
  display_name: "IP-Adapter Image Prompt"
33
  description: "Uses reference images to guide generation style, composition, structure, or face appearance without prompt text restrictions (SD1.5 & SDXL)."
 
 
 
 
 
 
34
  max_count: 5
35
  usage_guideline: "Supply global settings (preset, embeds_scaling, combine_method, final_weight) and up to 5 reference images with individual weights. Preset must match the target model architecture (SD1.5 or SDXL)."
36
  parameters_schema:
 
87
  chains: controlnet
88
  display_name: "ControlNet Spatial Guidance"
89
  description: "Applies structural and spatial conditioning (depth, pose, lineart, tile, scribble, canny) to guide output composition."
 
 
 
 
 
 
90
  max_count: 5
91
  usage_guideline: "Specify ControlNet type and series (must match requested model architecture e.g., SD1.5, SDXL, SD3.5, FLUX.1, Qwen-Image), pre-processed control image (Base64 Data URI or HTTP/HTTPS URL; system does NOT pre-process raw RGB images), and guidance strength."
92
  parameters_schema:
 
116
  chains: conditioning
117
  display_name: "Regional Conditioning / Area Prompt"
118
  description: "Defines rectangular areas (X, Y, Width, Height) and assigns specific text prompts and conditioning strengths to them."
 
 
 
 
 
 
119
  max_count: 10
120
  usage_guideline: "Define rectangular spatial areas (X, Y, width, height) and assign specific prompts and strengths to them. Supports up to 10 area prompts."
121
  parameters_schema:
 
153
  chains: vae
154
  display_name: "Custom VAE Loader"
155
  description: "Overrides default VAE model used for latent space encoding and final image decoding."
 
 
 
 
 
 
156
  max_count: 1
157
  usage_guideline: "Specify source ('Civitai' or 'Hugging Face'), then provide the vae_value (Civitai Version ID or HF file path)."
158
  parameters_schema:
 
173
  chains: pid
174
  display_name: "PiD High-Resolution Refinement"
175
  description: "Progressive Detail (PiD) upscale injector for fine detail enhancement and resolution upscaling."
 
 
176
  max_count: 1
177
  usage_guideline: "Enables PiD detail refinement pipeline using a boolean switch ('enabled': true/false)."
178
  parameters_schema:
 
189
  chains: style
190
  display_name: "FLUX.1 Style Reference"
191
  description: "Applies artistic style conditioning from reference images onto FLUX.1 model generated outputs."
 
 
 
 
 
 
192
  max_count: 5
193
  usage_guideline: "Supply style reference image(s) (up to 5) encoded as Base64 Data URI or HTTP/HTTPS URL and optional strength."
194
  parameters_schema:
 
210
  chains: reference_latent
211
  display_name: "Reference Edit"
212
  description: "For multimodal models, this feature enables powerful editing and combining capabilities. In txt2img mode, adding a single reference image performs an Image Edit, while adding multiple images performs an Image Combine."
 
 
 
 
 
 
213
  max_count: 10
214
  usage_guideline: "Supply reference image(s) encoded as Base64 Data URI or HTTP/HTTPS URL. Passing a single reference image performs an Image Edit, while passing multiple images (up to 10) performs an Image Combine."
215
  parameters_schema:
 
225
  chains: reference_image
226
  display_name: "Mage-Flow Reference Edit"
227
  description: " (Mage-Flow-Edit-Turbo/Mage-Flow-Edit recommended) For multimodal models, this feature enables powerful editing and combining capabilities. In txt2img mode, adding a single reference image performs an Image Edit, while adding multiple images performs an Image Combine."
 
 
 
 
 
 
228
  max_count: 10
229
  usage_guideline: "Supply reference image as Base64 Data URI or HTTP/HTTPS URL."
230
  parameters_schema:
 
240
  chains: krea2_identity_edit
241
  display_name: "KREA2 Identity Edit"
242
  description: "Processed using the lbouaraba/comfyui-krea2edit node. (Krea-2-Turbo recommended, Krea-2-Raw need set ZeroGPU Duration (s) to 120 ) In txt2img mode, adding a single reference image performs an Image Edit, while adding multiple images performs an Image Combine."
 
 
 
 
 
 
243
  max_count: 2
244
  usage_guideline: "Supply reference image as Base64 Data URI or HTTP/HTTPS URL."
245
  parameters_schema:
 
255
  chains: krea2_style_reference
256
  display_name: "KREA2 Style Reference"
257
  description: "(Krea-2-Turbo recommended) Add style reference images to perform style reference editing."
 
 
 
 
 
 
258
  max_count: 3
259
  usage_guideline: "Supply style reference image as Base64 Data URI or HTTP/HTTPS URL."
260
  parameters_schema:
 
270
  chains: diffsynth_controlnet
271
  display_name: "DiffSynth ControlNet"
272
  description: "DiffSynth optimized ControlNet injector for Z-Image models."
 
 
 
 
 
 
273
  max_count: 5
274
  usage_guideline: "Supply ControlNet type (e.g., 'Canny'), series (e.g., 'alibaba-pai Controlnet Union 2.1 8steps'), pre-processed control image (Base64 Data URI or HTTP/HTTPS URL; system does NOT pre-process raw RGB images), and optional strength."
275
  parameters_schema:
 
297
  chains: boogu_image_edit
298
  display_name: "Boogu-Image Edit"
299
  description: " (Boogu-Image-Edit-Turbo/Boogu-Image-Edit recommended, Boogu-Image-Edit need set ZeroGPU Duration (s) to 120 ) In txt2img mode, adding a single reference image performs an Image Edit, while adding multiple images performs an Image Combine."
 
 
 
 
 
 
300
  max_count: 2
301
  usage_guideline: "Supply reference image as Base64 Data URI or HTTP/HTTPS URL."
302
  parameters_schema:
 
312
  chains: joyai_image
313
  display_name: "JoyAI Reference Edit"
314
  description: " (JoyAI-Image-Edit recommended) For multimodal models, this feature enables powerful editing and combining capabilities. In txt2img mode, adding a single reference image performs an Image Edit (JoyAI-Image-Edit recommended), while adding multiple images performs an Image Combine (JoyAI-Image-Edit-Plus recommended with ZeroGPU Duration (s) set to 120)."
 
 
 
 
 
 
315
  max_count: 2
316
  usage_guideline: "Supply JoyAI reference image as Base64 Data URI or HTTP/HTTPS URL."
317
  parameters_schema:
 
327
  chains: qwen_image_edit
328
  display_name: "Qwen-Image Edit"
329
  description: " (lightx2v/Qwen-Image-Edit-2511-Lightning recommended) In txt2img mode, adding a single reference image performs an Image Edit, while adding multiple images performs an Image Combine."
 
 
 
 
 
 
330
  max_count: 3
331
  usage_guideline: "Supply reference image(s) (up to 3) encoded as Base64 Data URI or HTTP/HTTPS URL. Passing a single reference image performs an Image Edit, while passing multiple images performs an Image Combine."
332
  parameters_schema:
 
342
  chains: hidream_o1_smoothing
343
  display_name: "HiDream O1 Smoothing Injector"
344
  description: "HiDream O1 detail smoothing and artifact reduction injector."
 
 
 
 
 
 
345
  max_count: 1
346
  usage_guideline: "Configures smoothing factor for HiDream models."
347
  parameters_schema:
 
357
  chains: krea2_controlnet
358
  display_name: "KREA2 ControlNet"
359
  description: "Processed using the facok/comfyui-krea2-controlnet node."
 
 
 
 
 
 
360
  max_count: 5
361
  usage_guideline: "Supply ControlNet type (e.g., 'Depth'), series (e.g., 'Patil'), pre-processed control image (Base64 Data URI or HTTP/HTTPS URL; system does NOT pre-process raw RGB images), and optional strength."
362
  parameters_schema:
 
391
  chains: anima_controlnet_lllite
392
  display_name: "Anima ControlNet LLLite"
393
  description: "Anima model-specific lightweight ControlNet."
 
 
 
 
 
 
394
  max_count: 5
395
  usage_guideline: "Supply Anima ControlNet LLLite type (e.g., 'Depth'), series (e.g., 'kohya-ss'), pre-processed control image (Base64 Data URI or HTTP/HTTPS URL; system does NOT pre-process raw RGB images), and optional strength."
396
  parameters_schema:
 
420
  chains: hidream_o1_reference
421
  display_name: "HiDream-O1 Reference Edit"
422
  description: " (HiDream-O1-Image-Dev recommended with resolution set to 4.0MP, e.g., 2048x2048) For HiDream-O1 models, this feature enables reference image editing and combining capabilities. In txt2img mode, adding a single reference image performs an Image Edit, while adding multiple images performs an Image Combine."
 
 
 
 
 
 
423
  max_count: 9
424
  usage_guideline: "Supply reference image(s) (up to 9) encoded as Base64 Data URI or HTTP/HTTPS URL. Passing a single reference image performs an Image Edit, while passing multiple images performs an Image Combine."
425
  parameters_schema:
 
435
  chains: flux1_ipadapter
436
  display_name: "Flux1 IP-Adapter"
437
  description: "FLUX.1 model-specific IP-Adapter implementation."
 
 
 
 
 
 
438
  max_count: 5
439
  usage_guideline: "Supply reference image (Base64 Data URI or HTTP/HTTPS URL), optional weight (default 1.0), start_at (default 0.0), and end_at (default 1.0). Up to 5 images supported."
440
  parameters_schema:
 
470
  chains: sd3_ipadapter
471
  display_name: "SD3 IP-Adapter"
472
  description: "SD3/SD3.5 model-specific IP-Adapter implementation."
 
 
 
 
 
 
473
  max_count: 5
474
  usage_guideline: "Supply reference image (Base64 Data URI or HTTP/HTTPS URL), optional weight (default 1.0), start_at (default 0.0), and end_at (default 1.0). Up to 5 images supported."
475
  parameters_schema:
 
505
  chains: embedding
506
  display_name: "Textual Inversion Embedding Injector"
507
  description: "Downloads Textual Inversion embedding files from Civitai or Hugging Face to the server. Note: This feature ONLY handles file downloading/preparation. To activate the embedding, manually add 'embedding:<filename>' (e.g. 'embedding:civitai_456' for Civitai ID 456, or 'embedding:filename' for Hugging Face) into your prompt or negative_prompt."
 
 
 
 
 
 
508
  max_count: 5
509
  usage_guideline: "Specify source ('Civitai' or 'Hugging Face'), and embedding_value (Civitai Version ID or HF repo file path). The file is downloaded to server; manually enter 'embedding:<filename>' in prompt or negative_prompt to activate."
510
  parameters_schema:
yaml/{image_gen_features.yaml → model_architecture_features.yaml} RENAMED
@@ -1,200 +1,200 @@
1
- # Feature names in enabled_chains correspond 1-to-1 with chain_injectors/<name>_injector.py
2
- krea-2:
3
- enabled_chains:
4
- - lora
5
- - krea2_controlnet
6
- - krea2_identity_edit
7
- - krea2_style_reference
8
- - pid
9
-
10
- mage-flow:
11
- enabled_chains:
12
- - reference_image
13
-
14
- joyai-image:
15
- enabled_chains:
16
- - joyai_image
17
-
18
- boogu-image:
19
- enabled_chains:
20
- - lora
21
- - boogu_image_edit
22
- - pid
23
-
24
- pixeldit:
25
- enabled_chains:
26
- - conditioning
27
-
28
- ideogram-4:
29
- enabled_chains:
30
- - vae
31
- - pid
32
-
33
- lens:
34
- enabled_chains:
35
- - conditioning
36
- - pid
37
-
38
- flux2-kv:
39
- enabled_chains:
40
- - lora
41
- - reference_latent
42
- - conditioning
43
- - vae
44
- - pid
45
-
46
- flux2:
47
- enabled_chains:
48
- - lora
49
- - reference_latent
50
- - conditioning
51
- - vae
52
- - pid
53
-
54
- ernie-image:
55
- enabled_chains:
56
- - conditioning
57
- - pid
58
-
59
- z-image:
60
- enabled_chains:
61
- - lora
62
- - diffsynth_controlnet
63
- - conditioning
64
- - vae
65
- - pid
66
-
67
- qwen-image:
68
- enabled_chains:
69
- - lora
70
- - conditioning
71
- - controlnet
72
- - qwen_image_edit
73
- - vae
74
- - pid
75
-
76
- longcat-image:
77
- enabled_chains:
78
- - lora
79
- - conditioning
80
- - pid
81
-
82
- cosmos-predict2:
83
- enabled_chains:
84
- - conditioning
85
- - vae
86
-
87
- anima:
88
- enabled_chains:
89
- - lora
90
- - conditioning
91
- - anima_controlnet_lllite
92
- - vae
93
- - pid
94
-
95
- newbie-image:
96
- enabled_chains:
97
- - lora
98
- - embedding
99
- - conditioning
100
- - vae
101
- - pid
102
-
103
- kandinsky-5:
104
- enabled_chains:
105
- - conditioning
106
- - vae
107
- - pid
108
-
109
- ovis-image:
110
- enabled_chains:
111
- - conditioning
112
- - vae
113
- - pid
114
-
115
- hunyuanimage:
116
- enabled_chains:
117
- - conditioning
118
- - vae
119
-
120
- chroma1-radiance:
121
- enabled_chains:
122
- - conditioning
123
-
124
- chroma1:
125
- enabled_chains:
126
- - conditioning
127
- - vae
128
- - pid
129
-
130
- omnigen2:
131
- enabled_chains:
132
- - reference_latent
133
- - conditioning
134
- - pid
135
-
136
- lumina:
137
- enabled_chains:
138
- - lora
139
- - embedding
140
- - conditioning
141
- - vae
142
- - pid
143
-
144
- hidream-o1:
145
- enabled_chains:
146
- - lora
147
- - conditioning
148
- - hidream_o1_smoothing
149
- - hidream_o1_reference
150
-
151
- hidream-i1:
152
- enabled_chains:
153
- - lora
154
- - conditioning
155
- - pid
156
-
157
- flux1:
158
- enabled_chains:
159
- - lora
160
- - flux1_ipadapter
161
- - conditioning
162
- - style
163
- - controlnet
164
- - vae
165
- - pid
166
-
167
- auraflow:
168
- enabled_chains:
169
- - lora
170
- - conditioning
171
- - vae
172
-
173
- sd35:
174
- enabled_chains:
175
- - lora
176
- - sd3_ipadapter
177
- - embedding
178
- - conditioning
179
- - controlnet
180
- - vae
181
- - pid
182
-
183
- sdxl:
184
- enabled_chains:
185
- - lora
186
- - ipadapter
187
- - embedding
188
- - conditioning
189
- - controlnet
190
- - vae
191
- - pid
192
-
193
- sd15:
194
- enabled_chains:
195
- - lora
196
- - ipadapter
197
- - embedding
198
- - conditioning
199
- - controlnet
200
  - vae
 
1
+ # Feature names in enabled_chains correspond 1-to-1 with chain_injectors/<name>_injector.py
2
+ krea-2:
3
+ enabled_chains:
4
+ - lora
5
+ - krea2_controlnet
6
+ - krea2_identity_edit
7
+ - krea2_style_reference
8
+ - pid
9
+
10
+ mage-flow:
11
+ enabled_chains:
12
+ - reference_image
13
+
14
+ joyai-image:
15
+ enabled_chains:
16
+ - joyai_image
17
+
18
+ boogu-image:
19
+ enabled_chains:
20
+ - lora
21
+ - boogu_image_edit
22
+ - pid
23
+
24
+ pixeldit:
25
+ enabled_chains:
26
+ - conditioning
27
+
28
+ ideogram-4:
29
+ enabled_chains:
30
+ - vae
31
+ - pid
32
+
33
+ lens:
34
+ enabled_chains:
35
+ - conditioning
36
+ - pid
37
+
38
+ flux2-kv:
39
+ enabled_chains:
40
+ - lora
41
+ - reference_latent
42
+ - conditioning
43
+ - vae
44
+ - pid
45
+
46
+ flux2:
47
+ enabled_chains:
48
+ - lora
49
+ - reference_latent
50
+ - conditioning
51
+ - vae
52
+ - pid
53
+
54
+ ernie-image:
55
+ enabled_chains:
56
+ - conditioning
57
+ - pid
58
+
59
+ z-image:
60
+ enabled_chains:
61
+ - lora
62
+ - diffsynth_controlnet
63
+ - conditioning
64
+ - vae
65
+ - pid
66
+
67
+ qwen-image:
68
+ enabled_chains:
69
+ - lora
70
+ - conditioning
71
+ - controlnet
72
+ - qwen_image_edit
73
+ - vae
74
+ - pid
75
+
76
+ longcat-image:
77
+ enabled_chains:
78
+ - lora
79
+ - conditioning
80
+ - pid
81
+
82
+ cosmos-predict2:
83
+ enabled_chains:
84
+ - conditioning
85
+ - vae
86
+
87
+ anima:
88
+ enabled_chains:
89
+ - lora
90
+ - conditioning
91
+ - anima_controlnet_lllite
92
+ - vae
93
+ - pid
94
+
95
+ newbie-image:
96
+ enabled_chains:
97
+ - lora
98
+ - embedding
99
+ - conditioning
100
+ - vae
101
+ - pid
102
+
103
+ kandinsky-5:
104
+ enabled_chains:
105
+ - conditioning
106
+ - vae
107
+ - pid
108
+
109
+ ovis-image:
110
+ enabled_chains:
111
+ - conditioning
112
+ - vae
113
+ - pid
114
+
115
+ hunyuanimage:
116
+ enabled_chains:
117
+ - conditioning
118
+ - vae
119
+
120
+ chroma1-radiance:
121
+ enabled_chains:
122
+ - conditioning
123
+
124
+ chroma1:
125
+ enabled_chains:
126
+ - conditioning
127
+ - vae
128
+ - pid
129
+
130
+ omnigen2:
131
+ enabled_chains:
132
+ - reference_latent
133
+ - conditioning
134
+ - pid
135
+
136
+ lumina:
137
+ enabled_chains:
138
+ - lora
139
+ - embedding
140
+ - conditioning
141
+ - vae
142
+ - pid
143
+
144
+ hidream-o1:
145
+ enabled_chains:
146
+ - lora
147
+ - conditioning
148
+ - hidream_o1_smoothing
149
+ - hidream_o1_reference
150
+
151
+ hidream-i1:
152
+ enabled_chains:
153
+ - lora
154
+ - conditioning
155
+ - pid
156
+
157
+ flux1:
158
+ enabled_chains:
159
+ - lora
160
+ - flux1_ipadapter
161
+ - conditioning
162
+ - style
163
+ - controlnet
164
+ - vae
165
+ - pid
166
+
167
+ auraflow:
168
+ enabled_chains:
169
+ - lora
170
+ - conditioning
171
+ - vae
172
+
173
+ sd35:
174
+ enabled_chains:
175
+ - lora
176
+ - sd3_ipadapter
177
+ - embedding
178
+ - conditioning
179
+ - controlnet
180
+ - vae
181
+ - pid
182
+
183
+ sdxl:
184
+ enabled_chains:
185
+ - lora
186
+ - ipadapter
187
+ - embedding
188
+ - conditioning
189
+ - controlnet
190
+ - vae
191
+ - pid
192
+
193
+ sd15:
194
+ enabled_chains:
195
+ - lora
196
+ - ipadapter
197
+ - embedding
198
+ - conditioning
199
+ - controlnet
200
  - vae
yaml/task_features.yaml ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Task-level feature support configuration
2
+ # Defines which chains (features) are available for each task type.
3
+ # A feature is visible in the UI only when BOTH the task AND the model architecture support it.
4
+ # pid only supports txt2img; all other features support all 5 tasks.
5
+
6
+ txt2img:
7
+ enabled_chains:
8
+ - lora
9
+ - controlnet
10
+ - anima_controlnet_lllite
11
+ - diffsynth_controlnet
12
+ - krea2_controlnet
13
+ - ipadapter
14
+ - flux1_ipadapter
15
+ - sd3_ipadapter
16
+ - style
17
+ - embedding
18
+ - conditioning
19
+ - reference_latent
20
+ - hidream_o1_reference
21
+ - hidream_o1_smoothing
22
+ - joyai_image
23
+ - krea2_identity_edit
24
+ - krea2_style_reference
25
+ - qwen_image_edit
26
+ - boogu_image_edit
27
+ - reference_image
28
+ - pid
29
+ - vae
30
+
31
+ img2img:
32
+ enabled_chains:
33
+ - lora
34
+ - controlnet
35
+ - anima_controlnet_lllite
36
+ - diffsynth_controlnet
37
+ - krea2_controlnet
38
+ - ipadapter
39
+ - flux1_ipadapter
40
+ - sd3_ipadapter
41
+ - style
42
+ - embedding
43
+ - conditioning
44
+ - reference_latent
45
+ - hidream_o1_reference
46
+ - hidream_o1_smoothing
47
+ - joyai_image
48
+ - krea2_identity_edit
49
+ - krea2_style_reference
50
+ - qwen_image_edit
51
+ - boogu_image_edit
52
+ - reference_image
53
+ - vae
54
+
55
+ inpaint:
56
+ enabled_chains:
57
+ - lora
58
+ - controlnet
59
+ - anima_controlnet_lllite
60
+ - diffsynth_controlnet
61
+ - krea2_controlnet
62
+ - ipadapter
63
+ - flux1_ipadapter
64
+ - sd3_ipadapter
65
+ - style
66
+ - embedding
67
+ - conditioning
68
+ - reference_latent
69
+ - hidream_o1_reference
70
+ - hidream_o1_smoothing
71
+ - joyai_image
72
+ - krea2_identity_edit
73
+ - krea2_style_reference
74
+ - qwen_image_edit
75
+ - boogu_image_edit
76
+ - reference_image
77
+ - vae
78
+
79
+ outpaint:
80
+ enabled_chains:
81
+ - lora
82
+ - controlnet
83
+ - anima_controlnet_lllite
84
+ - diffsynth_controlnet
85
+ - krea2_controlnet
86
+ - ipadapter
87
+ - flux1_ipadapter
88
+ - sd3_ipadapter
89
+ - style
90
+ - embedding
91
+ - conditioning
92
+ - reference_latent
93
+ - hidream_o1_reference
94
+ - hidream_o1_smoothing
95
+ - joyai_image
96
+ - krea2_identity_edit
97
+ - krea2_style_reference
98
+ - qwen_image_edit
99
+ - boogu_image_edit
100
+ - reference_image
101
+ - vae
102
+
103
+ hires_fix:
104
+ enabled_chains:
105
+ - lora
106
+ - controlnet
107
+ - anima_controlnet_lllite
108
+ - diffsynth_controlnet
109
+ - krea2_controlnet
110
+ - ipadapter
111
+ - flux1_ipadapter
112
+ - sd3_ipadapter
113
+ - style
114
+ - embedding
115
+ - conditioning
116
+ - reference_latent
117
+ - hidream_o1_reference
118
+ - hidream_o1_smoothing
119
+ - joyai_image
120
+ - krea2_identity_edit
121
+ - krea2_style_reference
122
+ - qwen_image_edit
123
+ - boogu_image_edit
124
+ - reference_image
125
+ - vae