Merge pull request #90 from Runware/feature-SourcefulProviderSettings

Add Sourceful provider Settings
This commit is contained in:
Sirshendu Ganguly
2026-02-09 10:53:32 -05:00
committed by GitHub
9 changed files with 295 additions and 2 deletions
+4
View File
@@ -61,6 +61,8 @@ from .modules.providerSettings.alibabaProviderSettings import RunwareAlibabaProv
from .modules.providerSettings.googleProviderSettings import RunwareGoogleProviderSettings
from .modules.providerSettings.blackForestProviderSettings import RunwareBlackForestProviderSettings
from .modules.providerSettings.xaiProviderSettings import RunwareXAIProviderSettings
from .modules.providerSettings.sourcefulProviderSettings import RunwareSourcefulProviderSettings
from .modules.providerSettings.sourcefulProviderSettingsFonts import RunwareSourcefulProviderSettingsFonts
from .modules.ultralyticsInputs import RunwareUltralyticsInputs
from .modules.providerSettings.syncSegment import RunwareSyncSegment
from .modules.providerSettings.syncProviderSettings import RunwareSyncProviderSettings
@@ -153,6 +155,8 @@ NODE_CLASS_MAPPINGS = {
"Runware Google Provider Settings": RunwareGoogleProviderSettings,
"Runware BlackForest Labs Provider Settings": RunwareBlackForestProviderSettings,
"Runware xAI Provider Settings": RunwareXAIProviderSettings,
"Runware Sourceful Provider Settings": RunwareSourcefulProviderSettings,
"Runware Sourceful Provider Settings Fonts": RunwareSourcefulProviderSettingsFonts,
"Runware Image Inference Ultralytics": RunwareUltralyticsInputs,
"Runware Sync Segment": RunwareSyncSegment,
"Runware Sync Provider Settings": RunwareSyncProviderSettings,
+5 -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, mediaUUIDHandler, save3DFilepathHandler, videoTranscriptionHandler, videoOutputsHandler, handleCustomErrors, videoInferenceDimensionsHandler, videoModelSearchFilterHandler, audioModelSearchFilterHandler, useParameterToggleHandler, imageInferenceToggleHandler, upscalerToggleHandler, videoUpscalerToggleHandler, audioInferenceToggleHandler, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, xaiProviderSettingsToggleHandler, viduProviderSettingsToggleHandler, 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, mediaUUIDHandler, save3DFilepathHandler, videoTranscriptionHandler, videoOutputsHandler, handleCustomErrors, videoInferenceDimensionsHandler, videoModelSearchFilterHandler, audioModelSearchFilterHandler, useParameterToggleHandler, imageInferenceToggleHandler, upscalerToggleHandler, videoUpscalerToggleHandler, audioInferenceToggleHandler, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, xaiProviderSettingsToggleHandler, viduProviderSettingsToggleHandler, sourcefulProviderSettingsToggleHandler, sourcefulProviderSettingsFontsToggleHandler, ultralyticsProviderSettingsToggleHandler, openaiProviderSettingsToggleHandler, lightricksProviderSettingsToggleHandler, klingProviderSettingsToggleHandler, lumaProviderSettingsToggleHandler, briaProviderSettingsToggleHandler, pixverseProviderSettingsToggleHandler, alibabaProviderSettingsToggleHandler, mireloProviderSettingsToggleHandler, googleProviderSettingsToggleHandler, syncProviderSettingsToggleHandler, syncSegmentToggleHandler, settingsToggleHandler, audioInputToggleHandler, speechInputToggleHandler, briaProviderMaskToggleHandler, wanAnimateAdvancedFeatureSettingsToggleHandler, videoAdvancedFeatureInputsToggleHandler, audioInferenceInputsToggleHandler } from "./utils.js";
import { RUNWARE_NODE_TYPES, RUNWARE_NODE_PROPS, SEARCH_TERMS } from "./types.js";
const nodeInitList = [];
@@ -110,6 +110,10 @@ app.registerExtension({
syncSegmentToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.VIDUPROVIDERSETTINGS) {
viduProviderSettingsToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.SOURCEFULPROVIDERSETTINGS) {
sourcefulProviderSettingsToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.SOURCEFULPROVIDERSETTINGSFONTS) {
sourcefulProviderSettingsFontsToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.SETTINGS) {
settingsToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.AUDIOINPUT) {
+10
View File
@@ -107,6 +107,8 @@ const RUNWARE_NODE_TYPES = {
ALIBABAPROVIDERSETTINGS: "Runware Alibaba Provider Settings",
BLACKFORESTPROVIDERSETTINGS: "Runware BlackForest Labs Provider Settings",
XAIPROVIDERSETTINGS: "Runware xAI Provider Settings",
SOURCEFULPROVIDERSETTINGS: "Runware Sourceful Provider Settings",
SOURCEFULPROVIDERSETTINGSFONTS: "Runware Sourceful Provider Settings Fonts",
ULTRALYTICSINPUTS: "Runware Image Inference Ultralytics",
GOOGLEPROVIDERSETTINGS: "Runware Google Provider Settings",
SYNCSEGMENT: "Runware Sync Segment",
@@ -370,6 +372,14 @@ const RUNWARE_NODE_PROPS = {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
},
[RUNWARE_NODE_TYPES.SOURCEFULPROVIDERSETTINGS]: {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
},
[RUNWARE_NODE_TYPES.SOURCEFULPROVIDERSETTINGSFONTS]: {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
},
[RUNWARE_NODE_TYPES.ULTRALYTICSINPUTS]: {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
+106
View File
@@ -1449,6 +1449,110 @@ function viduProviderSettingsToggleHandler(viduNode) {
}
}
function sourcefulProviderSettingsToggleHandler(sourcefulNode) {
const useTransparencyWidget = sourcefulNode.widgets.find(w => w.name === "useTransparency");
const transparencyWidget = sourcefulNode.widgets.find(w => w.name === "transparency");
const useEnhancePromptWidget = sourcefulNode.widgets.find(w => w.name === "useEnhancePrompt");
const enhancePromptWidget = sourcefulNode.widgets.find(w => w.name === "enhancePrompt");
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 = sourcefulNode.htmlElements?.widgetsContainer || sourcefulNode.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.pointerEvents = enabled ? "auto" : "none";
}
}
}
sourcefulNode.setDirtyCanvas(true);
}
appendWidgetCB(useWidget, () => {
setTimeout(toggleEnabled, 50);
});
setTimeout(toggleEnabled, 100);
}
if (useTransparencyWidget && transparencyWidget) {
toggleWidgetState(useTransparencyWidget, transparencyWidget, "transparency");
}
if (useEnhancePromptWidget && enhancePromptWidget) {
toggleWidgetState(useEnhancePromptWidget, enhancePromptWidget, "enhancePrompt");
}
}
function sourcefulProviderSettingsFontsToggleHandler(fontsNode) {
const useFont1Widget = fontsNode.widgets.find(w => w.name === "useFont1");
const fontUrl1Widget = fontsNode.widgets.find(w => w.name === "fontUrl1");
const text1Widget = fontsNode.widgets.find(w => w.name === "text1");
const useFont2Widget = fontsNode.widgets.find(w => w.name === "useFont2");
const fontUrl2Widget = fontsNode.widgets.find(w => w.name === "fontUrl2");
const text2Widget = fontsNode.widgets.find(w => w.name === "text2");
function toggleFontGroup(useWidget, fontUrlWidget, textWidget, fontParamName, textParamName) {
if (!useWidget || !fontUrlWidget || !textWidget) return;
function toggleEnabled() {
const enabled = useWidget.value === true;
[fontUrlWidget, textWidget].forEach(paramWidget => {
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;
});
const nodeElement = fontsNode.htmlElements?.widgetsContainer || fontsNode.htmlElements;
if (nodeElement) {
[fontParamName, textParamName].forEach(paramName => {
const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"]`);
if (input) {
input.disabled = !enabled;
input.style.opacity = enabled ? "1" : "0.5";
input.style.pointerEvents = enabled ? "auto" : "none";
}
});
}
fontsNode.setDirtyCanvas(true);
}
appendWidgetCB(useWidget, () => {
setTimeout(toggleEnabled, 50);
});
setTimeout(toggleEnabled, 100);
}
if (useFont1Widget && fontUrl1Widget && text1Widget) {
toggleFontGroup(useFont1Widget, fontUrl1Widget, text1Widget, "fontUrl1", "text1");
}
if (useFont2Widget && fontUrl2Widget && text2Widget) {
toggleFontGroup(useFont2Widget, fontUrl2Widget, text2Widget, "fontUrl2", "text2");
}
}
function openaiProviderSettingsToggleHandler(openaiNode) {
// Find all "use" parameter widgets for OpenAI Provider Settings (these are COMBO widgets)
const useBackgroundWidget = openaiNode.widgets.find(w => w.name === "useBackground");
@@ -3440,6 +3544,8 @@ export {
bytedanceProviderSettingsToggleHandler,
xaiProviderSettingsToggleHandler,
viduProviderSettingsToggleHandler,
sourcefulProviderSettingsToggleHandler,
sourcefulProviderSettingsFontsToggleHandler,
ultralyticsProviderSettingsToggleHandler,
openaiProviderSettingsToggleHandler,
lightricksProviderSettingsToggleHandler,
+1 -1
View File
@@ -378,7 +378,7 @@ class txt2img:
if isinstance(providerSettings, dict):
# Check if providerSettings already has a provider key (e.g., {"alibaba": {...}})
if any(key in providerSettings for key in ["alibaba", "bytedance", "klingai", "openai", "pixverse",
"bria", "lightricks", "luma", "minimax", "runway", "vidu", "elevenlabs", "bfl", "xai"]):
"bria", "lightricks", "luma", "minimax", "runway", "vidu", "elevenlabs", "bfl", "xai", "sourceful"]):
final_provider_settings = providerSettings
else:
# Otherwise, wrap with the extracted provider name
+20
View File
@@ -5,6 +5,7 @@ class imageInferenceInputs:
"""Image Inference Inputs node for configuring image generation inputs"""
MAX_REFERENCE_IMAGES = 14
MAX_SUPER_RESOLUTION_REFERENCE_IMAGES = 5
@classmethod
def INPUT_TYPES(cls):
@@ -27,6 +28,12 @@ class imageInferenceInputs:
"default": "",
})
for i in range(1, cls.MAX_SUPER_RESOLUTION_REFERENCE_IMAGES + 1):
ordinal = rwUtils.getOrdinal(i)
optionalInputs[f"Super Resolution Reference Image {i}"] = ("IMAGE", {
"tooltip": f"Specifies {ordinal.capitalize()} Super Resolution Reference Image for the inputs.",
})
return {
"required": {},
"optional": optionalInputs
@@ -54,6 +61,10 @@ class imageInferenceInputs:
if len(references) > 0:
inputs["referenceImages"] = references
super_resolution_refs = self._collectSuperResolutionReferences(kwargs)
if len(super_resolution_refs) > 0:
inputs["superResolutionReferenceImages"] = super_resolution_refs
return (inputs,)
def _collectReferences(self, kwargs):
@@ -91,3 +102,12 @@ class imageInferenceInputs:
references.append(entry)
return references
def _collectSuperResolutionReferences(self, kwargs):
"""Collect and convert super resolution reference images to list (same pattern as referenceImages)"""
images = []
for i in range(1, self.MAX_SUPER_RESOLUTION_REFERENCE_IMAGES + 1):
image = kwargs.get(f"Super Resolution Reference Image {i}", None)
if image is not None:
images.append(rwUtils.convertTensor2IMG(image))
return images
@@ -0,0 +1,72 @@
"""
Runware Sourceful Provider Settings Node
Provides Sourceful-specific settings for image generation (providerSettings.sourceful.*)
"""
from typing import Dict, Any, List
class RunwareSourcefulProviderSettings:
"""Runware Sourceful Provider Settings Node"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {},
"optional": {
"useTransparency": ("BOOLEAN", {
"tooltip": "Enable to include transparency parameter in API request",
"default": False,
}),
"transparency": ("BOOLEAN", {
"tooltip": "Transparency setting for image generation. Only used when 'Use Transparency' is enabled.",
"default": False,
}),
"useEnhancePrompt": ("BOOLEAN", {
"tooltip": "Enable to include enhancePrompt parameter in API request",
"default": False,
}),
"enhancePrompt": ("BOOLEAN", {
"tooltip": "When true, enhances the provided prompt. Only used when 'Use Enhance Prompt' is enabled.",
"default": True,
}),
"fontInputs": ("RUNWARESOURCEFULFONTINPUTS", {
"tooltip": "Connect Runware Sourceful Provider Settings Fonts node to provide font references (fontUrl and text). Up to 2 fonts.",
}),
}
}
RETURN_TYPES = ("RUNWAREPROVIDERSETTINGS",)
RETURN_NAMES = ("providerSettings",)
FUNCTION = "create_provider_settings"
CATEGORY = "Runware/Provider Settings"
DESCRIPTION = "Configure Sourceful-specific provider settings for image generation: transparency, enhancePrompt, and font inputs."
def create_provider_settings(self, **kwargs) -> tuple[Dict[str, Any]]:
"""Create Sourceful provider settings"""
useTransparency = kwargs.get("useTransparency", False)
transparency = kwargs.get("transparency", False)
useEnhancePrompt = kwargs.get("useEnhancePrompt", False)
enhancePrompt = kwargs.get("enhancePrompt", True)
font_inputs = kwargs.get("fontInputs", None)
settings: Dict[str, Any] = {}
if useTransparency:
settings["transparency"] = transparency
if useEnhancePrompt:
settings["enhancePrompt"] = enhancePrompt
if font_inputs is not None and isinstance(font_inputs, list) and len(font_inputs) > 0:
settings["fontInputs"] = font_inputs
return (settings,)
NODE_CLASS_MAPPINGS = {
"RunwareSourcefulProviderSettings": RunwareSourcefulProviderSettings,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"RunwareSourcefulProviderSettings": "Runware Sourceful Provider Settings",
}
@@ -0,0 +1,76 @@
"""
Runware Sourceful Provider Settings Fonts Node
Creates font inputs array for Sourceful provider (up to 2 font references with fontUrl and text).
"""
from typing import Dict, List
class RunwareSourcefulProviderSettingsFonts:
"""Runware Sourceful Provider Settings Fonts Node"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {},
"optional": {
"useFont1": ("BOOLEAN", {
"tooltip": "Enable to include first font reference in fontInputs array",
"default": False,
}),
"fontUrl1": ("STRING", {
"tooltip": "URL of the font file (e.g. .woff2). Only used when 'Use Font 1' is enabled.",
"default": "",
}),
"text1": ("STRING", {
"multiline": True,
"tooltip": "Text to render with the first font. Only used when 'Use Font 1' is enabled.",
"default": "",
}),
"useFont2": ("BOOLEAN", {
"tooltip": "Enable to include second font reference in fontInputs array",
"default": False,
}),
"fontUrl2": ("STRING", {
"tooltip": "URL of the font file (e.g. .woff2). Only used when 'Use Font 2' is enabled.",
"default": "",
}),
"text2": ("STRING", {
"multiline": True,
"tooltip": "Text to render with the second font. Only used when 'Use Font 2' is enabled.",
"default": "",
}),
}
}
RETURN_TYPES = ("RUNWARESOURCEFULFONTINPUTS",)
RETURN_NAMES = ("Font Inputs",)
FUNCTION = "create_font_inputs"
CATEGORY = "Runware/Provider Settings"
DESCRIPTION = "Create font inputs for Sourceful provider. Up to 2 font references, each with font URL and text to render."
def create_font_inputs(self, **kwargs) -> tuple[List[Dict[str, str]]]:
"""Create font inputs array"""
font_inputs: List[Dict[str, str]] = []
for i in range(1, 3):
use_font = kwargs.get(f"useFont{i}", False)
if use_font:
font_url = (kwargs.get(f"fontUrl{i}", "") or "").strip()
text = (kwargs.get(f"text{i}", "") or "").strip()
if font_url and text:
font_inputs.append({
"fontUrl": font_url,
"text": text,
})
return (font_inputs,)
NODE_CLASS_MAPPINGS = {
"RunwareSourcefulProviderSettingsFonts": RunwareSourcefulProviderSettingsFonts,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"RunwareSourcefulProviderSettingsFonts": "Runware Sourceful Provider Settings Fonts",
}
File diff suppressed because one or more lines are too long