fix(web): workflow's variables bugfix
This commit is contained in:
@@ -91,15 +91,11 @@ const VariableSelect: FC<VariableSelectProps> = ({
|
||||
onChange={handleChange}
|
||||
showSearch
|
||||
allowClear={allowClear}
|
||||
optionFilterProp="value"
|
||||
filterOption={(input, option) => {
|
||||
if (input === '/') return true;
|
||||
if (option?.options) {
|
||||
return option.label?.toLowerCase().includes(input.toLowerCase()) ||
|
||||
option.options.some((opt: any) =>
|
||||
opt.value.toLowerCase().includes(input.toLowerCase())
|
||||
);
|
||||
}
|
||||
return option?.label?.toLowerCase().includes(input.toLowerCase()) ?? false;
|
||||
const value = 'value' in option! ? option.value as string : '';
|
||||
return value.toLowerCase().includes(input.toLowerCase());
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -135,6 +135,78 @@ export const getCurrentNodeVariables = (nodeData: any, values: any): Suggestion[
|
||||
return nodeData.type === 'var-aggregator' && !nodeData.config.group.defaultValue ? [] : list;
|
||||
};
|
||||
|
||||
export const getChildNodeVariables = (
|
||||
selectedNode: Node,
|
||||
graphRef: React.MutableRefObject<Graph | undefined>
|
||||
): Suggestion[] => {
|
||||
const graph = graphRef.current;
|
||||
if (!graph) return [];
|
||||
|
||||
const list: Suggestion[] = [];
|
||||
const nodes = graph.getNodes();
|
||||
const edges = graph.getEdges();
|
||||
const keys = new Set<string>();
|
||||
|
||||
const childNodes = nodes.filter(node => node.getData()?.cycle === selectedNode.id);
|
||||
|
||||
const getConnectedNodes = (nodeId: string, visited = new Set<string>()): string[] => {
|
||||
if (visited.has(nodeId)) return [];
|
||||
visited.add(nodeId);
|
||||
const prev = edges.filter(e => e.getTargetCellId() === nodeId).map(e => e.getSourceCellId());
|
||||
return [...prev, ...prev.flatMap(id => getConnectedNodes(id, visited))];
|
||||
};
|
||||
|
||||
const relevantIds = new Set<string>();
|
||||
childNodes.forEach(child => {
|
||||
relevantIds.add(child.id);
|
||||
getConnectedNodes(child.id).forEach(id => relevantIds.add(id));
|
||||
});
|
||||
|
||||
relevantIds.forEach(id => {
|
||||
const node = nodes.find(n => n.id === id);
|
||||
if (!node) return;
|
||||
|
||||
const nodeData = node.getData();
|
||||
const nodeId = nodeData.id;
|
||||
const { type } = nodeData;
|
||||
|
||||
if (type in NODE_VARIABLES) {
|
||||
NODE_VARIABLES[type as keyof typeof NODE_VARIABLES].forEach(({ label, dataType, field }) => {
|
||||
const varKey = `${nodeId}_${label}`;
|
||||
if (!keys.has(varKey)) {
|
||||
keys.add(varKey);
|
||||
list.push({
|
||||
key: varKey,
|
||||
label,
|
||||
type: 'variable',
|
||||
dataType,
|
||||
value: `${nodeId}.${field}`,
|
||||
nodeData,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (type === 'parameter-extractor') {
|
||||
(nodeData.config?.params?.defaultValue || []).forEach((p: any) => {
|
||||
if (p?.name && !keys.has(`${nodeId}_${p.name}`)) {
|
||||
keys.add(`${nodeId}_${p.name}`);
|
||||
list.push({
|
||||
key: `${nodeId}_${p.name}`,
|
||||
label: p.name,
|
||||
type: 'variable',
|
||||
dataType: p.type || 'string',
|
||||
value: `${nodeId}.${p.name}`,
|
||||
nodeData,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return list;
|
||||
};
|
||||
|
||||
export const useVariableList = (
|
||||
selectedNode: Node | null | undefined,
|
||||
graphRef: React.MutableRefObject<Graph | undefined>,
|
||||
@@ -187,13 +259,13 @@ export const useVariableList = (
|
||||
} else if (pd.type === 'iteration' && pd.config.input.defaultValue) {
|
||||
let itemType = 'object';
|
||||
const iv = list.find(v => `{{${v.value}}}` === pd.config.input.defaultValue);
|
||||
if (iv?.dataType.startsWith('array[')) itemType = iv.dataType.replace(/^array\[(.+)\]$/, '$1');
|
||||
if (iv?.dataType.startsWith('array[')) {itemType = iv.dataType.replace(/^array\[(.+)\]$/, '$1');}
|
||||
addVariable(list, keys, `${pid}_item`, 'item', itemType, `${pid}.item`, pd);
|
||||
addVariable(list, keys, `${pid}_index`, 'index', 'number', `${pid}.index`, pd);
|
||||
} else if (pd.type === 'iteration' && !pd.config.input.defaultValue) {
|
||||
let itemType = 'object';
|
||||
const iv = list.find(v => `{{${v.value}}}` === pd.config.input.defaultValue);
|
||||
if (iv?.dataType.startsWith('array[')) itemType = iv.dataType.replace(/^array\[(.+)\]$/, '$1');
|
||||
if (iv?.dataType.startsWith('array[')) {itemType = iv.dataType.replace(/^array\[(.+)\]$/, '$1');}
|
||||
addVariable(list, keys, `${pid}_item`, 'item', 'string', `${pid}.item`, pd);
|
||||
addVariable(list, keys, `${pid}_index`, 'index', 'number', `${pid}.index`, pd);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import AssignmentList from './AssignmentList'
|
||||
import ToolConfig from './ToolConfig'
|
||||
import MemoryConfig from './MemoryConfig'
|
||||
import VariableList from './VariableList'
|
||||
import { useVariableList, getCurrentNodeVariables } from './hooks/useVariableList'
|
||||
import { useVariableList, getCurrentNodeVariables, getChildNodeVariables } from './hooks/useVariableList'
|
||||
import styles from './properties.module.css'
|
||||
import Editor from "../Editor";
|
||||
import RbSlider from './RbSlider'
|
||||
@@ -290,141 +290,26 @@ const Properties: FC<PropertiesProps> = ({
|
||||
let filteredList = addParentIterationVars(variableList).filter(variable => variable.dataType === 'string' || variable.dataType === 'number');
|
||||
return filteredList;
|
||||
}
|
||||
if (nodeType === 'iteration' && key === 'output') {
|
||||
let filteredList = variableList.filter(variable => variable.value.includes('sys.'));
|
||||
// Add child node output variables for loop nodes
|
||||
if (selectedNode) {
|
||||
const graph = graphRef.current;
|
||||
if (graph) {
|
||||
const nodes = graph.getNodes();
|
||||
const childNodes = nodes.filter(node => {
|
||||
const nodeData = node.getData();
|
||||
return nodeData?.cycle === selectedNode.id;
|
||||
});
|
||||
|
||||
// Add output variables from child nodes
|
||||
childNodes.forEach(childNode => {
|
||||
const childData = childNode.getData();
|
||||
const childNodeId = childData.id;
|
||||
|
||||
// Add child node output variables based on their type
|
||||
switch (childData.type) {
|
||||
case 'llm':
|
||||
case 'jinja-render':
|
||||
case 'tool':
|
||||
const outputKey = `${childNodeId}_output`;
|
||||
const existingOutput = filteredList.find(v => v.key === outputKey);
|
||||
if (!existingOutput) {
|
||||
filteredList.push({
|
||||
key: outputKey,
|
||||
label: 'output',
|
||||
type: 'variable',
|
||||
dataType: 'string',
|
||||
value: `${childNodeId}.output`,
|
||||
nodeData: childData,
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 'http-request':
|
||||
const bodyKey = `${childNodeId}_body`;
|
||||
const statusKey = `${childNodeId}_status_code`;
|
||||
if (!filteredList.find(v => v.key === bodyKey)) {
|
||||
filteredList.push({
|
||||
key: bodyKey,
|
||||
label: 'body',
|
||||
type: 'variable',
|
||||
dataType: 'string',
|
||||
value: `${childNodeId}.body`,
|
||||
nodeData: childData,
|
||||
});
|
||||
}
|
||||
if (!filteredList.find(v => v.key === statusKey)) {
|
||||
filteredList.push({
|
||||
key: statusKey,
|
||||
label: 'status_code',
|
||||
type: 'variable',
|
||||
dataType: 'number',
|
||||
value: `${childNodeId}.status_code`,
|
||||
nodeData: childData,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
if (nodeType === 'iteration' && key === 'output' || nodeType === 'loop' && key === 'condition') {
|
||||
if (!selectedNode) return [];
|
||||
let filteredList = nodeType === 'iteration'
|
||||
? variableList.filter(variable => variable.value.includes('sys.'))
|
||||
: addParentIterationVars(variableList).filter(variable => variable.nodeData.type !== 'loop');
|
||||
|
||||
const childVariables = getChildNodeVariables(selectedNode, graphRef);
|
||||
const existingKeys = new Set(filteredList.map(v => v.key));
|
||||
childVariables.forEach(v => {
|
||||
if (!existingKeys.has(v.key)) {
|
||||
filteredList.push(v);
|
||||
existingKeys.add(v.key);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return filteredList;
|
||||
}
|
||||
if (nodeType === 'iteration') {
|
||||
return variableList.filter(variable => variable.dataType.includes('array'));
|
||||
}
|
||||
if (nodeType === 'loop' && key === 'condition') {
|
||||
let filteredList = addParentIterationVars(variableList).filter(variable => variable.nodeData.type !== 'loop');
|
||||
|
||||
// Add child node output variables for loop nodes
|
||||
if (selectedNode) {
|
||||
const graph = graphRef.current;
|
||||
if (graph) {
|
||||
const nodes = graph.getNodes();
|
||||
const childNodes = nodes.filter(node => {
|
||||
const nodeData = node.getData();
|
||||
return nodeData?.cycle === selectedNode.id;
|
||||
});
|
||||
|
||||
// Add output variables from child nodes
|
||||
childNodes.forEach(childNode => {
|
||||
const childData = childNode.getData();
|
||||
const childNodeId = childData.id;
|
||||
|
||||
// Add child node output variables based on their type
|
||||
switch(childData.type) {
|
||||
case 'llm':
|
||||
case 'jinja-render':
|
||||
case 'tool':
|
||||
const outputKey = `${childNodeId}_output`;
|
||||
const existingOutput = filteredList.find(v => v.key === outputKey);
|
||||
if (!existingOutput) {
|
||||
filteredList.push({
|
||||
key: outputKey,
|
||||
label: 'output',
|
||||
type: 'variable',
|
||||
dataType: 'string',
|
||||
value: `${childNodeId}.output`,
|
||||
nodeData: childData,
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 'http-request':
|
||||
const bodyKey = `${childNodeId}_body`;
|
||||
const statusKey = `${childNodeId}_status_code`;
|
||||
if (!filteredList.find(v => v.key === bodyKey)) {
|
||||
filteredList.push({
|
||||
key: bodyKey,
|
||||
label: 'body',
|
||||
type: 'variable',
|
||||
dataType: 'string',
|
||||
value: `${childNodeId}.body`,
|
||||
nodeData: childData,
|
||||
});
|
||||
}
|
||||
if (!filteredList.find(v => v.key === statusKey)) {
|
||||
filteredList.push({
|
||||
key: statusKey,
|
||||
label: 'status_code',
|
||||
type: 'variable',
|
||||
dataType: 'number',
|
||||
value: `${childNodeId}.status_code`,
|
||||
nodeData: childData,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return filteredList;
|
||||
}
|
||||
|
||||
// For all other node types, add parent iteration variables if applicable
|
||||
let baseList = variableList;
|
||||
|
||||
Reference in New Issue
Block a user