This commit is contained in:
justumen
2025-02-09 15:44:04 +01:00
parent d762702471
commit a0bf04c7d6
46 changed files with 1817 additions and 581 deletions

188
web/js/line_selector.js Normal file
View File

@@ -0,0 +1,188 @@
import { app } from "../../../scripts/app.js";
import { api } from "../../../scripts/api.js";
app.registerExtension({
name: "Bjornulf.LineSelector",
async nodeCreated(node) {
if (node.comfyClass !== "Bjornulf_LineSelector") return;
// Hide seed widget
const seedWidget = node.widgets.find((w) => w.name === "seed");
if (seedWidget) {
seedWidget.visible = false;
}
// Function to update the Reset Button text
const updateResetButtonTextNode = () => {
console.log("[line_selector]=====> updateResetButtonTextNode");
if (!node.graph) return;
fetch("/get_line_selector_counter", {
method: "POST",
})
.then((response) => response.json())
.then((data) => {
if (!node.graph) return;
if (data.success) {
const jumpWidget = node.widgets.find((w) => w.name === "jump");
const text = node.widgets.find((w) => w.name === "text");
if (data.value === 0) {
resetButton.name = "Reset Counter (Empty)";
} else {
// Count valid lines in text
const lines = text.value
.split("\n")
.filter((line) => line.trim() && !line.trim().startsWith("#"));
const lineCount = lines.length;
let next_value = data.value + jumpWidget.value;
if (next_value > lineCount) {
resetButton.name = `Reset Counter (ABOVE MAX: ${next_value} > ${lineCount})`;
} else {
resetButton.name = `Reset Counter (next: ${next_value})`;
}
}
} else if (node.graph) {
resetButton.name = "Reset Counter (Error)";
}
})
.catch((error) => {
if (node.graph) {
resetButton.name = "Reset Counter (Error)";
}
});
};
// Add reset button
const resetButton = node.addWidget(
"button",
"Reset Counter",
null,
async () => {
if (!node.graph) return;
try {
const response = await fetch("/reset_line_selector_counter", {
method: "POST",
});
const data = await response.json();
if (!node.graph) return;
if (data.success) {
app.ui.dialog.show(`[Line Selector] Reset counter successfully.`);
updateResetButtonTextNode();
} else {
app.ui.dialog.show(
`[Line Selector] Failed to reset counter: ${
data.error || "Unknown error"
}`
);
}
} catch (error) {
if (node.graph) {
app.ui.dialog.show(
"[Line Selector] An error occurred while resetting the counter."
);
}
}
}
);
// Create event handler function that we can remove later
// const executedHandler = async (event) => {
// if (event.detail.node_id === node.id) {
// updateResetButtonTextNode();
// }
// };
// Initial update of showing counter number
setTimeout(updateResetButtonTextNode, 0);
// Listen for node execution events (update value when node executed)
// api.addEventListener("executed", async () => {
// updateResetButtonTextNode();
// });
api.addEventListener("executed", async () => {
// Check if context file is enabled before updating
const contextWidget = node.widgets.find(
(w) => w.name === "LOOP_SEQUENTIAL"
);
if (contextWidget && contextWidget.value) {
updateResetButtonTextNode();
}
});
// Override the original execute function
const originalExecute = node.execute;
node.execute = function () {
const result = originalExecute.apply(this, arguments);
if (result instanceof Promise) {
return result.catch((error) => {
if (error.message.includes("Counter has reached") && node.graph) {
app.ui.dialog.show(`Execution blocked: ${error.message}`);
}
throw error;
});
}
return result;
};
// Setup widget handlers for updating counter display
const setupWidgetHandler = (widgetName) => {
const widget = node.widgets.find((w) => w.name === widgetName);
if (widget) {
const originalOnChange = widget.callback;
widget.callback = function (v) {
if (originalOnChange) {
originalOnChange.call(this, v);
}
if (node.widgets.find((w) => w.name === "LOOP_SEQUENTIAL")?.value) {
updateResetButtonTextNode();
}
};
}
};
// Setup handlers for relevant widgets
setupWidgetHandler("jump");
setupWidgetHandler("text");
setupWidgetHandler("LOOP_SEQUENTIAL");
//BUG this cleanup five a floating textarea
// Add cleanup when node is removed
// node.onRemoved = function() {
// api.removeEventListener("executed", executedHandler);
// };
// Initial button visibility check
const updateButtonVisibility = () => {
const loopSeqWidget = node.widgets.find(
(w) => w.name === "LOOP_SEQUENTIAL"
);
resetButton.type = loopSeqWidget?.value ? "button" : "hidden";
if (loopSeqWidget?.value) {
updateResetButtonTextNode();
}
};
// Setup visibility handler for LOOP_SEQUENTIAL
const loopSeqWidget = node.widgets.find(
(w) => w.name === "LOOP_SEQUENTIAL"
);
if (loopSeqWidget) {
const originalOnChange = loopSeqWidget.callback;
loopSeqWidget.callback = function (v) {
if (originalOnChange) {
originalOnChange.call(this, v);
}
updateButtonVisibility();
};
}
// Initial update
updateButtonVisibility();
},
});

