Add Google Provider Settings feature

This commit is contained in:
Sirshendu Ganguly
2025-12-15 23:36:42 -05:00
parent d65e37d40a
commit 1b958b09c2
8 changed files with 346 additions and 2 deletions
+4
View File
@@ -55,6 +55,7 @@ from .modules.providerSettings.runwayProviderSettings import RunwareRunwayProvid
from .modules.providerSettings.lumaProviderSettings import RunwareLumaProviderSettings
from .modules.providerSettings.midjourneyProviderSettings import RunwareMidjourneyProviderSettings
from .modules.providerSettings.alibabaProviderSettings import RunwareAlibabaProviderSettings
from .modules.providerSettings.googleProviderSettings import RunwareGoogleProviderSettings
from .modules.providerSettings.syncSegment import RunwareSyncSegment
from .modules.providerSettings.syncProviderSettings import RunwareSyncProviderSettings
from .modules.vectorize import vectorize
@@ -63,6 +64,7 @@ from .modules.videoUpscaler import videoUpscaler
from .modules.videoInputsReferences import videoInputsReferences
from .modules.videoInputsFrame import RunwareVideoInputsFrameImages
from .modules.safetyInputs import safetyInputs
from .modules.settings import RunwareSettings
from .modules.videoAdvancedFeatureInputs import videoAdvancedFeatureInputs
RUNWARE_COMFYUI_VERSION = "1.4.0 Beta"
@@ -133,6 +135,7 @@ NODE_CLASS_MAPPINGS = {
"Runware Runway Provider Settings": RunwareRunwayProviderSettings,
"Runware Midjourney Provider Settings": RunwareMidjourneyProviderSettings,
"Runware Alibaba Provider Settings": RunwareAlibabaProviderSettings,
"Runware Google Provider Settings": RunwareGoogleProviderSettings,
"Runware Sync Segment": RunwareSyncSegment,
"Runware Sync Provider Settings": RunwareSyncProviderSettings,
"Runware Vectorize": vectorize,
@@ -141,6 +144,7 @@ NODE_CLASS_MAPPINGS = {
"Runware Video Inputs References": videoInputsReferences,
"Runware Video Inputs Frame Images": RunwareVideoInputsFrameImages,
"Runware Safety Inputs": safetyInputs,
"Runware Settings": RunwareSettings,
"Runware Video Advanced Feature Inputs": videoAdvancedFeatureInputs,
}
+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, videoTranscriptionHandler, handleCustomErrors, videoInferenceDimensionsHandler, videoModelSearchFilterHandler, audioModelSearchFilterHandler, useParameterToggleHandler, imageInferenceToggleHandler, upscalerToggleHandler, videoUpscalerToggleHandler, audioInferenceToggleHandler, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, openaiProviderSettingsToggleHandler, lightricksProviderSettingsToggleHandler, klingProviderSettingsToggleHandler, lumaProviderSettingsToggleHandler, briaProviderSettingsToggleHandler, pixverseProviderSettingsToggleHandler, alibabaProviderSettingsToggleHandler, syncProviderSettingsToggleHandler, syncSegmentToggleHandler } from "./utils.js";
import { promptEnhanceHandler, syncDimensionsNodeHandler, searchNodeHandler, APIKeyHandler, captionNodeHandler, mediaUUIDHandler, videoTranscriptionHandler, handleCustomErrors, videoInferenceDimensionsHandler, videoModelSearchFilterHandler, audioModelSearchFilterHandler, useParameterToggleHandler, imageInferenceToggleHandler, upscalerToggleHandler, videoUpscalerToggleHandler, audioInferenceToggleHandler, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, openaiProviderSettingsToggleHandler, lightricksProviderSettingsToggleHandler, klingProviderSettingsToggleHandler, lumaProviderSettingsToggleHandler, briaProviderSettingsToggleHandler, pixverseProviderSettingsToggleHandler, alibabaProviderSettingsToggleHandler, googleProviderSettingsToggleHandler, syncProviderSettingsToggleHandler, syncSegmentToggleHandler, settingsToggleHandler } from "./utils.js";
import { RUNWARE_NODE_TYPES, RUNWARE_NODE_PROPS, SEARCH_TERMS } from "./types.js";
const nodeInitList = [];
@@ -73,10 +73,14 @@ app.registerExtension({
pixverseProviderSettingsToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.ALIBABAPROVIDERSETTINGS) {
alibabaProviderSettingsToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.GOOGLEPROVIDERSETTINGS) {
googleProviderSettingsToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.SYNCPROVIDERSETTINGS) {
syncProviderSettingsToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.SYNCSEGMENT) {
syncSegmentToggleHandler(node);
} else if(nodeClass === RUNWARE_NODE_TYPES.SETTINGS) {
settingsToggleHandler(node);
}
if(crNodeProps.colorModeOnly === true) return;
+10
View File
@@ -102,6 +102,7 @@ const RUNWARE_NODE_TYPES = {
LUMAPROVIDERSETTINGS: "Runware Luma Provider Settings",
MIDJOURNEYPROVIDERSETTINGS: "Runware Midjourney Provider Settings",
ALIBABAPROVIDERSETTINGS: "Runware Alibaba Provider Settings",
GOOGLEPROVIDERSETTINGS: "Runware Google Provider Settings",
SYNCSEGMENT: "Runware Sync Segment",
SYNCPROVIDERSETTINGS: "Runware Sync Provider Settings",
VECTORIZE: "Runware Vectorize",
@@ -113,6 +114,7 @@ const RUNWARE_NODE_TYPES = {
VIDEOTRANSCRIPTION: "Runware Video Transcription",
MINIMAXPROVIDERSETTINGS: "Runware MiniMax Provider Settings",
SAFETYINPUTS: "Runware Safety Inputs",
SETTINGS: "Runware Settings",
VIDEOADVANCEDFEATUREINPUTS: "Runware Video Advanced Feature Inputs",
};
@@ -336,6 +338,10 @@ const RUNWARE_NODE_PROPS = {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
},
[RUNWARE_NODE_TYPES.GOOGLEPROVIDERSETTINGS]: {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
},
[RUNWARE_NODE_TYPES.SYNCSEGMENT]: {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
@@ -381,6 +387,10 @@ const RUNWARE_NODE_PROPS = {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
},
[RUNWARE_NODE_TYPES.SETTINGS]: {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
},
[RUNWARE_NODE_TYPES.VIDEOADVANCEDFEATUREINPUTS]: {
bgColor: DEFAULT_BGCOLOR,
colorModeOnly: true,
+128
View File
@@ -2466,10 +2466,138 @@ export {
briaProviderSettingsToggleHandler,
pixverseProviderSettingsToggleHandler,
alibabaProviderSettingsToggleHandler,
googleProviderSettingsToggleHandler,
syncProviderSettingsToggleHandler,
syncSegmentToggleHandler,
settingsToggleHandler,
};
function googleProviderSettingsToggleHandler(googleNode) {
// Find all "use" parameter widgets for Google Provider Settings
const useGenerateAudioWidget = googleNode.widgets.find(w => w.name === "useGenerateAudio");
const generateAudioWidget = googleNode.widgets.find(w => w.name === "generateAudio");
const useEnhancePromptWidget = googleNode.widgets.find(w => w.name === "useEnhancePrompt");
const enhancePromptWidget = googleNode.widgets.find(w => w.name === "enhancePrompt");
const useSearchWidget = googleNode.widgets.find(w => w.name === "useSearch");
const searchWidget = googleNode.widgets.find(w => w.name === "search");
// Helper function to toggle widget enabled state
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 = googleNode.htmlElements?.widgetsContainer || googleNode.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";
}
}
}
}
googleNode.setDirtyCanvas(true);
}
appendWidgetCB(useWidget, () => {
setTimeout(toggleEnabled, 50);
});
setTimeout(toggleEnabled, 100);
}
// Set up toggle handlers
if (useGenerateAudioWidget && generateAudioWidget) {
toggleWidgetState(useGenerateAudioWidget, generateAudioWidget, "generateAudio");
}
if (useEnhancePromptWidget && enhancePromptWidget) {
toggleWidgetState(useEnhancePromptWidget, enhancePromptWidget, "enhancePrompt");
}
if (useSearchWidget && searchWidget) {
toggleWidgetState(useSearchWidget, searchWidget, "search");
}
}
function settingsToggleHandler(settingsNode) {
// Find all "use" parameter widgets for Settings
const useTemperatureWidget = settingsNode.widgets.find(w => w.name === "useTemperature");
const temperatureWidget = settingsNode.widgets.find(w => w.name === "temperature");
const useSystemPromptWidget = settingsNode.widgets.find(w => w.name === "useSystemPrompt");
const systemPromptWidget = settingsNode.widgets.find(w => w.name === "systemPrompt");
const useTopPWidget = settingsNode.widgets.find(w => w.name === "useTopP");
const topPWidget = settingsNode.widgets.find(w => w.name === "topP");
// Helper function to toggle widget enabled state
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 = settingsNode.htmlElements?.widgetsContainer || settingsNode.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";
}
}
}
}
settingsNode.setDirtyCanvas(true);
}
appendWidgetCB(useWidget, () => {
setTimeout(toggleEnabled, 50);
});
setTimeout(toggleEnabled, 100);
}
// Set up toggle handlers
if (useTemperatureWidget && temperatureWidget) {
toggleWidgetState(useTemperatureWidget, temperatureWidget, "temperature");
}
if (useSystemPromptWidget && systemPromptWidget) {
toggleWidgetState(useSystemPromptWidget, systemPromptWidget, "systemPrompt");
}
if (useTopPWidget && topPWidget) {
toggleWidgetState(useTopPWidget, topPWidget, "topP");
}
}
function syncProviderSettingsToggleHandler(syncNode) {
// Find all "use" parameter widgets for Sync Provider Settings
const useEditRegionWidget = syncNode.widgets.find(w => w.name === "useEditRegion");
+8
View File
@@ -188,6 +188,9 @@ class txt2img:
"safetyInputs": ("RUNWARESAFETYINPUTS", {
"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.",
}),
}
}
@@ -229,6 +232,7 @@ class txt2img:
inputs = kwargs.get("inputs", None)
providerSettings = kwargs.get("providerSettings", None)
safetyInputs = kwargs.get("safetyInputs", None)
settings = kwargs.get("settings", None)
seedImage = kwargs.get("seedImage", None)
seedImageStrength = kwargs.get("strength", 0.8)
maskImage = kwargs.get("maskImage", None)
@@ -386,6 +390,10 @@ class txt2img:
if safetyInputs is not None and isinstance(safetyInputs, dict) and len(safetyInputs) > 0:
genConfig[0]["safety"] = safetyInputs
# Add settings if provided
if settings is not None and isinstance(settings, dict) and len(settings) > 0:
genConfig[0]["settings"] = settings
if (multiInferenceMode):
return (None, genConfig)
else:
@@ -0,0 +1,95 @@
"""
Runware Google Provider Settings Node
Provides Google-specific settings for image/video generation
"""
from typing import Optional, Dict, Any
class RunwareGoogleProviderSettings:
"""Runware Google Provider Settings Node"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {},
"optional": {
"useGenerateAudio": ("BOOLEAN", {
"tooltip": "Enable to include generateAudio parameter in provider settings",
"default": False,
}),
"generateAudio": ("BOOLEAN", {
"tooltip": "Enable audio generation. Only used when 'Use Generate Audio' is enabled.",
"default": False,
"label_on": "Enabled",
"label_off": "Disabled",
}),
"useEnhancePrompt": ("BOOLEAN", {
"tooltip": "Enable to include enhancePrompt parameter in provider settings",
"default": False,
}),
"enhancePrompt": ("BOOLEAN", {
"tooltip": "Enable prompt enhancement for Google generation. Only used when 'Use Enhance Prompt' is enabled.",
"default": False,
"label_on": "Enabled",
"label_off": "Disabled",
}),
"useSearch": ("BOOLEAN", {
"tooltip": "Enable to include search parameter in provider settings",
"default": False,
}),
"search": ("BOOLEAN", {
"tooltip": "Enable search functionality. Only used when 'Use Search' is enabled.",
"default": False,
"label_on": "Enabled",
"label_off": "Disabled",
}),
}
}
RETURN_TYPES = ("RUNWAREPROVIDERSETTINGS",)
RETURN_NAMES = ("Provider Settings",)
FUNCTION = "createProviderSettings"
CATEGORY = "Runware/Provider Settings"
DESCRIPTION = "Configure Google-specific provider settings for image/video generation including audio generation, prompt enhancement, and search."
def createProviderSettings(self, **kwargs) -> tuple[Dict[str, Any]]:
"""Create Google provider settings"""
# Get control parameters
useGenerateAudio = kwargs.get("useGenerateAudio", False)
useEnhancePrompt = kwargs.get("useEnhancePrompt", False)
useSearch = kwargs.get("useSearch", False)
# Get value parameters
generateAudio = kwargs.get("generateAudio", False)
enhancePrompt = kwargs.get("enhancePrompt", False)
search = kwargs.get("search", False)
# Build settings dictionary - only include what is enabled
googleSettings: Dict[str, Any] = {}
# Add parameters only if their use toggles are enabled
if useGenerateAudio:
googleSettings["generateAudio"] = generateAudio
if useEnhancePrompt:
googleSettings["enhancePrompt"] = enhancePrompt
if useSearch:
googleSettings["search"] = search
# Clean up None values
googleSettings = {k: v for k, v in googleSettings.items() if v is not None}
# Return flat dictionary - will be wrapped by inference node with provider name
return (googleSettings,)
# Node class mappings
NODE_CLASS_MAPPINGS = {
"RunwareGoogleProviderSettings": RunwareGoogleProviderSettings,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"RunwareGoogleProviderSettings": "Runware Google Provider Settings",
}
+95
View File
@@ -0,0 +1,95 @@
"""
Runware Settings Node
Provides general settings for image generation including temperature, systemPrompt, and topP
"""
from typing import Optional, Dict, Any
class RunwareSettings:
"""Runware Settings Node"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {},
"optional": {
"useTemperature": ("BOOLEAN", {
"tooltip": "Enable to include temperature parameter in API request",
"default": False,
}),
"temperature": ("FLOAT", {
"tooltip": "Temperature value for generation. Only used when 'Use Temperature' is enabled.",
"default": 1.0,
"min": 0.0,
"max": 2.0,
"step": 0.1,
}),
"useSystemPrompt": ("BOOLEAN", {
"tooltip": "Enable to include systemPrompt parameter in API request",
"default": False,
}),
"systemPrompt": ("STRING", {
"multiline": True,
"tooltip": "System prompt for generation. Only used when 'Use System Prompt' is enabled.",
"default": "",
}),
"useTopP": ("BOOLEAN", {
"tooltip": "Enable to include topP parameter in API request",
"default": False,
}),
"topP": ("FLOAT", {
"tooltip": "Top-p (nucleus) sampling parameter. Only used when 'Use Top P' is enabled.",
"default": 1.0,
"min": 0.0,
"max": 1.0,
"step": 0.01,
}),
}
}
RETURN_TYPES = ("RUNWARESETTINGS",)
RETURN_NAMES = ("Settings",)
FUNCTION = "createSettings"
CATEGORY = "Runware"
DESCRIPTION = "Configure general settings for image generation including temperature, system prompt, and top-p sampling."
def createSettings(self, **kwargs) -> tuple[Dict[str, Any]]:
"""Create settings configuration"""
# Get control parameters
useTemperature = kwargs.get("useTemperature", False)
useSystemPrompt = kwargs.get("useSystemPrompt", False)
useTopP = kwargs.get("useTopP", False)
# Get value parameters
temperature = kwargs.get("temperature", 1.0)
systemPrompt = kwargs.get("systemPrompt", "")
topP = kwargs.get("topP", 1.0)
# Build settings dictionary - only include what is enabled
settings: Dict[str, Any] = {}
# Add optional parameters only if enabled
if useTemperature:
settings["temperature"] = float(temperature)
if useSystemPrompt and systemPrompt and systemPrompt.strip():
settings["systemPrompt"] = systemPrompt.strip()
if useTopP:
settings["topP"] = float(topP)
# 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",
}
+1 -1
View File
@@ -158,7 +158,7 @@ def getCustomEndpoint():
custom_endpoint = os.getenv("RUNWARE_CUSTOM_ENDPOINT")
if custom_endpoint and isinstance(custom_endpoint, str):
return custom_endpoint
return "https://api.runware.ai/v1"
return "https://api.runware.dev/v1"
SESSION_TIMEOUT = getTimeout()
RUNWARE_API_KEY = getAPIKey()