Merge pull request #114 from Runware/feature-updateSettings

Added Runware Image Inference Settings and Runware Image Upscaler Settings
This commit is contained in:
Sirshendu Ganguly
2026-04-03 17:13:56 +05:30
committed by GitHub
12 changed files with 481 additions and 32 deletions
+6
View File
@@ -3,6 +3,7 @@ from .modules.outpaintSettings import outpaintSettings
from .modules.bgremoval import bgremoval
from .modules.photoMaker import photoMaker
from .modules.upscaler import upscaler
from .modules.imageUpscalerSettings import RunwareImageUpscalerSettings
from .modules.modelSearch import modelSearch
from .modules.bridges import mainRoute
from .modules.controlNet import controlNet
@@ -90,6 +91,7 @@ from .modules.videoInputsReferences import videoInputsReferences
from .modules.videoInputsFrame import RunwareVideoInputsFrameImages
from .modules.safetyInputs import safetyInputs
from .modules.settings import RunwareSettings
from .modules.imageInferenceSettingsColorPalette import RunwareImageInferenceSettingsColorPalette
from .modules.videoAdvancedFeatureInputs import videoAdvancedFeatureInputs
from .modules.advancedFeatureSettings.wanAnimateAdvancedFeatureSettings import RunwareWanAnimateAdvancedFeatureSettings
from .modules.saveImage import RunwareSaveImage
@@ -121,6 +123,7 @@ NODE_CLASS_MAPPINGS = {
"Runware Background Removal": bgremoval,
"Runware PhotoMaker V2": photoMaker,
"Runware Image Upscaler": upscaler,
"Runware Image Upscaler Settings": RunwareImageUpscalerSettings,
"Runware Model Search": modelSearch,
"Runware Kontext Inference": runwareKontext,
"Runware Imagen Inference": runwareImagen,
@@ -207,6 +210,7 @@ NODE_CLASS_MAPPINGS = {
"Runware Video Inputs Frame Images": RunwareVideoInputsFrameImages,
"Runware Safety Inputs": safetyInputs,
"Runware Settings": RunwareSettings,
"Runware Image Inference Settings Color Palette": RunwareImageInferenceSettingsColorPalette,
"Runware Video Advanced Feature Inputs": videoAdvancedFeatureInputs,
"Runware Wan Animate Advanced Feature Settings": RunwareWanAnimateAdvancedFeatureSettings,
"Runware Save Image": RunwareSaveImage,
@@ -223,6 +227,7 @@ NODE_CLASS_MAPPINGS = {
}
NODE_DISPLAY_NAME_MAPPINGS = {
"Runware Settings": "Runware Image Inference Settings",
"Runware Model Search": "Runware Model",
"Runware Lora Search": "Runware Lora",
"Runware Embedding Search": "Runware Embedding",
@@ -231,6 +236,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"Runware Video Model Search": "Runware Video Model",
"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 Video Transcription": "Runware Video Caption",
}
+7 -1
View File
@@ -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, videoUpscalerToggleHandler, audioInferenceToggleHandler, audioInferenceSpeechToggleHandler, audioSettingsToggleHandler, textInferenceSettingsToggleHandler, videoSettingsToggleHandler, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, xaiProviderSettingsToggleHandler, viduProviderSettingsToggleHandler, sourcefulProviderSettingsToggleHandler, sourcefulProviderSettingsFontsToggleHandler, threeDInferenceToggleHandler, threeDInferenceSettingsToggleHandler, threeDInferenceSettingsLatToggleHandler, ultralyticsProviderSettingsToggleHandler, openaiProviderSettingsToggleHandler, lightricksProviderSettingsToggleHandler, klingProviderSettingsToggleHandler, lumaProviderSettingsToggleHandler, briaProviderSettingsToggleHandler, pixverseProviderSettingsToggleHandler, alibabaProviderSettingsToggleHandler, mireloProviderSettingsToggleHandler, googleProviderSettingsToggleHandler, syncProviderSettingsToggleHandler, syncSegmentToggleHandler, settingsToggleHandler, audioInputToggleHandler, speechInputToggleHandler, briaProviderMaskToggleHandler, wanAnimateAdvancedFeatureSettingsToggleHandler, videoAdvancedFeatureInputsToggleHandler, audioInferenceInputsToggleHandler } 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, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, xaiProviderSettingsToggleHandler, viduProviderSettingsToggleHandler, sourcefulProviderSettingsToggleHandler, sourcefulProviderSettingsFontsToggleHandler, threeDInferenceToggleHandler, threeDInferenceSettingsToggleHandler, threeDInferenceSettingsLatToggleHandler, ultralyticsProviderSettingsToggleHandler, openaiProviderSettingsToggleHandler, lightricksProviderSettingsToggleHandler, klingProviderSettingsToggleHandler, lumaProviderSettingsToggleHandler, briaProviderSettingsToggleHandler, pixverseProviderSettingsToggleHandler, alibabaProviderSettingsToggleHandler, mireloProviderSettingsToggleHandler, googleProviderSettingsToggleHandler, syncProviderSettingsToggleHandler, syncSegmentToggleHandler, settingsToggleHandler, safetyInputsToggleHandler, imageInferenceSettingsColorPaletteToggleHandler, audioInputToggleHandler, speechInputToggleHandler, briaProviderMaskToggleHandler, wanAnimateAdvancedFeatureSettingsToggleHandler, videoAdvancedFeatureInputsToggleHandler, audioInferenceInputsToggleHandler } from "./utils.js";
import { RUNWARE_NODE_TYPES, RUNWARE_NODE_PROPS, SEARCH_TERMS } from "./types.js";
const nodeInitList = [];
@@ -75,6 +75,8 @@ app.registerExtension({
videoInferenceDimensionsHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.UPSCALER) {
upscalerToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.IMAGEUPSCALERSETTINGS) {
imageUpscalerSettingsToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.VIDEOUPSCALER) {
videoUpscalerToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.AUDIOINFERENCE) {
@@ -133,6 +135,10 @@ app.registerExtension({
sourcefulProviderSettingsFontsToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.SETTINGS) {
settingsToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.SAFETYINPUTS) {
safetyInputsToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.IMAGEINFERENCESETTINGSCOLORPALETTE) {
imageInferenceSettingsColorPaletteToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.AUDIOINPUT) {
audioInputToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.SPEECHINPUT) {
+10
View File
@@ -61,6 +61,7 @@ const RUNWARE_NODE_TYPES = {
CONTROLNET: "Runware ControlNet",
BGREMOVAL: "Runware Background Removal",
UPSCALER: "Runware Image Upscaler",
IMAGEUPSCALERSETTINGS: "Runware Image Upscaler Settings",
REFINER: "Runware Refiner",
LORACOMBINE: "Runware Lora Combine",
CONTROLNETCOMBINE: "Runware ControlNet Combine",
@@ -138,6 +139,7 @@ const RUNWARE_NODE_TYPES = {
MINIMAXPROVIDERSETTINGS: "Runware MiniMax Provider Settings",
SAFETYINPUTS: "Runware Safety Inputs",
SETTINGS: "Runware Settings",
IMAGEINFERENCESETTINGSCOLORPALETTE: "Runware Image Inference Settings Color Palette",
VIDEOADVANCEDFEATUREINPUTS: "Runware Video Advanced Feature Inputs",
WANANIMATEADVANCEDFEATURESETTINGS: "Runware Wan Animate Advanced Feature Settings",
SAVEIMAGE: "Runware Save Image",
@@ -231,6 +233,10 @@ const RUNWARE_NODE_PROPS = {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
},
[RUNWARE_NODE_TYPES.IMAGEUPSCALERSETTINGS]: {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
},
[RUNWARE_NODE_TYPES.REFINER]: {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
@@ -526,6 +532,10 @@ const RUNWARE_NODE_PROPS = {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
},
[RUNWARE_NODE_TYPES.IMAGEINFERENCESETTINGSCOLORPALETTE]: {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
},
[RUNWARE_NODE_TYPES.VIDEOADVANCEDFEATUREINPUTS]: {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
+196
View File
@@ -987,6 +987,8 @@ function useParameterToggleHandler(node) {
function upscalerToggleHandler(upscalerNode) {
// Find all "use" parameter widgets for Upscaler
const useUpscaleFactorWidget = upscalerNode.widgets.find(w => w.name === "useUpscaleFactor");
const upscaleFactorWidget = upscalerNode.widgets.find(w => w.name === "upscaleFactor");
const useStepsWidget = upscalerNode.widgets.find(w => w.name === "useSteps");
const stepsWidget = upscalerNode.widgets.find(w => w.name === "steps");
const useSeedWidget = upscalerNode.widgets.find(w => w.name === "useSeed");
@@ -1054,6 +1056,10 @@ function upscalerToggleHandler(upscalerNode) {
}
// Set up all toggle handlers
if (useUpscaleFactorWidget && upscaleFactorWidget) {
toggleWidgetState(useUpscaleFactorWidget, [upscaleFactorWidget], ["upscaleFactor"]);
}
if (useStepsWidget && stepsWidget) {
toggleWidgetState(useStepsWidget, [stepsWidget], ["steps"]);
}
@@ -1081,6 +1087,63 @@ function upscalerToggleHandler(upscalerNode) {
if (useLatentParamsWidget && clipSkipWidget) {
toggleWidgetState(useLatentParamsWidget, [clipSkipWidget], ["clipSkip"]);
}
const useTargetMegapixelsWidget = upscalerNode.widgets.find(w => w.name === "useTargetMegapixels");
const targetMegapixelsWidget = upscalerNode.widgets.find(w => w.name === "targetMegapixels");
if (useTargetMegapixelsWidget && targetMegapixelsWidget) {
toggleWidgetState(useTargetMegapixelsWidget, [targetMegapixelsWidget], ["targetMegapixels"]);
}
}
function imageUpscalerSettingsToggleHandler(settingsNode) {
const useEnhanceDetailsWidget = settingsNode.widgets.find(w => w.name === "useEnhanceDetails");
const enhanceDetailsWidget = settingsNode.widgets.find(w => w.name === "enhanceDetails");
const useRealismWidget = settingsNode.widgets.find(w => w.name === "useRealism");
const realismWidget = settingsNode.widgets.find(w => w.name === "realism");
function toggleWidgetState(useWidget, paramWidget, paramName) {
if (!useWidget || !paramWidget) return;
function toggleEnabled() {
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 ? "pointer" : "not-allowed";
}
paramWidget.disabled = !enabled;
if (!paramWidget.inputEl) {
const nodeElement = settingsNode.htmlElements?.widgetsContainer || settingsNode.htmlElements;
if (nodeElement && paramName) {
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 ? "pointer" : "not-allowed";
}
}
}
settingsNode.setDirtyCanvas(true);
}
appendWidgetCB(useWidget, () => {
setTimeout(toggleEnabled, 50);
});
setTimeout(toggleEnabled, 100);
}
if (useEnhanceDetailsWidget && enhanceDetailsWidget) {
toggleWidgetState(useEnhanceDetailsWidget, enhanceDetailsWidget, "enhanceDetails");
}
if (useRealismWidget && realismWidget) {
toggleWidgetState(useRealismWidget, realismWidget, "realism");
}
}
function audioInferenceToggleHandler(audioInferenceNode) {
@@ -4394,6 +4457,7 @@ export {
videoInferenceSpeechInputToggleHandler,
regionalPromptingRegionsToggleHandler,
upscalerToggleHandler,
imageUpscalerSettingsToggleHandler,
videoUpscalerToggleHandler,
audioInferenceToggleHandler,
audioInferenceSpeechToggleHandler,
@@ -4422,6 +4486,8 @@ export {
syncProviderSettingsToggleHandler,
syncSegmentToggleHandler,
settingsToggleHandler,
safetyInputsToggleHandler,
imageInferenceSettingsColorPaletteToggleHandler,
audioInputToggleHandler,
speechInputToggleHandler,
briaProviderMaskToggleHandler,
@@ -4514,6 +4580,12 @@ function settingsToggleHandler(settingsNode) {
const qualityWidget = settingsNode.widgets.find(w => w.name === "quality");
const usePromptExtendWidget = settingsNode.widgets.find(w => w.name === "usePromptExtend");
const promptExtendWidget = settingsNode.widgets.find(w => w.name === "promptExtend");
const useEditRegionsWidget = settingsNode.widgets.find(w => w.name === "useEditRegions");
const editRegionsWidget = settingsNode.widgets.find(w => w.name === "editRegions");
const useThinkingWidget = settingsNode.widgets.find(w => w.name === "useThinking");
const thinkingWidget = settingsNode.widgets.find(w => w.name === "thinking");
const useSequentialWidget = settingsNode.widgets.find(w => w.name === "useSequential");
const sequentialWidget = settingsNode.widgets.find(w => w.name === "sequential");
// Helper function to toggle widget enabled state
function toggleWidgetState(useWidget, paramWidget, paramName) {
@@ -4579,6 +4651,130 @@ function settingsToggleHandler(settingsNode) {
if (usePromptExtendWidget && promptExtendWidget) {
toggleWidgetState(usePromptExtendWidget, promptExtendWidget, "promptExtend");
}
if (useEditRegionsWidget && editRegionsWidget) {
toggleWidgetState(useEditRegionsWidget, editRegionsWidget, "editRegions");
}
if (useThinkingWidget && thinkingWidget) {
toggleWidgetState(useThinkingWidget, thinkingWidget, "thinking");
}
if (useSequentialWidget && sequentialWidget) {
toggleWidgetState(useSequentialWidget, sequentialWidget, "sequential");
}
}
function safetyInputsToggleHandler(safetyNode) {
const useModeWidget = safetyNode.widgets.find(w => w.name === "useMode");
const modeWidget = safetyNode.widgets.find(w => w.name === "mode");
const useToleranceWidget = safetyNode.widgets.find(w => w.name === "useTolerance");
const toleranceWidget = safetyNode.widgets.find(w => w.name === "tolerance");
const useCheckInputsWidget = safetyNode.widgets.find(w => w.name === "useCheckInputs");
const checkInputsWidget = safetyNode.widgets.find(w => w.name === "checkInputs");
const useCheckContentWidget = safetyNode.widgets.find(w => w.name === "useCheckContent");
const checkContentWidget = safetyNode.widgets.find(w => w.name === "checkContent");
function toggleWidgetState(useWidget, paramWidget, paramName) {
if (!useWidget || !paramWidget) return;
function toggleEnabled() {
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 = safetyNode.htmlElements?.widgetsContainer || safetyNode.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;
if (input.tagName === "SELECT") {
input.style.pointerEvents = enabled ? "auto" : "none";
}
}
}
}
safetyNode.setDirtyCanvas(true);
}
appendWidgetCB(useWidget, () => {
setTimeout(toggleEnabled, 50);
});
setTimeout(toggleEnabled, 100);
}
if (useModeWidget && modeWidget) {
toggleWidgetState(useModeWidget, modeWidget, "mode");
}
if (useToleranceWidget && toleranceWidget) {
toggleWidgetState(useToleranceWidget, toleranceWidget, "tolerance");
}
if (useCheckInputsWidget && checkInputsWidget) {
toggleWidgetState(useCheckInputsWidget, checkInputsWidget, "checkInputs");
}
if (useCheckContentWidget && checkContentWidget) {
toggleWidgetState(useCheckContentWidget, checkContentWidget, "checkContent");
}
}
function imageInferenceSettingsColorPaletteToggleHandler(paletteNode) {
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 = paletteNode.htmlElements?.widgetsContainer || paletteNode.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 bindSlot(i) {
const useW = paletteNode.widgets.find((w) => w.name === `use_${i}`);
const hexW = paletteNode.widgets.find((w) => w.name === `hex_${i}`);
const ratioW = paletteNode.widgets.find((w) => w.name === `ratio_${i}`);
if (!useW || !hexW || !ratioW) return;
function toggleSlot() {
applyParamState(useW, hexW, `hex_${i}`);
applyParamState(useW, ratioW, `ratio_${i}`);
paletteNode.setDirtyCanvas(true);
}
appendWidgetCB(useW, () => {
setTimeout(toggleSlot, 50);
});
setTimeout(toggleSlot, 100);
}
for (let i = 1; i <= 8; i++) {
bindSlot(i);
}
}
function syncProviderSettingsToggleHandler(syncNode) {
+1 -1
View File
@@ -189,7 +189,7 @@ class txt2img:
"tooltip": "Connect Runware Safety Inputs node to configure safety and content moderation settings.",
}),
"settings": ("RUNWARESETTINGS", {
"tooltip": "Connect Runware Settings node to configure temperature, systemPrompt, and topP parameters.",
"tooltip": "Connect Runware Image Inference Settings for temperature, systemPrompt, topP, layers, quality, promptExtend, editRegions (JSON), thinking, sequential, colorPalette (via Color Palette node), etc.",
}),
"ultralytics": ("RUNWAREULTRALYTICSINPUTS", {
"tooltip": "Connect Runware Image Inference Ultralytics node to configure Ultralytics parameters (maskBlur, maskPadding, confidence, prompts, steps, CFGScale, strength).",
@@ -0,0 +1,59 @@
"""
Runware Image Inference Settings Color Palette
Builds settings.colorPalette: list of { "hex": "#...", "ratio": "NN.NN%" } for Runware Image Inference Settings.
"""
from typing import Any, Dict, List, Tuple
class RunwareImageInferenceSettingsColorPalette:
"""Up to 8 hex/ratio pairs; each slot is included only when use_{i} is enabled."""
_SLOTS = 8
@classmethod
def INPUT_TYPES(cls):
optional: Dict[str, tuple] = {}
for i in range(1, cls._SLOTS + 1):
optional[f"use_{i}"] = ("BOOLEAN", {
"default": False,
"label_on": "Enabled",
"label_off": "Disabled",
"tooltip": f"Include swatch {i} in the output colorPalette.",
})
optional[f"hex_{i}"] = ("STRING", {
"default": "",
"tooltip": f"Swatch {i} hex, e.g. #C2D1E6. Required when use_{i} is enabled.",
})
optional[f"ratio_{i}"] = ("STRING", {
"default": "",
"tooltip": f"Swatch {i} ratio, e.g. 23.51%%. Optional.",
})
return {"required": {}, "optional": optional}
RETURN_TYPES = ("RUNWAREIMAGEINFERENCECOLORPALETTE",)
RETURN_NAMES = ("colorPalette",)
FUNCTION = "build_palette"
CATEGORY = "Runware"
DESCRIPTION = (
"Build a colorPalette list for image inference settings (hex + optional ratio per swatch). "
"Enable use_1…use_8 for each swatch to include; connect the output to Runware Image Inference Settings."
)
def build_palette(self, **kwargs) -> Tuple[List[Dict[str, Any]]]:
out: List[Dict[str, Any]] = []
for i in range(1, self._SLOTS + 1):
if not kwargs.get(f"use_{i}", False):
continue
hx = str(kwargs.get(f"hex_{i}") or "").strip()
if not hx:
raise ValueError(
f"use_{i} is enabled but hex_{i} is empty or invalid. "
"Provide a hex color (e.g. #C2D1E6) or disable this swatch."
)
ratio = str(kwargs.get(f"ratio_{i}") or "").strip()
entry: Dict[str, Any] = {"hex": hx}
if ratio:
entry["ratio"] = ratio
out.append(entry)
return (out,)
+61
View File
@@ -0,0 +1,61 @@
"""
Runware Image Upscaler Settings — builds settings (enhanceDetails, realism). Connect to Runware Image Upscaler.
"""
from typing import Any, Dict, Tuple
class RunwareImageUpscalerSettings:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {},
"optional": {
"useEnhanceDetails": ("BOOLEAN", {
"default": False,
"label_on": "Enabled",
"label_off": "Disabled",
"tooltip": "Include settings.enhanceDetails in the upscale request.",
}),
"enhanceDetails": ("BOOLEAN", {
"default": False,
"label_on": "true",
"label_off": "false",
"tooltip": "Enhance fine textures and small details. May increase contrast and introduce minor deviations from the original.",
}),
"useRealism": ("BOOLEAN", {
"default": False,
"label_on": "Enabled",
"label_off": "Disabled",
"tooltip": "Include settings.realism in the upscale request.",
}),
"realism": ("BOOLEAN", {
"default": True,
"label_on": "true",
"label_off": "false",
"tooltip": "Improve realism. May deviate more from the original. Recommended for AI-generated images.",
}),
},
}
RETURN_TYPES = ("RUNWAREIMAGEUPSCALERSETTINGS",)
RETURN_NAMES = ("Upscaler Settings",)
FUNCTION = "build_settings"
CATEGORY = "Runware"
DESCRIPTION = (
"Optional settings.enhanceDetails and settings.realism for image upscale. "
"Connect to Runware Image Upscaler."
)
def build_settings(self, **kwargs) -> Tuple[Dict[str, Any]]:
out: Dict[str, Any] = {}
settings: Dict[str, Any] = {}
if kwargs.get("useEnhanceDetails", False):
settings["enhanceDetails"] = bool(kwargs.get("enhanceDetails", False))
if kwargs.get("useRealism", False):
settings["realism"] = bool(kwargs.get("realism", True))
if settings:
out["settings"] = settings
return (out,)
+27 -7
View File
@@ -9,25 +9,41 @@ class safetyInputs:
return {
"required": {},
"optional": {
"useMode": ("BOOLEAN", {
"tooltip": "Enable to include mode in payload.",
"default": False,
}),
"mode": (["none", "fast", "full"], {
"tooltip": "Safety moderation mode: none (disable), fast (quick check), or full (comprehensive check).",
"default": "none",
}),
"useTolerance": ("BOOLEAN", {
"tooltip": "Enable to include tolerance in payload.",
"default": False,
}),
"tolerance": ("BOOLEAN", {
"tooltip": "Safety tolerance setting for content moderation.",
"default": None,
"default": False,
"label_on": "Enabled",
"label_off": "Disabled",
}),
"useCheckInputs": ("BOOLEAN", {
"tooltip": "Enable to include checkInputs in payload.",
"default": False,
}),
"checkInputs": ("BOOLEAN", {
"tooltip": "Enable checking of input content for safety violations.",
"default": None,
"default": False,
"label_on": "Enabled",
"label_off": "Disabled",
}),
"useCheckContent": ("BOOLEAN", {
"tooltip": "Enable to include checkContent in payload.",
"default": False,
}),
"checkContent": ("BOOLEAN", {
"tooltip": "Enable checking of generated content for safety violations.",
"default": None,
"default": False,
"label_on": "Enabled",
"label_off": "Disabled",
}),
@@ -42,20 +58,24 @@ class safetyInputs:
def createSafetyInputs(self, **kwargs) -> tuple[Dict[str, Any]]:
"""Create safety inputs dictionary"""
useMode = kwargs.get("useMode", False)
mode = kwargs.get("mode", None)
useTolerance = kwargs.get("useTolerance", False)
tolerance = kwargs.get("tolerance", None)
useCheckInputs = kwargs.get("useCheckInputs", False)
checkInputs = kwargs.get("checkInputs", None)
useCheckContent = kwargs.get("useCheckContent", False)
checkContent = kwargs.get("checkContent", None)
safetyInputs = {}
if mode is not None:
if useMode and mode is not None:
safetyInputs["mode"] = mode
if tolerance is not None:
if useTolerance and tolerance is not None:
safetyInputs["tolerance"] = tolerance
if checkInputs is not None:
if useCheckInputs and checkInputs is not None:
safetyInputs["checkInputs"] = checkInputs
if checkContent is not None:
if useCheckContent and checkContent is not None:
safetyInputs["checkContent"] = checkContent
return (safetyInputs,)
+69 -17
View File
@@ -1,13 +1,15 @@
"""
Runware Settings Node
Provides general settings for image generation including temperature, systemPrompt, and topP
Runware Image Inference Settings (registered as Runware Settings for workflow compatibility).
Provides settings for image generation including temperature, systemPrompt, topP,
editRegions, thinking, sequential, and colorPalette (from Runware Image Inference Settings Color Palette).
"""
from typing import Optional, Dict, Any
import json
from typing import Any, Dict, List, Optional
class RunwareSettings:
"""Runware Settings Node"""
"""Runware Image Inference Settings node (display name); API registration key remains Runware Settings."""
@classmethod
def INPUT_TYPES(cls):
@@ -84,6 +86,37 @@ class RunwareSettings:
"label_on": "true",
"label_off": "false",
}),
"useEditRegions": ("BOOLEAN", {
"tooltip": "Enable to include editRegions in settings (per-input-image bounding boxes for edit flows).",
"default": False,
}),
"editRegions": ("STRING", {
"multiline": True,
"tooltip": "JSON array: one entry per input image; each entry is a list of boxes [x1,y1,x2,y2]. Example: [[[0,0,12,12],[25,25,100,100]],[],[[10,10,50,50]]]",
"default": "",
}),
"useThinking": ("BOOLEAN", {
"tooltip": "Enable to include thinking (string) in settings.",
"default": False,
}),
"thinking": ("STRING", {
"multiline": True,
"tooltip": "Thinking / reasoning string passed in settings. Only used when 'Use Thinking' is enabled.",
"default": "",
}),
"useSequential": ("BOOLEAN", {
"tooltip": "Enable to include sequential (boolean) in settings.",
"default": False,
}),
"sequential": ("BOOLEAN", {
"tooltip": "Sequential / image-set mode flag. Only used when 'Use Sequential' is enabled.",
"default": False,
"label_on": "true",
"label_off": "false",
}),
"colorPalette": ("RUNWAREIMAGEINFERENCECOLORPALETTE", {
"tooltip": "Connect Runware Image Inference Color Palette. When the palette node outputs at least one swatch, it is merged into settings.colorPalette.",
}),
}
}
@@ -91,7 +124,10 @@ class RunwareSettings:
RETURN_NAMES = ("Settings",)
FUNCTION = "createSettings"
CATEGORY = "Runware"
DESCRIPTION = "Configure general settings for image generation including temperature, system prompt, and top-p sampling."
DESCRIPTION = (
"Configure general settings for image generation: temperature, system prompt, top-p, layers, quality, "
"promptExtend, editRegions (JSON), thinking, sequential, and optional colorPalette from the Color Palette node."
)
def createSettings(self, **kwargs) -> tuple[Dict[str, Any]]:
"""Create settings configuration"""
@@ -103,8 +139,11 @@ class RunwareSettings:
useLayers = kwargs.get("useLayers", False)
useTrueCFGScale = kwargs.get("useTrueCFGScale", False)
useQuality = kwargs.get("useQuality", False)
usePromptExtend = kwargs.get("usePromptExtend", True)
promptExtend = kwargs.get("promptExtend", True)
usePromptExtend = kwargs.get("usePromptExtend", False)
promptExtend = kwargs.get("promptExtend", False)
useEditRegions = kwargs.get("useEditRegions", False)
useThinking = kwargs.get("useThinking", False)
useSequential = kwargs.get("useSequential", False)
# Get value parameters
temperature = kwargs.get("temperature", 1.0)
@@ -133,18 +172,31 @@ class RunwareSettings:
if usePromptExtend:
settings["promptExtend"] = bool(promptExtend)
if useEditRegions:
raw_er = (kwargs.get("editRegions") or "").strip()
if raw_er:
try:
parsed = json.loads(raw_er)
except json.JSONDecodeError as e:
raise ValueError(f"editRegions must be valid JSON: {e}") from e
if not isinstance(parsed, list):
raise ValueError("editRegions JSON must be an array (one element per input image).")
settings["editRegions"] = parsed
if useThinking:
th = (kwargs.get("thinking") or "").strip()
if th:
settings["thinking"] = th
if useSequential:
settings["sequential"] = bool(kwargs.get("sequential", False))
palette: Optional[List[Dict[str, Any]]] = kwargs.get("colorPalette")
if palette is not None and isinstance(palette, list) and len(palette) > 0:
settings["colorPalette"] = palette
# Clean up None values
settings = {k: v for k, v in settings.items() if v is not None}
return (settings,)
# Node class mappings
NODE_CLASS_MAPPINGS = {
"RunwareSettings": RunwareSettings,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"RunwareSettings": "Runware Settings",
}
+43 -6
View File
@@ -8,13 +8,32 @@ class upscaler:
"Image": ("IMAGE", {
"tooltip": "Specifies the input image to be upscaled."
}),
"useUpscaleFactor": ("BOOLEAN", {
"tooltip": "Include upscaleFactor in the upscale request.",
"default": True,
"label_on": "Enabled",
"label_off": "Disabled",
}),
"upscaleFactor": ("INT", {
"tooltip": "Each level will increase the size of the image by the corresponding factor.",
"tooltip": "Each level will increase the size of the image by the corresponding factor. Only used when 'Use Upscale Factor' is enabled.",
"default": 2,
"min": 1,
"max": 8,
"step": 1,
}),
"useTargetMegapixels": ("BOOLEAN", {
"tooltip": "Enable targetMegapixels (root-level) on the upscale request.",
"default": False,
"label_on": "Enabled",
"label_off": "Disabled",
}),
"targetMegapixels": ("INT", {
"tooltip": "Target resolution in megapixels (1–8). Only used when 'Use Target Megapixels' is enabled.",
"default": 4,
"min": 1,
"max": 8,
"step": 1,
}),
},
"optional": {
"model": ("STRING", {
@@ -114,7 +133,7 @@ class upscaler:
"max": 2,
}),
"safetyInputs": ("RUNWARESAFETYINPUTS", {
"tooltip": "Connect Runware Safety Inputs node to configure safety and content moderation settings.",
"tooltip": "Connect Runware Safety Inputs node to include safety settings in the upscale request.",
}),
"Accelerator": ("RUNWAREACCELERATOR", {
"tooltip": "Connect a Runware Accelerator Options Node to configure caching and acceleration settings.",
@@ -122,6 +141,9 @@ class upscaler:
"providerSettings": ("RUNWAREPROVIDERSETTINGS", {
"tooltip": "Connect a Runware Provider Settings node to configure provider-specific parameters.",
}),
"imageUpscalerSettings": ("RUNWAREIMAGEUPSCALERSETTINGS", {
"tooltip": "Connect Runware Image Upscaler Settings for settings.enhanceDetails and settings.realism.",
}),
},
}
@@ -133,8 +155,8 @@ class upscaler:
def upscale(self, **kwargs):
image = kwargs.get("Image")
upscaleFactor = int(kwargs.get("upscaleFactor", 2))
useUpscaleFactor = kwargs.get("useUpscaleFactor", True)
# Get toggle parameters
useSteps = kwargs.get("useSteps", False)
useSeed = kwargs.get("useSeed", False)
@@ -160,21 +182,28 @@ class upscaler:
safetyInputs = kwargs.get("safetyInputs", None)
runwareAccelerator = kwargs.get("Accelerator", None)
providerSettings = kwargs.get("providerSettings", None)
imageUpscalerSettingsBundle = kwargs.get("imageUpscalerSettings", None)
useTargetMegapixels = kwargs.get("useTargetMegapixels", False)
# Build the base configuration
genConfig = {
"taskType": "imageUpscale",
"taskUUID": rwUtils.genRandUUID(),
"inputImage": rwUtils.convertTensor2IMG(image),
"upscaleFactor": int(upscaleFactor),
"outputFormat": rwUtils.OUTPUT_FORMAT,
"outputQuality": rwUtils.OUTPUT_QUALITY,
"outputType": "URL",
}
if useUpscaleFactor:
genConfig["upscaleFactor"] = int(kwargs.get("upscaleFactor", 2))
# Add model if specified
if model:
genConfig["model"] = model
if useTargetMegapixels:
genConfig["targetMegapixels"] = int(kwargs.get("targetMegapixels", 4))
# Add common parameters at top level - only add if their toggle is enabled
if useSteps:
@@ -206,11 +235,19 @@ class upscaler:
# Latent upscaler specific parameters
if useLatentParams:
settings["clipSkip"] = clipSkip
if (
imageUpscalerSettingsBundle is not None
and isinstance(imageUpscalerSettingsBundle, dict)
and "settings" in imageUpscalerSettingsBundle
and isinstance(imageUpscalerSettingsBundle["settings"], dict)
):
settings.update(imageUpscalerSettingsBundle["settings"])
# Add settings to config if any settings were specified
if settings:
genConfig["settings"] = settings
# Add safety inputs if provided
if safetyInputs is not None and isinstance(safetyInputs, dict) and len(safetyInputs) > 0:
genConfig["safety"] = safetyInputs
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long