View File

@@ -19,6 +19,9 @@ app.registerExtension({
// Function to update the Reset Button text
const updateResetButtonTextNode = () => {
console.log("[loop_lines_sequential]=====> updateResetButtonTextNode");
if (!node.graph) return;
fetch("/get_current_line_number", {
method: "POST",
})
@@ -36,12 +39,12 @@ app.registerExtension({
resetButton.name = `Reset Counter (next: ${next_value})`;
}
} else {
console.error("Error in context size:", data.error);
console.error("[Loop Lines Sequential] Error in context size:", data.error);
resetButton.name = "Reset Counter (Error)";
}
})
.catch((error) => {
console.error("Error fetching context size:", error);
console.error("[Loop Lines Sequential] Error fetching context size:", error);
resetButton.name = "Reset Counter (Error)";
});
};
@@ -56,20 +59,15 @@ app.registerExtension({
if (data.success) {
// updateLineNumber();
updateResetButtonTextNode();
app.ui.toast("Counter reset successfully!", { duration: 5000 });
// app.ui.dialog.show("Counter reset successfully!");
} else {
app.ui.toast(
`Failed to reset counter: ${data.error || "Unknown error"}`,
{ type: "error", duration: 5000 }
);
app.ui.dialog.show(
`[Loop Lines Sequential] Failed to reset counter: ${data.error || "Unknown error"}`);
}
})
.catch((error) => {
console.error("Error:", error);
app.ui.toast("An error occurred while resetting the counter.", {
type: "error",
duration: 5000,
});
console.error("[Loop Lines Sequential] Error:", error);
app.ui.dialog.show("[Loop Lines Sequential] An error occurred while resetting the counter.");
});
});
@@ -82,20 +80,15 @@ app.registerExtension({
.then((data) => {
if (data.success) {
updateResetButtonTextNode();
app.ui.toast("Counter incremented", { duration: 3000 });
// app.ui.dialog.show("Counter incremented");
} else {
app.ui.toast(
`Failed to increment counter: ${data.error || "Unknown error"}`,
{ type: "error", duration: 5000 }
);
app.ui.dialog.show(
`[Loop Lines Sequential] Failed to increment counter: ${data.error || "Unknown error"}`);
}
})
.catch((error) => {
console.error("Error:", error);
app.ui.toast("An error occurred while incrementing the counter.", {
type: "error",
duration: 5000,
});
console.error("[Loop Lines Sequential] Error:", error);
app.ui.dialog.show("[Loop Lines Sequential] An error occurred while incrementing the counter.");
});
});
@@ -108,49 +101,18 @@ app.registerExtension({
.then((data) => {
if (data.success) {
updateResetButtonTextNode();
app.ui.toast("Counter decremented", { duration: 3000 });
// app.ui.dialog.show("Counter decremented");
} else {
app.ui.toast(
`Failed to decrement counter: ${data.error || "Unknown error"}`,
{ type: "error", duration: 5000 }
);
app.ui.dialog.show(
`[Loop Lines Sequential] Failed to decrement counter: ${data.error || "Unknown error"}`);
}
})
.catch((error) => {
console.error("Error:", error);
app.ui.toast("An error occurred while decrementing the counter.", {
type: "error",
duration: 5000,
});
console.error("[Loop Lines Sequential] Error:", error);
app.ui.dialog.show("[Loop Lines Sequential] An error occurred while decrementing the counter.");
});
});
// Add reset button
// const resetButton = node.addWidget("button", "Reset Counter", null, () => {
// fetch("/reset_lines_counter", {
// method: "POST",
// })
// .then((response) => response.json())
// .then((data) => {
// if (data.success) {
// updateLineNumber();
// app.ui.toast("Counter reset successfully!", { duration: 5000 });
// } else {
// app.ui.toast(
// `Failed to reset counter: ${data.error || "Unknown error"}`,
// { type: "error", duration: 5000 }
// );
// }
// })
// .catch((error) => {
// console.error("Error:", error);
// app.ui.toast("An error occurred while resetting the counter.", {
// type: "error",
// duration: 5000,
// });
// });
// });
// Update line number periodically
setTimeout(updateResetButtonTextNode, 0);
@@ -178,10 +140,7 @@ app.registerExtension({
if (result instanceof Promise) {
return result.catch((error) => {
if (error.message.includes("Counter has reached its limit")) {
app.ui.toast(`Execution blocked: ${error.message}`, {
type: "error",
duration: 5000,
});
app.ui.dialog.show(`[Loop Lines Sequential] Execution blocked: ${error.message}`);
}
throw error;
});

View File

@@ -23,6 +23,9 @@ app.registerExtension({
// Function to update the Reset Button text
const updateResetButtonTextNode = () => {
console.log("[loop_sequential_integer]=====> updateResetButtonTextNode");
if (!node.graph) return;
fetch("/get_counter_value", {
method: "POST",
})
@@ -49,12 +52,12 @@ app.registerExtension({
}
}
} else {
console.error("Error in context size:", data.error);
console.error("[Loop Integer Sequential] Error in context size:", data.error);
resetButton.name = "Reset Counter (Error)";
}
})
.catch((error) => {
console.error("Error fetching context size:", error);
console.error("[Loop Integer Sequential] Error fetching context size:", error);
resetButton.name = "Reset Counter (Error)";
});
};
@@ -69,20 +72,15 @@ app.registerExtension({
if (data.success) {
// updateLineNumber();
updateResetButtonTextNode();
app.ui.toast("Counter reset successfully!", { duration: 5000 });
// app.ui.dialog.show("Counter reset successfully!");
} else {
app.ui.toast(
`Failed to reset counter: ${data.error || "Unknown error"}`,
{ type: "error", duration: 5000 }
);
app.ui.dialog.show(
`[Loop Integer Sequential] Failed to reset counter: ${data.error || "Unknown error"}`);
}
})
.catch((error) => {
console.error("Error:", error);
app.ui.toast("An error occurred while resetting the counter.", {
type: "error",
duration: 5000,
});
console.error("[Loop Integer Sequential] Error:", error);
app.ui.dialog.show("[Loop Integer Sequential] An error occurred while resetting the counter.");
});
});
@@ -92,8 +90,8 @@ app.registerExtension({
const result = originalExecute.apply(this, arguments);
if (result instanceof Promise) {
return result.catch((error) => {
if (error.message.includes("Counter has reached its limit")) {
app.ui.toast(`Execution blocked: ${error.message}`, {
if (error.message.includes("[Loop Integer Sequential] Counter has reached its limit")) {
app.ui.dialog.show(`[Loop Integer Sequential] Execution blocked: ${error.message}`, {
type: "error",
duration: 5000,
});
@@ -150,20 +148,15 @@ app.registerExtension({
if (data.success) {
// updateLineNumber();
updateResetButtonTextNode();
app.ui.toast("Counter reset successfully!", { duration: 5000 });
// app.ui.dialog.show("Counter reset successfully!", { duration: 5000 });
} else {
app.ui.toast(
`Failed to reset counter: ${data.error || "Unknown error"}`,
{ type: "error", duration: 5000 }
);
app.ui.dialog.show(
`[Loop Integer Sequential] Failed to reset counter: ${data.error || "Unknown error"}`);
}
})
.catch((error) => {
console.error("Error:", error);
app.ui.toast("An error occurred while resetting the counter.", {
type: "error",
duration: 5000,
});
console.error("[Loop Integer Sequential] Error:", error);
app.ui.dialog.show("[Loop Integer Sequential] An error occurred while resetting the counter.");
});
};
}

110
web/js/lora_stacks.js Normal file
View File

@@ -0,0 +1,110 @@
import { app } from "../../../scripts/app.js";
app.registerExtension({
name: "Bjornulf.AllLoraSelector",
async nodeCreated(node) {
if (node.comfyClass === "Bjornulf_AllLoraSelector") {
node.properties = node.properties || {};
const updateLoraInputs = () => {
const initialWidth = node.size[0];
const numLorasWidget = node.widgets.find(w => w.name === "number_of_loras");
if (!numLorasWidget) return;
const numLoras = numLorasWidget.value;
const loraList = node.widgets.find(w => w.name === "lora_1")?.options?.values || [];
// Save existing values
node.widgets.forEach(w => {
if (w.name.startsWith("lora_") || w.name.startsWith("strength_model_") || w.name.startsWith("strength_clip_")) {
node.properties[w.name] = w.value;
}
});
// Remove existing LoRA-related widgets
node.widgets = node.widgets.filter(w =>
!w.name.startsWith("lora_") &&
!w.name.startsWith("strength_model_") &&
!w.name.startsWith("strength_clip_")
);
// Add number_of_loras widget if it doesn't exist
const ensureWidget = (name, type, defaultValue, config) => {
let widget = node.widgets.find(w => w.name === name);
if (!widget) {
widget = node.addWidget(type, name,
node.properties[name] !== undefined ? node.properties[name] : defaultValue,
value => { node.properties[name] = value; },
config
);
}
};
ensureWidget("number_of_loras", "number", 3, { min: 1, max: 20, step: 1 });
// Add LoRA widgets for each slot
for (let i = 1; i <= numLoras; i++) {
const loraName = `lora_${i}`;
const strengthModelName = `strength_model_${i}`;
const strengthClipName = `strength_clip_${i}`;
// Add LoRA selector
node.addWidget("combo", loraName,
node.properties[loraName] || loraList[0],
value => { node.properties[loraName] = value; },
{ values: loraList }
);
// Add strength sliders
node.addWidget("number", strengthModelName,
node.properties[strengthModelName] !== undefined ? node.properties[strengthModelName] : 1.0,
value => { node.properties[strengthModelName] = value; },
{ min: -100.0, max: 100.0, step: 0.01 }
);
node.addWidget("number", strengthClipName,
node.properties[strengthClipName] !== undefined ? node.properties[strengthClipName] : 1.0,
value => { node.properties[strengthClipName] = value; },
{ min: -100.0, max: 100.0, step: 0.01 }
);
}
node.setSize(node.computeSize());
node.size[0] = Math.max(initialWidth, node.size[0]);
};
// Set up number_of_loras widget callback
const numLorasWidget = node.widgets.find(w => w.name === "number_of_loras");
if (numLorasWidget) {
numLorasWidget.callback = () => {
updateLoraInputs();
app.graph.setDirtyCanvas(true);
};
}
// Handle serialization
const originalOnSerialize = node.onSerialize;
node.onSerialize = function(info) {
if (originalOnSerialize) {
originalOnSerialize.call(this, info);
}
info.properties = { ...this.properties };
};
// Handle deserialization
const originalOnConfigure = node.onConfigure;
node.onConfigure = function(info) {
if (originalOnConfigure) {
originalOnConfigure.call(this, info);
}
if (info.properties) {
Object.assign(this.properties, info.properties);
}
updateLoraInputs();
};
// Initial setup
updateLoraInputs();
}
}
});

View File

@@ -0,0 +1,71 @@
import { app } from "../../../scripts/app.js";
app.registerExtension({
name: "Bjornulf.ModelClipVaeSelector",
async nodeCreated(node) {
if (node.comfyClass === "Bjornulf_ModelClipVaeSelector") {
const updateInputs = () => {
const numInputsWidget = node.widgets.find(w => w.name === "number_of_inputs");
if (!numInputsWidget) return;
const numInputs = numInputsWidget.value;
// Initialize node.inputs if it doesn't exist
if (!node.inputs) {
node.inputs = [];
}
// Filter existing model, clip, and vae inputs
const existingModelInputs = node.inputs.filter(input => input.name.startsWith('model_'));
const existingClipInputs = node.inputs.filter(input => input.name.startsWith('clip_'));
const existingVaeInputs = node.inputs.filter(input => input.name.startsWith('vae_'));
// Determine if we need to add or remove inputs
if (existingModelInputs.length < numInputs || existingClipInputs.length < numInputs || existingVaeInputs.length < numInputs) {
// Add new model, clip, and vae inputs if not enough existing
for (let i = Math.max(existingModelInputs.length, existingClipInputs.length, existingVaeInputs.length) + 1; i <= numInputs; i++) {
const modelInputName = `model_${i}`;
const clipInputName = `clip_${i}`;
const vaeInputName = `vae_${i}`;
if (!node.inputs.find(input => input.name === modelInputName)) {
node.addInput(modelInputName, "MODEL");
}
if (!node.inputs.find(input => input.name === clipInputName)) {
node.addInput(clipInputName, "CLIP");
}
if (!node.inputs.find(input => input.name === vaeInputName)) {
node.addInput(vaeInputName, "VAE");
}
}
} else {
// Remove excess model, clip, and vae inputs if too many
node.inputs = node.inputs.filter(input =>
(!input.name.startsWith('model_') && !input.name.startsWith('clip_') && !input.name.startsWith('vae_')) ||
(parseInt(input.name.split('_')[1]) <= numInputs)
);
}
node.setSize(node.computeSize());
};
// Move number_of_inputs to the top initially
const numInputsWidget = node.widgets.find(w => w.name === "number_of_inputs");
if (numInputsWidget) {
node.widgets = [numInputsWidget, ...node.widgets.filter(w => w !== numInputsWidget)];
numInputsWidget.callback = () => {
updateInputs();
app.graph.setDirtyCanvas(true);
};
}
// Set seed widget to hidden input
const seedWidget = node.widgets.find((w) => w.name === "seed");
if (seedWidget) {
seedWidget.type = "HIDDEN";
}
// Delay the initial update to ensure node is fully initialized
setTimeout(updateInputs, 0);
}
}
});

View File

@@ -10,10 +10,16 @@ app.registerExtension({
"select_model_here",
"",
(v) => {
// When model_list changes, update model_name
const modelNameWidget = node.widgets.find(w => w.name === "model_name");
if (modelNameWidget) {
modelNameWidget.value = v;
try {
// When model_list changes, update model_name
const modelNameWidget = node.widgets.find(w => w.name === "model_name");
if (modelNameWidget) {
modelNameWidget.value = v;
} else {
console.error('[Ollama Config] Model name widget not found');
}
} catch (error) {
console.error('[Ollama Config] Error updating model name:', error);
}
},
{ values: [] }
@@ -26,13 +32,26 @@ app.registerExtension({
value: "Update Models",
callback: async function() {
try {
const url = node.widgets.find(w => w.name === "ollama_url").value;
const url = node.widgets.find(w => w.name === "ollama_url")?.value;
if (!url) {
console.error('[Ollama Config] Ollama URL is not set');
return;
}
console.log('[Ollama Config] Fetching models from:', url);
const response = await fetch(`${url}/api/tags`);
if (!response.ok) {
console.error('[Ollama Config] Server response not OK:', response.status, response.statusText);
return;
}
const data = await response.json();
if (data.models) {
const modelNames = data.models.map(m => m.name);
if (modelNames.length > 0) {
console.log('Found models:', modelNames);
// Update model_list widget
modelListWidget.options.values = modelNames;
modelListWidget.value = modelNames[0];
@@ -41,11 +60,22 @@ app.registerExtension({
const modelNameWidget = node.widgets.find(w => w.name === "model_name");
if (modelNameWidget) {
modelNameWidget.value = modelNames[0];
} else {
console.error('[Ollama Config] Model name widget not found');
}
} else {
console.error('[Ollama Config] No models found in response');
}
} else {
console.error('[Ollama Config] Invalid response format:', data);
}
} catch (error) {
console.error('Error updating models:', error);
console.error('[Ollama Config] Error updating models:', error);
console.error('[Ollama Config] Error details:', {
message: error.message,
stack: error.stack,
name: error.name
});
}
}
});

View File

@@ -14,24 +14,28 @@ app.registerExtension({
// Function to update the Reset Button text
const updateResetButtonTextNode = () => {
console.log("[ollama_talk]=====> updateResetButtonTextNode:");
if (!node.graph) return;
fetch("/get_current_context_size", {
method: "POST",
})
.then((response) => response.json())
.then((data) => {
if (data.success) {
// console.log("[Ollama] /get_current_context_size fetched successfully");
if (data.value === 0) {
resetButton.name = "Save/Reset Context File (Empty)";
} else {
resetButton.name = `Save/Reset Context File (${data.value} lines)`;
resetButton.name = `Reset Context File (${data.value} lines)`;
}
} else {
console.error("Error in context size:", data.error);
console.error("[Ollama] Error in context size:", data.error);
resetButton.name = "Save/Reset Context File (Error)";
}
})
.catch((error) => {
console.error("Error fetching context size:", error);
console.error("[Ollama] Error fetching context size:", error);
resetButton.name = "Save/Reset Context File (Error)";
});
};
@@ -50,20 +54,15 @@ app.registerExtension({
if (data.success) {
// updateLineNumber();
updateResetButtonTextNode();
app.ui.toast("Counter reset successfully!", { duration: 5000 });
app.ui.dialog.show("[Ollama] Context saved in Bjornulf/ollama and reset successfully!");
} else {
app.ui.toast(
`Failed to reset counter: ${data.error || "Unknown error"}`,
{ type: "error", duration: 5000 }
);
app.ui.dialog.show(
`[Ollama] Failed to reset Context: ${data.error || "Unknown error"}`);
}
})
.catch((error) => {
console.error("Error:", error);
app.ui.toast("An error occurred while resetting the counter.", {
type: "error",
duration: 5000,
});
app.ui.dialog.show("[Ollama] An error occurred while resetting the Context.");
});
}
);
@@ -89,31 +88,52 @@ app.registerExtension({
})
.then((response) => response.text())
.then((data) => {
console.log("Resume response:", data);
console.log("[Ollama] Resume response:", data);
})
.catch((error) => console.error("Error:", error));
.catch((error) => console.error("[Ollama] Error:", error));
});
// Function to update button visibility based on widget values
// const updateButtonVisibility = () => {
// // Check context file widget
// const contextWidget = node.widgets.find(
// (w) => w.name === "use_context_file"
// );
// const isContextFileEnabled = contextWidget
// ? contextWidget.value
// : false;
// resetButton.type = isContextFileEnabled ? "button" : "HIDDEN";
// // Check waiting for prompt widget
// const waitingWidget = node.widgets.find(
// (w) => w.name === "waiting_for_prompt"
// );
// const isWaitingForPrompt = waitingWidget ? waitingWidget.value : false;
// resumeButton.type = isWaitingForPrompt ? "button" : "HIDDEN";
// //ALSO update reset button text node
// updateResetButtonTextNode(); // Will trigger when... toggle / refresh page
// // Force canvas redraw to update UI
// node.setDirtyCanvas(true);
// };
// In updateButtonVisibility function - Only update when context is enabled
const updateButtonVisibility = () => {
// Check context file widget
const contextWidget = node.widgets.find(
(w) => w.name === "use_context_file"
);
const isContextFileEnabled = contextWidget
? contextWidget.value
: false;
const contextWidget = node.widgets.find(w => w.name === "use_context_file");
const isContextFileEnabled = contextWidget ? contextWidget.value : false;
resetButton.type = isContextFileEnabled ? "button" : "HIDDEN";
// Check waiting for prompt widget
const waitingWidget = node.widgets.find(
(w) => w.name === "waiting_for_prompt"
);
const waitingWidget = node.widgets.find(w => w.name === "waiting_for_prompt");
const isWaitingForPrompt = waitingWidget ? waitingWidget.value : false;
resumeButton.type = isWaitingForPrompt ? "button" : "HIDDEN";
//ALSO update reset button text node
updateResetButtonTextNode(); // Will trigger when... toggle / refresh page
// ONLY update reset button text if context file is enabled
if (isContextFileEnabled) {
updateResetButtonTextNode();
}
// Force canvas redraw to update UI
node.setDirtyCanvas(true);
@@ -151,8 +171,15 @@ app.registerExtension({
setTimeout(updateButtonVisibility, 0);
// Listen for node execution events
// api.addEventListener("executed", async () => {
// updateResetButtonTextNode();
// });
api.addEventListener("executed", async () => {
updateResetButtonTextNode();
// Check if context file is enabled before updating
const contextWidget = node.widgets.find(w => w.name === "use_context_file");
if (contextWidget && contextWidget.value) {
updateResetButtonTextNode();
}
});
//If workflow is stopped during pause, cancel the run