From bc916d597fad044b77747b2feba58315659127a3 Mon Sep 17 00:00:00 2001 From: Sirshendu Ganguly Date: Thu, 4 Jun 2026 22:07:10 +0530 Subject: [PATCH 1/3] Added structuredPrompt support for Ideoggram 4 --- __init__.py | 3 + clientlibs/main.js | 4 +- clientlibs/types.js | 5 + clientlibs/utils.js | 78 +++++++ .../imageInferenceSettingsStructuredPrompt.py | 214 ++++++++++++++++++ modules/settings.py | 17 +- .../Runware_Image_Inference_Ideogram_V4.json | 1 + 7 files changed, 318 insertions(+), 4 deletions(-) create mode 100644 modules/imageInferenceSettingsStructuredPrompt.py create mode 100644 workflows/Runware_Image_Inference_Ideogram_V4.json diff --git a/__init__.py b/__init__.py index 2793993..6f20548 100644 --- a/__init__.py +++ b/__init__.py @@ -110,6 +110,7 @@ from .modules.safetyInputs import safetyInputs from .modules.settings import RunwareSettings from .modules.imageInferenceSettingsColorPalette import RunwareImageInferenceSettingsColorPalette from .modules.imageInferenceSettingsMoodboards import RunwareImageInferenceSettingsMoodboards +from .modules.imageInferenceSettingsStructuredPrompt import RunwareImageInferenceSettingsStructuredPrompt from .modules.videoAdvancedFeatureInputs import videoAdvancedFeatureInputs from .modules.advancedFeatureSettings.wanAnimateAdvancedFeatureSettings import RunwareWanAnimateAdvancedFeatureSettings from .modules.saveImage import RunwareSaveImage @@ -250,6 +251,7 @@ NODE_CLASS_MAPPINGS = { "Runware Settings": RunwareSettings, "Runware Image Inference Settings Color Palette": RunwareImageInferenceSettingsColorPalette, "Runware Image Inference Settings Moodboards": RunwareImageInferenceSettingsMoodboards, + "Runware Image Inference Settings Structured Prompt": RunwareImageInferenceSettingsStructuredPrompt, "Runware Video Advanced Feature Inputs": videoAdvancedFeatureInputs, "Runware Wan Animate Advanced Feature Settings": RunwareWanAnimateAdvancedFeatureSettings, "Runware Save Image": RunwareSaveImage, @@ -277,6 +279,7 @@ NODE_DISPLAY_NAME_MAPPINGS = { "Runware Audio Model Search": "Runware Audio Model", "Runware Text Model Search": "Runware Text Model", "Runware Image Inference Settings Color Palette": "Runware Image Inference Color Palette", + "Runware Image Inference Settings Structured Prompt": "Runware Image Inference Structured Prompt", "Runware Video Transcription": "Runware Video Caption", "Runware Video Inputs References": "Runware Video Inference Inputs Reference Images", "Runware Video Inference Inputs Reference Images": "Runware Video Inference Inputs Reference Images", diff --git a/clientlibs/main.js b/clientlibs/main.js index 950a8d7..cbd3065 100644 --- a/clientlibs/main.js +++ b/clientlibs/main.js @@ -1,6 +1,6 @@ import { app } from "../../scripts/app.js"; import { api } from "../../scripts/api.js"; -import { promptEnhanceHandler, syncDimensionsNodeHandler, searchNodeHandler, APIKeyHandler, captionNodeHandler, saveTextHandler, mediaUUIDHandler, save3DFilepathHandler, videoTranscriptionHandler, videoOutputsHandler, handleCustomErrors, videoInferenceDimensionsHandler, videoModelSearchFilterHandler, audioModelSearchFilterHandler, textModelSearchFilterHandler, vectorizeModelSearchFilterHandler, vectorizeToggleHandler, useParameterToggleHandler, imageInferenceToggleHandler, imageInferenceAdvancedFeaturesToggleHandler, watermarkAdvancedFeatureToggleHandler, videoInferenceSpeechInputToggleHandler, regionalPromptingRegionsToggleHandler, upscalerToggleHandler, imageUpscalerSettingsToggleHandler, videoUpscalerToggleHandler, audioInferenceToggleHandler, audioInferenceSpeechToggleHandler, audioSettingsToggleHandler, textInferenceSettingsToggleHandler, videoSettingsToggleHandler, videoInferenceSettingsTtsToggleHandler, videoInferenceSettingsActiveSpeakerDetectionToggleHandler, videoInferenceSettingsActiveSpeakerBoundingBoxesToggleHandler, videoInferenceSettingsSegmentsToggleHandler, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, xaiProviderSettingsToggleHandler, viduProviderSettingsToggleHandler, sourcefulProviderSettingsToggleHandler, sourcefulProviderSettingsFontsToggleHandler, threeDInferenceToggleHandler, threeDInferenceSettingsToggleHandler, threeDInferenceSettingsLatToggleHandler, threeDInferenceSettingsMeshClusterToggleHandler, ultralyticsProviderSettingsToggleHandler, openaiProviderSettingsToggleHandler, lightricksProviderSettingsToggleHandler, klingProviderSettingsToggleHandler, lumaProviderSettingsToggleHandler, briaProviderSettingsToggleHandler, pixverseProviderSettingsToggleHandler, alibabaProviderSettingsToggleHandler, mireloProviderSettingsToggleHandler, googleProviderSettingsToggleHandler, syncProviderSettingsToggleHandler, syncSegmentToggleHandler, settingsToggleHandler, outpaintSettingsToggleHandler, safetyInputsToggleHandler, imageInferenceSettingsColorPaletteToggleHandler, imageInferenceSettingsMoodboardsToggleHandler, audioInputToggleHandler, speechInputToggleHandler, briaProviderMaskToggleHandler, wanAnimateAdvancedFeatureSettingsToggleHandler, videoAdvancedFeatureInputsToggleHandler, audioInferenceInputsToggleHandler, audioInferenceReferenceVoiceToggleHandler, audioInferenceSpeechVoicesToggleHandler, videoInputsFrameToggleHandler, referenceVideosToggleHandler } from "./utils.js"; +import { promptEnhanceHandler, syncDimensionsNodeHandler, searchNodeHandler, APIKeyHandler, captionNodeHandler, saveTextHandler, mediaUUIDHandler, save3DFilepathHandler, videoTranscriptionHandler, videoOutputsHandler, handleCustomErrors, videoInferenceDimensionsHandler, videoModelSearchFilterHandler, audioModelSearchFilterHandler, textModelSearchFilterHandler, vectorizeModelSearchFilterHandler, vectorizeToggleHandler, useParameterToggleHandler, imageInferenceToggleHandler, imageInferenceAdvancedFeaturesToggleHandler, watermarkAdvancedFeatureToggleHandler, videoInferenceSpeechInputToggleHandler, regionalPromptingRegionsToggleHandler, upscalerToggleHandler, imageUpscalerSettingsToggleHandler, videoUpscalerToggleHandler, audioInferenceToggleHandler, audioInferenceSpeechToggleHandler, audioSettingsToggleHandler, textInferenceSettingsToggleHandler, videoSettingsToggleHandler, videoInferenceSettingsTtsToggleHandler, videoInferenceSettingsActiveSpeakerDetectionToggleHandler, videoInferenceSettingsActiveSpeakerBoundingBoxesToggleHandler, videoInferenceSettingsSegmentsToggleHandler, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, xaiProviderSettingsToggleHandler, viduProviderSettingsToggleHandler, sourcefulProviderSettingsToggleHandler, sourcefulProviderSettingsFontsToggleHandler, threeDInferenceToggleHandler, threeDInferenceSettingsToggleHandler, threeDInferenceSettingsLatToggleHandler, threeDInferenceSettingsMeshClusterToggleHandler, ultralyticsProviderSettingsToggleHandler, openaiProviderSettingsToggleHandler, lightricksProviderSettingsToggleHandler, klingProviderSettingsToggleHandler, lumaProviderSettingsToggleHandler, briaProviderSettingsToggleHandler, pixverseProviderSettingsToggleHandler, alibabaProviderSettingsToggleHandler, mireloProviderSettingsToggleHandler, googleProviderSettingsToggleHandler, syncProviderSettingsToggleHandler, syncSegmentToggleHandler, settingsToggleHandler, outpaintSettingsToggleHandler, safetyInputsToggleHandler, imageInferenceSettingsColorPaletteToggleHandler, imageInferenceSettingsMoodboardsToggleHandler, imageInferenceSettingsStructuredPromptToggleHandler, audioInputToggleHandler, speechInputToggleHandler, briaProviderMaskToggleHandler, wanAnimateAdvancedFeatureSettingsToggleHandler, videoAdvancedFeatureInputsToggleHandler, audioInferenceInputsToggleHandler, audioInferenceReferenceVoiceToggleHandler, audioInferenceSpeechVoicesToggleHandler, videoInputsFrameToggleHandler, referenceVideosToggleHandler } from "./utils.js"; import { RUNWARE_NODE_TYPES, RUNWARE_NODE_PROPS, SEARCH_TERMS } from "./types.js"; const nodeInitList = []; @@ -153,6 +153,8 @@ app.registerExtension({ imageInferenceSettingsColorPaletteToggleHandler(node); } else if(nodeClass === RUNWARE_NODE_TYPES.IMAGEINFERENCESETTINGSMOODBOARDS) { imageInferenceSettingsMoodboardsToggleHandler(node); + } else if(nodeClass === RUNWARE_NODE_TYPES.IMAGEINFERENCESETTINGSSTRUCTUREDPROMPT) { + imageInferenceSettingsStructuredPromptToggleHandler(node); } else if(nodeClass === RUNWARE_NODE_TYPES.AUDIOINPUT) { audioInputToggleHandler(node); } else if(nodeClass === RUNWARE_NODE_TYPES.SPEECHINPUT) { diff --git a/clientlibs/types.js b/clientlibs/types.js index ea1b713..fdf69b6 100644 --- a/clientlibs/types.js +++ b/clientlibs/types.js @@ -159,6 +159,7 @@ const RUNWARE_NODE_TYPES = { SETTINGS: "Runware Settings", IMAGEINFERENCESETTINGSCOLORPALETTE: "Runware Image Inference Settings Color Palette", IMAGEINFERENCESETTINGSMOODBOARDS: "Runware Image Inference Settings Moodboards", + IMAGEINFERENCESETTINGSSTRUCTUREDPROMPT: "Runware Image Inference Settings Structured Prompt", VIDEOADVANCEDFEATUREINPUTS: "Runware Video Advanced Feature Inputs", WANANIMATEADVANCEDFEATURESETTINGS: "Runware Wan Animate Advanced Feature Settings", SAVEIMAGE: "Runware Save Image", @@ -632,6 +633,10 @@ const RUNWARE_NODE_PROPS = { bgColor: DEFAULT_BGCOLOR, colorModeOnly: true, }, + [RUNWARE_NODE_TYPES.IMAGEINFERENCESETTINGSSTRUCTUREDPROMPT]: { + bgColor: DEFAULT_BGCOLOR, + colorModeOnly: true, + }, [RUNWARE_NODE_TYPES.VIDEOADVANCEDFEATUREINPUTS]: { bgColor: DEFAULT_BGCOLOR, colorModeOnly: true, diff --git a/clientlibs/utils.js b/clientlibs/utils.js index a5e2b14..0d5ac92 100644 --- a/clientlibs/utils.js +++ b/clientlibs/utils.js @@ -5249,6 +5249,7 @@ export { safetyInputsToggleHandler, imageInferenceSettingsColorPaletteToggleHandler, imageInferenceSettingsMoodboardsToggleHandler, + imageInferenceSettingsStructuredPromptToggleHandler, audioInputToggleHandler, speechInputToggleHandler, briaProviderMaskToggleHandler, @@ -5668,6 +5669,83 @@ function imageInferenceSettingsMoodboardsToggleHandler(moodboardsNode) { setTimeout(toggleStrengthState, 100); } +function imageInferenceSettingsStructuredPromptToggleHandler(node) { + if (!node?.widgets) return; + + function applyParamState(useWidget, paramWidget, paramName) { + if (!useWidget || !paramWidget) return; + const enabled = useWidget.value === true; + if (paramWidget.inputEl) { + paramWidget.inputEl.disabled = !enabled; + paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; + paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; + paramWidget.inputEl.readOnly = !enabled; + } + paramWidget.disabled = !enabled; + if (!paramWidget.inputEl) { + const nodeElement = node.htmlElements?.widgetsContainer || node.htmlElements; + if (nodeElement) { + const input = nodeElement.querySelector( + `input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]` + ); + if (input) { + input.disabled = !enabled; + input.style.opacity = enabled ? "1" : "0.5"; + input.style.cursor = enabled ? "text" : "not-allowed"; + input.readOnly = !enabled; + } + } + } + } + + function toggleWidgetState(useWidget, paramWidget, paramName) { + if (!useWidget || !paramWidget) return; + function toggleEnabled() { + applyParamState(useWidget, paramWidget, paramName); + node.setDirtyCanvas(true); + } + appendWidgetCB(useWidget, () => setTimeout(toggleEnabled, 50)); + setTimeout(toggleEnabled, 100); + } + + const useStyleDescriptionWidget = node.widgets.find((w) => w && w.name === "useStyleDescription"); + const styleDescriptionWidget = node.widgets.find((w) => w && w.name === "style_description"); + if (useStyleDescriptionWidget && styleDescriptionWidget) { + toggleWidgetState(useStyleDescriptionWidget, styleDescriptionWidget, "style_description"); + } + + const useElementsJsonWidget = node.widgets.find((w) => w && w.name === "useElementsJson"); + const elementsJsonWidget = node.widgets.find((w) => w && w.name === "elementsJson"); + if (useElementsJsonWidget && elementsJsonWidget) { + toggleWidgetState(useElementsJsonWidget, elementsJsonWidget, "elementsJson"); + } + + function bindElementSlot(i) { + const useW = node.widgets.find((w) => w && w.name === `use_element_${i}`); + const typeW = node.widgets.find((w) => w && w.name === `element_type_${i}`); + const descW = node.widgets.find((w) => w && w.name === `element_desc_${i}`); + const textW = node.widgets.find((w) => w && w.name === `element_text_${i}`); + const bboxW = node.widgets.find((w) => w && w.name === `element_bbox_${i}`); + const paletteW = node.widgets.find((w) => w && w.name === `element_color_palette_${i}`); + if (!useW) return; + + function toggleSlot() { + const enabled = useW.value === true; + [typeW, descW, textW, bboxW, paletteW].forEach((w) => { + if (w) toggleWidgetEnabled(w, enabled, node); + }); + node.setDirtyCanvas(true); + } + + appendWidgetCB(useW, () => setTimeout(toggleSlot, 50)); + setTimeout(toggleSlot, 100); + } + + for (let i = 1; i <= 8; i++) { + bindElementSlot(i); + } +} + function syncProviderSettingsToggleHandler(syncNode) { // Find all "use" parameter widgets for Sync Provider Settings const useEditRegionWidget = syncNode.widgets.find(w => w.name === "useEditRegion"); diff --git a/modules/imageInferenceSettingsStructuredPrompt.py b/modules/imageInferenceSettingsStructuredPrompt.py new file mode 100644 index 0000000..cbdc9c9 --- /dev/null +++ b/modules/imageInferenceSettingsStructuredPrompt.py @@ -0,0 +1,214 @@ +""" +Runware Image Inference Settings Structured Prompt +Builds settings.structuredPrompt for Ideogram 4.0 and compatible models. +Connect the output to Runware Image Inference Settings → structuredPrompt. +Mutually exclusive with positivePrompt at the API level. +""" + +import json +from typing import Any, Dict, List, Tuple + + +class RunwareImageInferenceSettingsStructuredPrompt: + """Ideogram-style structured JSON prompt for image inference settings.""" + + _ELEMENT_SLOTS = 8 + + @classmethod + def INPUT_TYPES(cls): + optional: Dict[str, tuple] = { + "high_level_description": ("STRING", { + "multiline": True, + "default": "", + "tooltip": "Global scene summary (required).", + }), + "background": ("STRING", { + "multiline": True, + "default": "", + "tooltip": "compositional_deconstruction.background — setting/surface/atmosphere, not discrete subjects.", + }), + "useStyleDescription": ("BOOLEAN", { + "default": False, + "label_on": "Enabled", + "label_off": "Disabled", + "tooltip": "Include style_description from JSON below.", + }), + "style_description": ("STRING", { + "multiline": True, + "default": "", + "tooltip": "style_description object as JSON (aesthetics, lighting, photo OR art_style, medium, color_palette). Only when 'Use Style Description' is enabled.", + }), + "useElementsJson": ("BOOLEAN", { + "default": False, + "label_on": "Enabled", + "label_off": "Disabled", + "tooltip": "Set elements from a JSON array instead of element slots 1–8.", + }), + "elementsJson": ("STRING", { + "multiline": True, + "default": "", + "tooltip": "JSON array of element objects ({type, desc, text?, bbox?, color_palette?}). Only when 'Use Elements JSON' is enabled.", + }), + } + + for i in range(1, cls._ELEMENT_SLOTS + 1): + optional[f"use_element_{i}"] = ("BOOLEAN", { + "default": False, + "label_on": "Enabled", + "label_off": "Disabled", + "tooltip": f"Include element slot {i} in compositional_deconstruction.elements.", + }) + optional[f"element_type_{i}"] = (["obj", "text"], { + "default": "obj", + "tooltip": f"Element {i} type: obj (desc interpreted) or text (text rendered literally).", + }) + optional[f"element_desc_{i}"] = ("STRING", { + "multiline": True, + "default": "", + "tooltip": f"Element {i} desc — natural language treatment/position notes.", + }) + optional[f"element_text_{i}"] = ("STRING", { + "multiline": True, + "default": "", + "tooltip": f"Element {i} text — literal copy for type text only.", + }) + optional[f"element_bbox_{i}"] = ("STRING", { + "default": "", + "tooltip": f"Element {i} optional bbox JSON: [y_min, x_min, y_max, x_max] in 0–1000 coords.", + }) + optional[f"element_color_palette_{i}"] = ("STRING", { + "default": "", + "tooltip": f"Element {i} optional hex colours, comma-separated (e.g. #1F3B26,#7A5A2F).", + }) + + return {"required": {}, "optional": optional} + + RETURN_TYPES = ("RUNWAREIMAGEINFERENCESTRUCTUREDPROMPT",) + RETURN_NAMES = ("structuredPrompt",) + FUNCTION = "build_structured_prompt" + CATEGORY = "Runware" + DESCRIPTION = ( + "Build settings.structuredPrompt for Ideogram 4.0 (snake_case schema) from " + "high_level_description, background, style_description, and elements. " + "Connect to Runware Image Inference Settings. Do not send positivePrompt in the same request." + ) + + @staticmethod + def _parse_json_object(raw: str, field_name: str) -> Dict[str, Any]: + text = (raw or "").strip() + if not text: + raise ValueError(f"{field_name} is empty.") + try: + parsed = json.loads(text) + except json.JSONDecodeError as e: + raise ValueError(f"{field_name} must be valid JSON: {e}") from e + if not isinstance(parsed, dict): + raise ValueError(f"{field_name} must be a JSON object.") + return parsed + + @staticmethod + def _parse_json_array(raw: str, field_name: str) -> List[Any]: + text = (raw or "").strip() + if not text: + raise ValueError(f"{field_name} is empty.") + try: + parsed = json.loads(text) + except json.JSONDecodeError as e: + raise ValueError(f"{field_name} must be valid JSON: {e}") from e + if not isinstance(parsed, list): + raise ValueError(f"{field_name} must be a JSON array.") + return parsed + + @classmethod + def _build_element_from_slot(cls, kwargs: Dict[str, Any], index: int) -> Dict[str, Any]: + el_type = str(kwargs.get(f"element_type_{index}", "obj")).strip() or "obj" + if el_type not in ("obj", "text"): + raise ValueError(f"element_type_{index} must be obj or text.") + + element: Dict[str, Any] = {"type": el_type} + + desc = str(kwargs.get(f"element_desc_{index}") or "").strip() + if desc: + element["desc"] = desc + + if el_type == "text": + text = str(kwargs.get(f"element_text_{index}") or "").strip() + if text: + element["text"] = text + + bbox_raw = str(kwargs.get(f"element_bbox_{index}") or "").strip() + if bbox_raw: + try: + bbox = json.loads(bbox_raw) + except json.JSONDecodeError as e: + raise ValueError(f"element_bbox_{index} must be valid JSON: {e}") from e + if not isinstance(bbox, list): + raise ValueError(f"element_bbox_{index} must be a JSON array.") + element["bbox"] = bbox + + palette_raw = str(kwargs.get(f"element_color_palette_{index}") or "").strip() + if palette_raw: + palette = [h.strip() for h in palette_raw.split(",") if h.strip()] + if palette: + element["color_palette"] = palette + + if el_type == "text" and "text" not in element and not desc: + raise ValueError( + f"Element slot {index}: type text requires element_text_{index} or element_desc_{index}." + ) + if el_type == "obj" and not desc: + raise ValueError(f"Element slot {index}: type obj requires element_desc_{index}.") + + return element + + @classmethod + def _collect_elements(cls, kwargs: Dict[str, Any]) -> List[Dict[str, Any]]: + if kwargs.get("useElementsJson", False): + return cls._parse_json_array( + kwargs.get("elementsJson", ""), + "elementsJson", + ) + + elements: List[Dict[str, Any]] = [] + for i in range(1, cls._ELEMENT_SLOTS + 1): + if not kwargs.get(f"use_element_{i}", False): + continue + elements.append(cls._build_element_from_slot(kwargs, i)) + return elements + + def build_structured_prompt(self, **kwargs) -> Tuple[Dict[str, Any]]: + hld = str(kwargs.get("high_level_description") or "").strip() + if not hld: + raise ValueError("high_level_description is required.") + + structured: Dict[str, Any] = {"high_level_description": hld} + + if kwargs.get("useStyleDescription", False): + style_raw = kwargs.get("style_description", "") + structured["style_description"] = self._parse_json_object( + style_raw, + "style_description", + ) + + comp: Dict[str, Any] = {} + background = str(kwargs.get("background") or "").strip() + if background: + comp["background"] = background + + elements = self._collect_elements(kwargs) + if elements: + comp["elements"] = elements + + if comp: + structured["compositional_deconstruction"] = comp + + return (structured,) + + +NODE_CLASS_MAPPINGS = { + "RunwareImageInferenceSettingsStructuredPrompt": RunwareImageInferenceSettingsStructuredPrompt, +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "RunwareImageInferenceSettingsStructuredPrompt": "Runware Image Inference Settings Structured Prompt", +} diff --git a/modules/settings.py b/modules/settings.py index cca04b0..7b45bd8 100644 --- a/modules/settings.py +++ b/modules/settings.py @@ -4,8 +4,8 @@ Provides settings for image generation including temperature, systemPrompt, topP quality, background, style, search, promptExtend, editRegions, thinking (boolean), thinkingLevel (high/medium/low), sequential, renderingSpeed (TURBO/DEFAULT/QUALITY), magicPrompt (AUTO/ON/OFF), autoCrop, dilatePixels, creativity (raw/low/medium/high), colorPalette, -and moodboards -(from Runware Image Inference Settings Color Palette). +moodboards (from Runware Image Inference Settings Moodboards), +and structuredPrompt (from Runware Image Inference Settings Structured Prompt; Ideogram 4.0). """ import json @@ -205,6 +205,9 @@ class RunwareSettings: "moodboards": ("RUNWAREIMAGEINFERENCEMOODBOARDS", { "tooltip": "Connect Runware Image Inference Settings Moodboards. When connected with at least one entry, it is merged into settings.moodboards.", }), + "structuredPrompt": ("RUNWAREIMAGEINFERENCESTRUCTUREDPROMPT", { + "tooltip": "Connect Runware Image Inference Settings Structured Prompt (Ideogram 4.0). Merged into settings.structuredPrompt. Mutually exclusive with positivePrompt on the same API request.", + }), } } @@ -216,7 +219,7 @@ class RunwareSettings: "Configure general settings for image generation: temperature, system prompt, top-p, layers, quality, background, style, search, " "promptExtend, editRegions (JSON), thinking (boolean), thinkingLevel (high/medium/low), sequential, " "renderingSpeed (TURBO/DEFAULT/QUALITY), magicPrompt (AUTO/ON/OFF), autoCrop, dilatePixels, " - "creativity (raw/low/medium/high), and optional colorPalette and moodboards from dedicated settings nodes." + "creativity (raw/low/medium/high), and optional colorPalette, moodboards, and structuredPrompt from dedicated settings nodes." ) def createSettings(self, **kwargs) -> tuple[Dict[str, Any]]: @@ -309,6 +312,14 @@ class RunwareSettings: if moodboards is not None and isinstance(moodboards, list) and len(moodboards) > 0: settings["moodboards"] = moodboards + structured_prompt: Optional[Dict[str, Any]] = kwargs.get("structuredPrompt") + if ( + structured_prompt is not None + and isinstance(structured_prompt, dict) + and len(structured_prompt) > 0 + ): + settings["structuredPrompt"] = structured_prompt + if useRenderingSpeed: settings["renderingSpeed"] = str(renderingSpeed) if useMagicPrompt: diff --git a/workflows/Runware_Image_Inference_Ideogram_V4.json b/workflows/Runware_Image_Inference_Ideogram_V4.json new file mode 100644 index 0000000..1f7054f --- /dev/null +++ b/workflows/Runware_Image_Inference_Ideogram_V4.json @@ -0,0 +1 @@ +{"id":"23d5cf83-5409-4c87-bb6f-66f2bd116b72","revision":0,"last_node_id":8,"last_link_id":5,"nodes":[{"id":2,"type":"Runware Settings","pos":[72.64754306900058,530.9703257013587],"size":[400,1046],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"colorPalette","name":"colorPalette","shape":7,"type":"RUNWAREIMAGEINFERENCECOLORPALETTE","link":null},{"localized_name":"moodboards","name":"moodboards","shape":7,"type":"RUNWAREIMAGEINFERENCEMOODBOARDS","link":null},{"localized_name":"structuredPrompt","name":"structuredPrompt","shape":7,"type":"RUNWAREIMAGEINFERENCESTRUCTUREDPROMPT","link":5},{"localized_name":"useTemperature","name":"useTemperature","shape":7,"type":"BOOLEAN","widget":{"name":"useTemperature"},"link":null},{"localized_name":"temperature","name":"temperature","shape":7,"type":"FLOAT","widget":{"name":"temperature"},"link":null},{"localized_name":"useSystemPrompt","name":"useSystemPrompt","shape":7,"type":"BOOLEAN","widget":{"name":"useSystemPrompt"},"link":null},{"localized_name":"systemPrompt","name":"systemPrompt","shape":7,"type":"STRING","widget":{"name":"systemPrompt"},"link":null},{"localized_name":"useTopP","name":"useTopP","shape":7,"type":"BOOLEAN","widget":{"name":"useTopP"},"link":null},{"localized_name":"topP","name":"topP","shape":7,"type":"FLOAT","widget":{"name":"topP"},"link":null},{"localized_name":"useLayers","name":"useLayers","shape":7,"type":"BOOLEAN","widget":{"name":"useLayers"},"link":null},{"localized_name":"layers","name":"layers","shape":7,"type":"INT","widget":{"name":"layers"},"link":null},{"localized_name":"useTrueCFGScale","name":"useTrueCFGScale","shape":7,"type":"BOOLEAN","widget":{"name":"useTrueCFGScale"},"link":null},{"localized_name":"trueCFGScale","name":"trueCFGScale","shape":7,"type":"FLOAT","widget":{"name":"trueCFGScale"},"link":null},{"localized_name":"useQuality","name":"useQuality","shape":7,"type":"BOOLEAN","widget":{"name":"useQuality"},"link":null},{"localized_name":"quality","name":"quality","shape":7,"type":"COMBO","widget":{"name":"quality"},"link":null},{"localized_name":"usePromptExtend","name":"usePromptExtend","shape":7,"type":"BOOLEAN","widget":{"name":"usePromptExtend"},"link":null},{"localized_name":"promptExtend","name":"promptExtend","shape":7,"type":"BOOLEAN","widget":{"name":"promptExtend"},"link":null},{"localized_name":"useEditRegions","name":"useEditRegions","shape":7,"type":"BOOLEAN","widget":{"name":"useEditRegions"},"link":null},{"localized_name":"editRegions","name":"editRegions","shape":7,"type":"STRING","widget":{"name":"editRegions"},"link":null},{"localized_name":"useThinking","name":"useThinking","shape":7,"type":"BOOLEAN","widget":{"name":"useThinking"},"link":null},{"localized_name":"thinking","name":"thinking","shape":7,"type":"BOOLEAN","widget":{"name":"thinking"},"link":null},{"localized_name":"useSequential","name":"useSequential","shape":7,"type":"BOOLEAN","widget":{"name":"useSequential"},"link":null},{"localized_name":"sequential","name":"sequential","shape":7,"type":"BOOLEAN","widget":{"name":"sequential"},"link":null},{"localized_name":"useThinkingLevel","name":"useThinkingLevel","shape":7,"type":"BOOLEAN","widget":{"name":"useThinkingLevel"},"link":null},{"localized_name":"thinkingLevel","name":"thinkingLevel","shape":7,"type":"COMBO","widget":{"name":"thinkingLevel"},"link":null},{"localized_name":"useBackground","name":"useBackground","shape":7,"type":"BOOLEAN","widget":{"name":"useBackground"},"link":null},{"localized_name":"background","name":"background","shape":7,"type":"COMBO","widget":{"name":"background"},"link":null},{"localized_name":"useStyle","name":"useStyle","shape":7,"type":"BOOLEAN","widget":{"name":"useStyle"},"link":null},{"localized_name":"style","name":"style","shape":7,"type":"STRING","widget":{"name":"style"},"link":null},{"localized_name":"useSearch","name":"useSearch","shape":7,"type":"BOOLEAN","widget":{"name":"useSearch"},"link":null},{"localized_name":"search","name":"search","shape":7,"type":"BOOLEAN","widget":{"name":"search"},"link":null},{"localized_name":"useRenderingSpeed","name":"useRenderingSpeed","shape":7,"type":"BOOLEAN","widget":{"name":"useRenderingSpeed"},"link":null},{"localized_name":"renderingSpeed","name":"renderingSpeed","shape":7,"type":"COMBO","widget":{"name":"renderingSpeed"},"link":null},{"localized_name":"useMagicPrompt","name":"useMagicPrompt","shape":7,"type":"BOOLEAN","widget":{"name":"useMagicPrompt"},"link":null},{"localized_name":"magicPrompt","name":"magicPrompt","shape":7,"type":"COMBO","widget":{"name":"magicPrompt"},"link":null},{"localized_name":"useAutoCrop","name":"useAutoCrop","shape":7,"type":"BOOLEAN","widget":{"name":"useAutoCrop"},"link":null},{"localized_name":"autoCrop","name":"autoCrop","shape":7,"type":"BOOLEAN","widget":{"name":"autoCrop"},"link":null},{"localized_name":"useDilatePixels","name":"useDilatePixels","shape":7,"type":"BOOLEAN","widget":{"name":"useDilatePixels"},"link":null},{"localized_name":"dilatePixels","name":"dilatePixels","shape":7,"type":"INT","widget":{"name":"dilatePixels"},"link":null},{"localized_name":"useCreativity","name":"useCreativity","shape":7,"type":"BOOLEAN","widget":{"name":"useCreativity"},"link":null},{"localized_name":"creativity","name":"creativity","shape":7,"type":"COMBO","widget":{"name":"creativity"},"link":null}],"outputs":[{"localized_name":"Settings","name":"Settings","type":"RUNWARESETTINGS","links":[2]}],"properties":{"cnr_id":"ComfyUI-Runware","ver":"429eb9b8be0fcf8b3f2f3ab58cb418d35bedcfb2","Node name for S&R":"Runware Settings"},"widgets_values":[false,1,false,"",false,1,false,4,false,1,false,"medium",false,false,false,"",false,false,false,false,false,"high",false,"auto",false,"auto",false,false,false,"DEFAULT",false,"AUTO",false,false,false,10,false,"medium"],"bgcolor":"#5345bf"},{"id":5,"type":"Runware Save Image","pos":[973.426201790141,600.3295504914947],"size":[270,318],"flags":{},"order":4,"mode":0,"inputs":[{"localized_name":"Images","name":"Images","type":"STRING","widget":{"name":"Images"},"link":3},{"localized_name":"filenamePrefix","name":"filenamePrefix","type":"STRING","widget":{"name":"filenamePrefix"},"link":null},{"localized_name":"saveImage","name":"saveImage","type":"BOOLEAN","widget":{"name":"saveImage"},"link":null}],"outputs":[{"localized_name":"IMAGE","name":"IMAGE","type":"IMAGE","links":null}],"properties":{"cnr_id":"ComfyUI-Runware","ver":"429eb9b8be0fcf8b3f2f3ab58cb418d35bedcfb2","Node name for S&R":"Runware Save Image"},"widgets_values":["","ComfyUI",true],"bgcolor":"#5345bf"},{"id":6,"type":"Runware Model Search","pos":[-832.1743280729665,543.6760210557717],"size":[272.111328125,154],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"Model Search","name":"Model Search","type":"STRING","widget":{"name":"Model Search"},"link":null},{"localized_name":"Model Architecture","name":"Model Architecture","type":"COMBO","widget":{"name":"Model Architecture"},"link":null},{"localized_name":"ModelType","name":"ModelType","type":"COMBO","widget":{"name":"ModelType"},"link":null},{"localized_name":"ModelList","name":"ModelList","type":"COMBO","widget":{"name":"ModelList"},"link":null},{"localized_name":"Use Search Value","name":"Use Search Value","type":"BOOLEAN","widget":{"name":"Use Search Value"},"link":null}],"outputs":[{"localized_name":"Runware Model","name":"Runware Model","type":"RUNWAREMODEL","links":[4]}],"properties":{"cnr_id":"ComfyUI-Runware","ver":"429eb9b8be0fcf8b3f2f3ab58cb418d35bedcfb2","Node name for S&R":"Runware Model Search"},"widgets_values":["ideogram:4@0","All","Base Model","ideogram:4@0 (Ideogram 4.0 4.0)",true],"bgcolor":"#5345bf"},{"id":1,"type":"Runware Image Inference","pos":[-397.1735531165802,463.5775492624153],"size":[400,1130],"flags":{},"order":3,"mode":0,"inputs":[{"localized_name":"Model","name":"Model","type":"RUNWAREMODEL","link":4},{"localized_name":"Accelerator","name":"Accelerator","shape":7,"type":"RUNWAREACCELERATOR","link":null},{"localized_name":"Lora","name":"Lora","shape":7,"type":"RUNWARELORA","link":null},{"localized_name":"Outpainting","name":"Outpainting","shape":7,"type":"RUNWAREOUTPAINT","link":null},{"localized_name":"IPAdapters","name":"IPAdapters","shape":7,"type":"RUNWAREIPAdapter","link":null},{"localized_name":"ControlNet","name":"ControlNet","shape":7,"type":"RUNWARECONTROLNET","link":null},{"localized_name":"Refiner","name":"Refiner","shape":7,"type":"RUNWAREREFINER","link":null},{"localized_name":"seedImage","name":"seedImage","shape":7,"type":"IMAGE","link":null},{"localized_name":"maskImage","name":"maskImage","shape":7,"type":"MASK","link":null},{"localized_name":"Embeddings","name":"Embeddings","shape":7,"type":"RUNWAREEMBEDDING","link":null},{"localized_name":"VAE","name":"VAE","shape":7,"type":"RUNWAREVAE","link":null},{"localized_name":"referenceImages","name":"referenceImages","shape":7,"type":"RUNWAREREFERENCEIMAGES","link":null},{"localized_name":"inputs","name":"inputs","shape":7,"type":"RUNWAREIMAGEINFERENCEINPUTS","link":null},{"localized_name":"providerSettings","name":"providerSettings","shape":7,"type":"RUNWAREPROVIDERSETTINGS","link":null},{"localized_name":"safetyInputs","name":"safetyInputs","shape":7,"type":"RUNWARESAFETYINPUTS","link":null},{"localized_name":"settings","name":"settings","shape":7,"type":"RUNWARESETTINGS","link":2},{"localized_name":"ultralytics","name":"ultralytics","shape":7,"type":"RUNWAREULTRALYTICSINPUTS","link":null},{"localized_name":"advancedFeatures","name":"advancedFeatures","shape":7,"type":"RUNWAREIMAGEINFERENCEADVANCEDFEATURES","link":null},{"localized_name":"positivePrompt","name":"positivePrompt","type":"STRING","widget":{"name":"positivePrompt"},"link":null},{"localized_name":"negativePrompt","name":"negativePrompt","type":"STRING","widget":{"name":"negativePrompt"},"link":null},{"localized_name":"Multi Inference Mode","name":"Multi Inference Mode","type":"BOOLEAN","widget":{"name":"Multi Inference Mode"},"link":null},{"localized_name":"Prompt Weighting","name":"Prompt Weighting","type":"COMBO","widget":{"name":"Prompt Weighting"},"link":null},{"localized_name":"dimensions","name":"dimensions","type":"COMBO","widget":{"name":"dimensions"},"link":null},{"localized_name":"width","name":"width","type":"INT","widget":{"name":"width"},"link":null},{"localized_name":"height","name":"height","type":"INT","widget":{"name":"height"},"link":null},{"localized_name":"useResolution","name":"useResolution","type":"BOOLEAN","widget":{"name":"useResolution"},"link":null},{"localized_name":"resolution","name":"resolution","type":"COMBO","widget":{"name":"resolution"},"link":null},{"localized_name":"useSteps","name":"useSteps","type":"BOOLEAN","widget":{"name":"useSteps"},"link":null},{"localized_name":"steps","name":"steps","type":"INT","widget":{"name":"steps"},"link":null},{"localized_name":"useScheduler","name":"useScheduler","type":"BOOLEAN","widget":{"name":"useScheduler"},"link":null},{"localized_name":"scheduler","name":"scheduler","type":"COMBO","widget":{"name":"scheduler"},"link":null},{"localized_name":"useCFGScale","name":"useCFGScale","type":"BOOLEAN","widget":{"name":"useCFGScale"},"link":null},{"localized_name":"cfgScale","name":"cfgScale","type":"FLOAT","widget":{"name":"cfgScale"},"link":null},{"localized_name":"useSeed","name":"useSeed","type":"BOOLEAN","widget":{"name":"useSeed"},"link":null},{"localized_name":"seed","name":"seed","type":"INT","widget":{"name":"seed"},"link":null},{"localized_name":"useClipSkip","name":"useClipSkip","type":"BOOLEAN","widget":{"name":"useClipSkip"},"link":null},{"localized_name":"clipSkip","name":"clipSkip","type":"INT","widget":{"name":"clipSkip"},"link":null},{"localized_name":"strength","name":"strength","type":"FLOAT","widget":{"name":"strength"},"link":null},{"localized_name":"Mask Margin","name":"Mask Margin","type":"BOOLEAN","widget":{"name":"Mask Margin"},"link":null},{"localized_name":"maskMargin","name":"maskMargin","type":"INT","widget":{"name":"maskMargin"},"link":null},{"localized_name":"outputFormat","name":"outputFormat","type":"COMBO","widget":{"name":"outputFormat"},"link":null},{"localized_name":"batchSize","name":"batchSize","type":"INT","widget":{"name":"batchSize"},"link":null},{"localized_name":"acceleration","name":"acceleration","type":"COMBO","widget":{"name":"acceleration"},"link":null},{"localized_name":"outputQuality","name":"outputQuality","type":"INT","widget":{"name":"outputQuality"},"link":null},{"localized_name":"useUpscaleFactor","name":"useUpscaleFactor","type":"BOOLEAN","widget":{"name":"useUpscaleFactor"},"link":null},{"localized_name":"upscaleFactor","name":"upscaleFactor","type":"COMBO","widget":{"name":"upscaleFactor"},"link":null}],"outputs":[{"localized_name":"IMAGE","name":"IMAGE","type":"STRING","links":[3]},{"localized_name":"RW-Task","name":"RW-Task","type":"RUNWARETASK","links":null}],"properties":{"cnr_id":"ComfyUI-Runware","ver":"429eb9b8be0fcf8b3f2f3ab58cb418d35bedcfb2","Node name for S&R":"Runware Image Inference"},"widgets_values":["","",false,"Disabled","Custom",2880,1440,false,"1k",false,4,false,"Default",false,6.5,false,1097339186,"randomize",false,0,0.8,false,32,"WEBP",1,"none",95,false,2],"bgcolor":"#5345bf"},{"id":8,"type":"Runware Image Inference Settings Structured Prompt","pos":[509.48794677223043,466.8854507524061],"size":[400,1930.0000000000018],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"high_level_description","name":"high_level_description","shape":7,"type":"STRING","widget":{"name":"high_level_description"},"link":null},{"localized_name":"background","name":"background","shape":7,"type":"STRING","widget":{"name":"background"},"link":null},{"localized_name":"useStyleDescription","name":"useStyleDescription","shape":7,"type":"BOOLEAN","widget":{"name":"useStyleDescription"},"link":null},{"localized_name":"style_description","name":"style_description","shape":7,"type":"STRING","widget":{"name":"style_description"},"link":null},{"localized_name":"useElementsJson","name":"useElementsJson","shape":7,"type":"BOOLEAN","widget":{"name":"useElementsJson"},"link":null},{"localized_name":"elementsJson","name":"elementsJson","shape":7,"type":"STRING","widget":{"name":"elementsJson"},"link":null},{"localized_name":"use_element_1","name":"use_element_1","shape":7,"type":"BOOLEAN","widget":{"name":"use_element_1"},"link":null},{"localized_name":"element_type_1","name":"element_type_1","shape":7,"type":"COMBO","widget":{"name":"element_type_1"},"link":null},{"localized_name":"element_desc_1","name":"element_desc_1","shape":7,"type":"STRING","widget":{"name":"element_desc_1"},"link":null},{"localized_name":"element_text_1","name":"element_text_1","shape":7,"type":"STRING","widget":{"name":"element_text_1"},"link":null},{"localized_name":"element_bbox_1","name":"element_bbox_1","shape":7,"type":"STRING","widget":{"name":"element_bbox_1"},"link":null},{"localized_name":"element_color_palette_1","name":"element_color_palette_1","shape":7,"type":"STRING","widget":{"name":"element_color_palette_1"},"link":null},{"localized_name":"use_element_2","name":"use_element_2","shape":7,"type":"BOOLEAN","widget":{"name":"use_element_2"},"link":null},{"localized_name":"element_type_2","name":"element_type_2","shape":7,"type":"COMBO","widget":{"name":"element_type_2"},"link":null},{"localized_name":"element_desc_2","name":"element_desc_2","shape":7,"type":"STRING","widget":{"name":"element_desc_2"},"link":null},{"localized_name":"element_text_2","name":"element_text_2","shape":7,"type":"STRING","widget":{"name":"element_text_2"},"link":null},{"localized_name":"element_bbox_2","name":"element_bbox_2","shape":7,"type":"STRING","widget":{"name":"element_bbox_2"},"link":null},{"localized_name":"element_color_palette_2","name":"element_color_palette_2","shape":7,"type":"STRING","widget":{"name":"element_color_palette_2"},"link":null},{"localized_name":"use_element_3","name":"use_element_3","shape":7,"type":"BOOLEAN","widget":{"name":"use_element_3"},"link":null},{"localized_name":"element_type_3","name":"element_type_3","shape":7,"type":"COMBO","widget":{"name":"element_type_3"},"link":null},{"localized_name":"element_desc_3","name":"element_desc_3","shape":7,"type":"STRING","widget":{"name":"element_desc_3"},"link":null},{"localized_name":"element_text_3","name":"element_text_3","shape":7,"type":"STRING","widget":{"name":"element_text_3"},"link":null},{"localized_name":"element_bbox_3","name":"element_bbox_3","shape":7,"type":"STRING","widget":{"name":"element_bbox_3"},"link":null},{"localized_name":"element_color_palette_3","name":"element_color_palette_3","shape":7,"type":"STRING","widget":{"name":"element_color_palette_3"},"link":null},{"localized_name":"use_element_4","name":"use_element_4","shape":7,"type":"BOOLEAN","widget":{"name":"use_element_4"},"link":null},{"localized_name":"element_type_4","name":"element_type_4","shape":7,"type":"COMBO","widget":{"name":"element_type_4"},"link":null},{"localized_name":"element_desc_4","name":"element_desc_4","shape":7,"type":"STRING","widget":{"name":"element_desc_4"},"link":null},{"localized_name":"element_text_4","name":"element_text_4","shape":7,"type":"STRING","widget":{"name":"element_text_4"},"link":null},{"localized_name":"element_bbox_4","name":"element_bbox_4","shape":7,"type":"STRING","widget":{"name":"element_bbox_4"},"link":null},{"localized_name":"element_color_palette_4","name":"element_color_palette_4","shape":7,"type":"STRING","widget":{"name":"element_color_palette_4"},"link":null},{"localized_name":"use_element_5","name":"use_element_5","shape":7,"type":"BOOLEAN","widget":{"name":"use_element_5"},"link":null},{"localized_name":"element_type_5","name":"element_type_5","shape":7,"type":"COMBO","widget":{"name":"element_type_5"},"link":null},{"localized_name":"element_desc_5","name":"element_desc_5","shape":7,"type":"STRING","widget":{"name":"element_desc_5"},"link":null},{"localized_name":"element_text_5","name":"element_text_5","shape":7,"type":"STRING","widget":{"name":"element_text_5"},"link":null},{"localized_name":"element_bbox_5","name":"element_bbox_5","shape":7,"type":"STRING","widget":{"name":"element_bbox_5"},"link":null},{"localized_name":"element_color_palette_5","name":"element_color_palette_5","shape":7,"type":"STRING","widget":{"name":"element_color_palette_5"},"link":null},{"localized_name":"use_element_6","name":"use_element_6","shape":7,"type":"BOOLEAN","widget":{"name":"use_element_6"},"link":null},{"localized_name":"element_type_6","name":"element_type_6","shape":7,"type":"COMBO","widget":{"name":"element_type_6"},"link":null},{"localized_name":"element_desc_6","name":"element_desc_6","shape":7,"type":"STRING","widget":{"name":"element_desc_6"},"link":null},{"localized_name":"element_text_6","name":"element_text_6","shape":7,"type":"STRING","widget":{"name":"element_text_6"},"link":null},{"localized_name":"element_bbox_6","name":"element_bbox_6","shape":7,"type":"STRING","widget":{"name":"element_bbox_6"},"link":null},{"localized_name":"element_color_palette_6","name":"element_color_palette_6","shape":7,"type":"STRING","widget":{"name":"element_color_palette_6"},"link":null},{"localized_name":"use_element_7","name":"use_element_7","shape":7,"type":"BOOLEAN","widget":{"name":"use_element_7"},"link":null},{"localized_name":"element_type_7","name":"element_type_7","shape":7,"type":"COMBO","widget":{"name":"element_type_7"},"link":null},{"localized_name":"element_desc_7","name":"element_desc_7","shape":7,"type":"STRING","widget":{"name":"element_desc_7"},"link":null},{"localized_name":"element_text_7","name":"element_text_7","shape":7,"type":"STRING","widget":{"name":"element_text_7"},"link":null},{"localized_name":"element_bbox_7","name":"element_bbox_7","shape":7,"type":"STRING","widget":{"name":"element_bbox_7"},"link":null},{"localized_name":"element_color_palette_7","name":"element_color_palette_7","shape":7,"type":"STRING","widget":{"name":"element_color_palette_7"},"link":null},{"localized_name":"use_element_8","name":"use_element_8","shape":7,"type":"BOOLEAN","widget":{"name":"use_element_8"},"link":null},{"localized_name":"element_type_8","name":"element_type_8","shape":7,"type":"COMBO","widget":{"name":"element_type_8"},"link":null},{"localized_name":"element_desc_8","name":"element_desc_8","shape":7,"type":"STRING","widget":{"name":"element_desc_8"},"link":null},{"localized_name":"element_text_8","name":"element_text_8","shape":7,"type":"STRING","widget":{"name":"element_text_8"},"link":null},{"localized_name":"element_bbox_8","name":"element_bbox_8","shape":7,"type":"STRING","widget":{"name":"element_bbox_8"},"link":null},{"localized_name":"element_color_palette_8","name":"element_color_palette_8","shape":7,"type":"STRING","widget":{"name":"element_color_palette_8"},"link":null}],"outputs":[{"localized_name":"structuredPrompt","name":"structuredPrompt","type":"RUNWAREIMAGEINFERENCESTRUCTUREDPROMPT","links":[5]}],"properties":{"cnr_id":"ComfyUI-Runware","ver":"429eb9b8be0fcf8b3f2f3ab58cb418d35bedcfb2","Node name for S&R":"Runware Image Inference Settings Structured Prompt"},"widgets_values":["A 35mm photograph on Kodak Portra 400 of a monumental weathered bronze equestrian statue and a living black stallion standing shoulder-to-shoulder at dusk","Deep indigo dusk sky filling the upper frame, shallow ground mist pools across the lower frame",false,"",false,"",true,"obj","Large weathered bronze equestrian horse statue mounted on a rough-hewn stone plinth","","","",true,"obj","Real black stallion standing to the right of the statue, narrow amber strip of last sunlight along its back","","","",true,"obj","Faint wisp of condensed breath near the stallion's muzzle","","","",false,"obj","","","","",false,"obj","","","","",false,"obj","","","","",false,"obj","","","","",false,"obj","","","",""],"bgcolor":"#5345bf"}],"links":[[2,2,0,1,15,"RUNWARESETTINGS"],[3,1,0,5,0,"STRING"],[4,6,0,1,0,"RUNWAREMODEL"],[5,8,0,2,2,"RUNWAREIMAGEINFERENCESTRUCTUREDPROMPT"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.5125039258664733,"offset":[1118.3105518758753,-268.8076231786261]}},"version":0.4} \ No newline at end of file From 1b4b89f55df1f95d8c49e55af5ac7c0c3d8208aa Mon Sep 17 00:00:00 2001 From: Sirshendu Ganguly Date: Thu, 4 Jun 2026 22:57:16 +0530 Subject: [PATCH 2/3] Fixed optional params --- clientlibs/utils.js | 15 ++++++++++++++- modules/imageInference.py | 16 +++++++++++++++- .../imageInferenceSettingsStructuredPrompt.py | 14 ++++++++------ 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/clientlibs/utils.js b/clientlibs/utils.js index 0d5ac92..9919f4d 100644 --- a/clientlibs/utils.js +++ b/clientlibs/utils.js @@ -5716,6 +5716,7 @@ function imageInferenceSettingsStructuredPromptToggleHandler(node) { const useElementsJsonWidget = node.widgets.find((w) => w && w.name === "useElementsJson"); const elementsJsonWidget = node.widgets.find((w) => w && w.name === "elementsJson"); + const elementSlotRefreshers = []; if (useElementsJsonWidget && elementsJsonWidget) { toggleWidgetState(useElementsJsonWidget, elementsJsonWidget, "elementsJson"); } @@ -5730,13 +5731,16 @@ function imageInferenceSettingsStructuredPromptToggleHandler(node) { if (!useW) return; function toggleSlot() { - const enabled = useW.value === true; + const jsonMode = useElementsJsonWidget?.value === true; + toggleWidgetEnabled(useW, !jsonMode, node); + const enabled = !jsonMode && useW.value === true; [typeW, descW, textW, bboxW, paletteW].forEach((w) => { if (w) toggleWidgetEnabled(w, enabled, node); }); node.setDirtyCanvas(true); } + elementSlotRefreshers.push(toggleSlot); appendWidgetCB(useW, () => setTimeout(toggleSlot, 50)); setTimeout(toggleSlot, 100); } @@ -5744,6 +5748,15 @@ function imageInferenceSettingsStructuredPromptToggleHandler(node) { for (let i = 1; i <= 8; i++) { bindElementSlot(i); } + + if (useElementsJsonWidget) { + function refreshElementSlotsForJsonMode() { + elementSlotRefreshers.forEach((refresh) => refresh()); + node.setDirtyCanvas(true); + } + appendWidgetCB(useElementsJsonWidget, () => setTimeout(refreshElementSlotsForJsonMode, 50)); + setTimeout(refreshElementSlotsForJsonMode, 100); + } } function syncProviderSettingsToggleHandler(syncNode) { diff --git a/modules/imageInference.py b/modules/imageInference.py index 6871dcb..1aa5fb6 100644 --- a/modules/imageInference.py +++ b/modules/imageInference.py @@ -225,7 +225,21 @@ class txt2img: def VALIDATE_INPUTS(cls, **kwargs): positivePrompt = kwargs.get("positivePrompt", "") negativePrompt = kwargs.get("negativePrompt", "") - + settings = kwargs.get("settings") + + structured_prompt = None + if isinstance(settings, dict): + structured_prompt = settings.get("structuredPrompt") + has_structured_prompt = ( + isinstance(structured_prompt, dict) and len(structured_prompt) > 0 + ) + has_positive_prompt = bool(positivePrompt and str(positivePrompt).strip()) + if has_structured_prompt and has_positive_prompt: + return ( + "settings.structuredPrompt and positivePrompt are mutually exclusive. " + "Clear positivePrompt or disconnect Structured Prompt from Settings." + ) + # Only validate positivePrompt length if it's provided if positivePrompt and len(positivePrompt) > 10000: return "Positive Prompt is too long. Maximum length is 10000 characters." diff --git a/modules/imageInferenceSettingsStructuredPrompt.py b/modules/imageInferenceSettingsStructuredPrompt.py index cbdc9c9..bae80a1 100644 --- a/modules/imageInferenceSettingsStructuredPrompt.py +++ b/modules/imageInferenceSettingsStructuredPrompt.py @@ -17,11 +17,6 @@ class RunwareImageInferenceSettingsStructuredPrompt: @classmethod def INPUT_TYPES(cls): optional: Dict[str, tuple] = { - "high_level_description": ("STRING", { - "multiline": True, - "default": "", - "tooltip": "Global scene summary (required).", - }), "background": ("STRING", { "multiline": True, "default": "", @@ -81,7 +76,14 @@ class RunwareImageInferenceSettingsStructuredPrompt: "tooltip": f"Element {i} optional hex colours, comma-separated (e.g. #1F3B26,#7A5A2F).", }) - return {"required": {}, "optional": optional} + required = { + "high_level_description": ("STRING", { + "multiline": True, + "default": "", + "tooltip": "Global scene summary (required).", + }), + } + return {"required": required, "optional": optional} RETURN_TYPES = ("RUNWAREIMAGEINFERENCESTRUCTUREDPROMPT",) RETURN_NAMES = ("structuredPrompt",) From 16966342bb5fd79fcfb6308efd6447e3f44aa4ff Mon Sep 17 00:00:00 2001 From: Sirshendu Ganguly Date: Thu, 4 Jun 2026 23:17:50 +0530 Subject: [PATCH 3/3] Fixed whitespaces --- modules/imageInference.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/imageInference.py b/modules/imageInference.py index 1aa5fb6..9aca713 100644 --- a/modules/imageInference.py +++ b/modules/imageInference.py @@ -233,7 +233,9 @@ class txt2img: has_structured_prompt = ( isinstance(structured_prompt, dict) and len(structured_prompt) > 0 ) - has_positive_prompt = bool(positivePrompt and str(positivePrompt).strip()) + has_positive_prompt = bool( + positivePrompt is not None and str(positivePrompt) != "" + ) if has_structured_prompt and has_positive_prompt: return ( "settings.structuredPrompt and positivePrompt are mutually exclusive. "