Files

172 lines
5.3 KiB
JavaScript

const TypeSlot = {
Input: 1,
Output: 2,
};
const TypeSlotEvent = {
Connect: true,
Disconnect: false,
};
export function setupCombineNodes(nodeType, nodeData, app) {
if (
nodeData.name === "Griptape Combine: Merge Texts" ||
nodeData.name === "Griptape Combine: Merge Inputs" ||
nodeData.name === "Griptape Combine: Rules List" ||
nodeData.name === "Griptape Combine: Tool List" ||
nodeData.name === "Griptape Combine: RAG Module List" ||
nodeData.name === "Griptape Util: Switch Node" ||
nodeData.name === "Griptape Combine: Merge Dictionary" ||
nodeData.name === "Griptape Combine: String List" ||
nodeData.name === "Griptape Create: Pipeline"
) {
setupCombineNode(nodeType, nodeData, app);
}
}
function setupCombineNode(nodeType, nodeData, app) {
const input_name = getInputName(nodeData.name);
const DEFAULT_TYPE = "*";
const onNodeCreated = nodeType.prototype.onNodeCreated;
nodeType.prototype.onNodeCreated = function () {
const me = onNodeCreated?.apply(this);
// Add initial dynamic input if it doesn't exist
if (!this.inputs.some(input => input.name.includes(input_name))) {
this.addInput(`${input_name}1`, DEFAULT_TYPE);
}
return me;
};
const onConnectionsChange = nodeType.prototype.onConnectionsChange;
nodeType.prototype.onConnectionsChange = function (slotType, slot_idx, event, link_info, node_slot) {
const me = onConnectionsChange?.apply(this, arguments);
if (slotType === TypeSlot.Input) {
if (link_info && event === TypeSlotEvent.Connect) {
// Get the origin node and determine the type
const fromNode = this.graph._nodes.find(
(otherNode) => otherNode.id == link_info.origin_id
);
if (fromNode) {
const parent_link = fromNode.outputs[link_info.origin_slot];
if (parent_link) {
const origin_type = parent_link.type;
// Don't allow connections of type "*"
if (origin_type === "*") {
this.disconnectInput(link_info.target_slot);
return me;
}
// Update all dynamic inputs to match the connected type
updateAllDynamicInputTypes(this, input_name, origin_type);
}
}
} else if (event === TypeSlotEvent.Disconnect) {
// Handle disconnection - remove empty slots except special ones and the last one
handleDisconnection(this, slot_idx, input_name);
}
// Clean up and reorganize inputs
reorganizeInputs(this, input_name);
// Force canvas refresh
this?.graph?.setDirtyCanvas(true);
}
return me;
};
}
function getInputName(nodeName) {
switch (nodeName) {
case "Griptape Combine: Rules List":
return "rules_";
case "Griptape Combine: Tool List":
return "tool_";
case "Griptape Create: Pipeline":
return "task_";
case "Griptape Combine: RAG Module List":
return "module_";
case "Griptape Combine: Merge Dictionary":
return "dict_";
default:
return "input_";
}
}
function updateAllDynamicInputTypes(node, input_name, origin_type) {
// Update all dynamic inputs to use the same type
for (let input of node.inputs) {
if (input.name.includes(input_name)) {
input.type = origin_type;
}
}
// Store the origin type for future dynamic inputs
node.origin_type = origin_type;
}
function handleDisconnection(node, slot_idx, input_name) {
const specialInputs = ["select", "sel_mode"];
const inputToRemove = node.inputs[slot_idx];
// Don't remove special inputs
if (inputToRemove && !specialInputs.includes(inputToRemove.name)) {
// Only remove if we have more than one dynamic input
const dynamicInputCount = node.inputs.filter(input => input.name.includes(input_name)).length;
if (dynamicInputCount > 1) {
node.removeInput(slot_idx);
}
}
}
function reorganizeInputs(node, input_name) {
const specialInputs = ["select", "sel_mode"];
let slot_i = 1;
// Rename all dynamic inputs sequentially
for (let i = 0; i < node.inputs.length; i++) {
let input_i = node.inputs[i];
if (!specialInputs.includes(input_i.name) && input_i.name.includes(input_name)) {
input_i.name = `${input_name}${slot_i}`;
slot_i++;
}
}
// Check if we need to add a new input slot
const dynamicInputs = node.inputs.filter(input => input.name.includes(input_name));
const lastDynamicInput = dynamicInputs[dynamicInputs.length - 1];
if (lastDynamicInput && lastDynamicInput.link !== null) {
// The last dynamic input is connected, so add a new one
const inputType = node.origin_type || "*";
node.addInput(`${input_name}${slot_i}`, inputType);
}
// Update widgets if they exist
updateWidgets(node, input_name);
}
function updateWidgets(node, input_name) {
if (!node.widgets) return;
const inputWidget = node.widgets.find((w) => w.name.includes(input_name));
if (inputWidget) {
const specialInputs = ["select", "sel_mode"];
const dynamicInputCount = node.inputs.filter(input =>
!specialInputs.includes(input.name) && input.name.includes(input_name)
).length;
inputWidget.options.max = dynamicInputCount;
inputWidget.value = Math.min(
Math.max(1, inputWidget.value),
inputWidget.options.max
);
}
}