Merge branch 'develop' of github.com:SuanmoSuanyangTechnology/MemoryBear into develop
This commit is contained in:
@@ -107,7 +107,7 @@ const AddNode: ReactShapeConfig['component'] = ({ node, graph }) => {
|
||||
<div style={{ maxHeight: '300px', overflowY: 'auto', minWidth: '240px' }}>
|
||||
{nodeLibrary.map((category, categoryIndex) => {
|
||||
const filteredNodes = category.nodes.filter(nodeType =>
|
||||
nodeType.type !== 'start' && nodeType.type !== 'end' && nodeType.type !== 'loop' && nodeType.type !== 'cycle-start'
|
||||
nodeType.type !== 'start' && nodeType.type !== 'end' && nodeType.type !== 'iteration' && nodeType.type !== 'loop' && nodeType.type !== 'cycle-start'
|
||||
);
|
||||
|
||||
if (filteredNodes.length === 0) return null;
|
||||
|
||||
@@ -33,7 +33,7 @@ const LoopNode: ReactShapeConfig['component'] = ({ node, graph }) => {
|
||||
y: cycleStartBBox.y,
|
||||
data: {
|
||||
type: 'add-node',
|
||||
label: '添加节点',
|
||||
label: t('workflow.addNode'),
|
||||
icon: '+',
|
||||
parentId: node.id,
|
||||
cycle: data.id,
|
||||
@@ -61,7 +61,7 @@ const LoopNode: ReactShapeConfig['component'] = ({ node, graph }) => {
|
||||
},
|
||||
},
|
||||
},
|
||||
zIndex: 3
|
||||
zIndex: 10
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -97,7 +97,7 @@ const LoopNode: ReactShapeConfig['component'] = ({ node, graph }) => {
|
||||
y: centerY,
|
||||
data: {
|
||||
type: 'add-node',
|
||||
label: '添加节点',
|
||||
label: t('workflow.addNode'),
|
||||
icon: '+',
|
||||
parentId: node.id,
|
||||
cycle: data.id,
|
||||
@@ -128,7 +128,7 @@ const LoopNode: ReactShapeConfig['component'] = ({ node, graph }) => {
|
||||
},
|
||||
},
|
||||
},
|
||||
zIndex: 3
|
||||
zIndex: 10
|
||||
}
|
||||
|
||||
graph.addEdge(edgeConfig)
|
||||
|
||||
@@ -151,11 +151,11 @@ const PortClickHandler: React.FC<PortClickHandlerProps> = ({ graph }) => {
|
||||
|
||||
let filteredNodes;
|
||||
if (isChildOfLoop) {
|
||||
// Use same filtering as AddNode for child nodes of loop
|
||||
// Use same filtering as AddNode for child nodes of loop, but allow break
|
||||
filteredNodes = category.nodes.filter(nodeType => !['start', 'end', 'loop', 'cycle-start', 'iteration'].includes(nodeType.type));
|
||||
} else if (isChildOfIteration) {
|
||||
// Filter out loop and iteration nodes for children of iteration nodes
|
||||
filteredNodes = category.nodes.filter(nodeType => !['start', 'end', 'loop', 'break', 'cycle-start', 'iteration'].includes(nodeType.type));
|
||||
// Filter out loop and iteration nodes for children of iteration nodes, but allow break
|
||||
filteredNodes = category.nodes.filter(nodeType => !['start', 'end', 'loop', 'cycle-start', 'iteration'].includes(nodeType.type));
|
||||
} else {
|
||||
// Original filtering for non-loop child nodes
|
||||
filteredNodes = category.nodes.filter(nodeType => !['start', 'end', 'break', 'cycle-start'].includes(nodeType.type));
|
||||
|
||||
@@ -60,7 +60,7 @@ const AssignmentList: FC<AssignmentListProps> = ({
|
||||
>
|
||||
<VariableSelect
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
options={options}
|
||||
options={options.filter(vo => vo.nodeData.type === 'loop' || vo.value.includes('conv.'))}
|
||||
popupMatchSelectWidth={false}
|
||||
onChange={() => {
|
||||
form.setFieldValue([parentName, name, 'operation'], undefined);
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import { type FC } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Input, Button, Form, Space } from 'antd';
|
||||
import { PlusOutlined, CopyOutlined, DeleteOutlined, ExpandOutlined } from '@ant-design/icons';
|
||||
import { Button, Form, Space } from 'antd';
|
||||
import { DeleteOutlined } from '@ant-design/icons';
|
||||
import { Graph, Node } from '@antv/x6';
|
||||
import type { PortMetadata } from '@antv/x6/lib/model/port';
|
||||
import Editor from '../../Editor';
|
||||
import type { Suggestion } from '../../Editor/plugin/AutocompletePlugin'
|
||||
|
||||
interface CategoryListProps {
|
||||
parentName: string;
|
||||
options: Suggestion[];
|
||||
selectedNode?: Node | null;
|
||||
graphRef?: React.MutableRefObject<Graph | undefined>;
|
||||
}
|
||||
|
||||
const CategoryList: FC<CategoryListProps> = ({ parentName, selectedNode, graphRef }) => {
|
||||
const CategoryList: FC<CategoryListProps> = ({ parentName, selectedNode, graphRef, options }) => {
|
||||
const { t } = useTranslation();
|
||||
const form = Form.useFormInstance();
|
||||
const formValues = Form.useWatch([parentName], form);
|
||||
@@ -167,9 +169,9 @@ const CategoryList: FC<CategoryListProps> = ({ parentName, selectedNode, graphRe
|
||||
name={[name, 'class_name']}
|
||||
noStyle
|
||||
>
|
||||
<Input.TextArea
|
||||
<Editor
|
||||
placeholder={t('common.pleaseEnter')}
|
||||
rows={2}
|
||||
options={options}
|
||||
/>
|
||||
</Form.Item>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { type FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Form, Button, Select, Row, Col, InputNumber, Radio, type SelectProps } from 'antd'
|
||||
import { Form, Button, Select, Row, Col, InputNumber, Radio, Input, type SelectProps } from 'antd'
|
||||
import { DeleteOutlined } from '@ant-design/icons';
|
||||
|
||||
import type { Suggestion } from '../../Editor/plugin/AutocompletePlugin'
|
||||
@@ -114,7 +114,7 @@ const ConditionList: FC<CaseListProps> = ({
|
||||
<Col span={14}>
|
||||
<Form.Item name={[field.name, 'left']} noStyle>
|
||||
<VariableSelect
|
||||
options={options}
|
||||
options={options.filter(vo => vo.value.includes('sys.') || vo.value.includes('conv.') || vo.nodeData.type === 'loop')}
|
||||
size="small"
|
||||
allowClear={false}
|
||||
popupMatchSelectWidth={false}
|
||||
@@ -186,7 +186,7 @@ const ConditionList: FC<CaseListProps> = ({
|
||||
<Radio.Button value={true}>True</Radio.Button>
|
||||
<Radio.Button value={false}>False</Radio.Button>
|
||||
</Radio.Group>
|
||||
: <Editor options={options} />
|
||||
: <Input placeholder={t('common.pleaseEnter')} />
|
||||
}
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { type FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Form, Button, Select, Row, Col, Input } from 'antd'
|
||||
import { Form, Select, Row, Col, Input } from 'antd'
|
||||
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import VariableSelect from '../VariableSelect'
|
||||
|
||||
@@ -36,7 +36,6 @@ const CycleVarsList: FC<CycleVarsListProps> = ({
|
||||
value = [],
|
||||
options,
|
||||
parentName,
|
||||
onChange,
|
||||
selectedNode,
|
||||
graphRef
|
||||
}) => {
|
||||
@@ -139,12 +138,17 @@ const CycleVarsList: FC<CycleVarsListProps> = ({
|
||||
<Form.Item name={[name, 'value']} noStyle>
|
||||
{currentInputType === 'variable' ? (
|
||||
<VariableSelect
|
||||
placeholder="选择变量"
|
||||
options={availableOptions}
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
options={availableOptions.filter(option => {
|
||||
const currentType = value?.[index]?.type;
|
||||
if (!currentType) return true;
|
||||
|
||||
return option.dataType === currentType
|
||||
})}
|
||||
/>
|
||||
) : (
|
||||
<Input.TextArea
|
||||
placeholder="输入值"
|
||||
placeholder={t('common.pleaseEnter')}
|
||||
rows={3}
|
||||
className="rb:w-full"
|
||||
/>
|
||||
|
||||
@@ -18,8 +18,22 @@ const GroupVariableList: FC<GroupVariableListProps> = ({
|
||||
isCanAdd = false
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const form = Form.useFormInstance();
|
||||
const value = form.getFieldValue(name) || [];
|
||||
|
||||
console.log('GroupVariableList', value)
|
||||
|
||||
if (!isCanAdd) {
|
||||
// Filter options based on first variable's dataType if value exists
|
||||
let filteredOptions = options;
|
||||
if (value.length > 0) {
|
||||
const firstVariableValue = value[0];
|
||||
const firstVariable = options.find(opt => `{{${opt.value}}}` === firstVariableValue);
|
||||
if (firstVariable) {
|
||||
filteredOptions = options.filter(opt => opt.dataType === firstVariable.dataType);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="rb:mb-4">
|
||||
<Row gutter={12} className="rb:mb-2!">
|
||||
@@ -38,7 +52,7 @@ const GroupVariableList: FC<GroupVariableListProps> = ({
|
||||
>
|
||||
<VariableSelect
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
options={options}
|
||||
options={filteredOptions}
|
||||
mode="multiple"
|
||||
/>
|
||||
</Form.Item>
|
||||
@@ -77,7 +91,18 @@ const GroupVariableList: FC<GroupVariableListProps> = ({
|
||||
>
|
||||
<VariableSelect
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
options={options}
|
||||
options={(() => {
|
||||
const currentGroupValue = value[name]?.value || [];
|
||||
if (currentGroupValue.length > 0) {
|
||||
const firstVariableValue = currentGroupValue[0];
|
||||
const firstVariable = options.find(opt => `{{${opt.value}}}` === firstVariableValue);
|
||||
if (firstVariable) {
|
||||
return options.filter(opt => opt.dataType === firstVariable.dataType);
|
||||
}
|
||||
}
|
||||
return options;
|
||||
})()
|
||||
}
|
||||
mode="multiple"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
@@ -90,7 +90,7 @@ const HttpRequest: FC<{ options: Suggestion[]; selectedNode?: any; graphRef?: an
|
||||
</Col>
|
||||
<Col span={16}>
|
||||
<Form.Item name="url">
|
||||
<Editor options={options} variant="outlined" />
|
||||
<Editor options={options.filter(vo => vo.dataType === 'string' || vo.dataType === 'number')} variant="outlined" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
@@ -144,7 +144,7 @@ const HttpRequest: FC<{ options: Suggestion[]; selectedNode?: any; graphRef?: an
|
||||
<Form.Item name={['body', 'data']} noStyle>
|
||||
<EditableTable
|
||||
parentName={['body', 'data']}
|
||||
options={options}
|
||||
options={options.filter(vo => vo.dataType === 'string' || vo.dataType === 'number')}
|
||||
filterBooleanType={true}
|
||||
/>
|
||||
</Form.Item>
|
||||
@@ -154,7 +154,7 @@ const HttpRequest: FC<{ options: Suggestion[]; selectedNode?: any; graphRef?: an
|
||||
<MessageEditor
|
||||
key="json"
|
||||
parentName={['body', 'data']}
|
||||
options={options}
|
||||
options={options.filter(vo => vo.dataType === 'string' || vo.dataType === 'number')}
|
||||
isArray={false}
|
||||
title="JSON"
|
||||
/>
|
||||
|
||||
@@ -91,6 +91,7 @@ const VariableSelect: FC<VariableSelectProps> = ({
|
||||
showSearch
|
||||
allowClear={allowClear}
|
||||
filterOption={(input, option) => {
|
||||
if (input === '/') return true;
|
||||
if (option?.options) {
|
||||
return option.label?.toLowerCase().includes(input.toLowerCase()) ||
|
||||
option.options.some((opt: any) =>
|
||||
|
||||
@@ -22,6 +22,7 @@ import ConditionList from './ConditionList'
|
||||
import CycleVarsList from './CycleVarsList'
|
||||
import AssignmentList from './AssignmentList'
|
||||
import ToolConfig from './ToolConfig'
|
||||
// import { calculateVariableList } from './utils/variableListCalculator'
|
||||
|
||||
interface PropertiesProps {
|
||||
selectedNode?: Node | null;
|
||||
@@ -338,112 +339,35 @@ const Properties: FC<PropertiesProps> = ({
|
||||
const parentLoopNode = getParentLoopNode(selectedNode.id);
|
||||
|
||||
console.log('childNodeIds', selectedNode, childNodeIds)
|
||||
const allRelevantNodeIds = [...allPreviousNodeIds, ...childNodeIds];
|
||||
let allRelevantNodeIds = [...allPreviousNodeIds, ...childNodeIds];
|
||||
|
||||
// Add parent loop/iteration node variables if current node is a child
|
||||
// Add variables from nodes preceding the parent loop/iteration node if current node is a child
|
||||
if (parentLoopNode) {
|
||||
const parentData = parentLoopNode.getData();
|
||||
const parentNodeId = parentLoopNode.getData().id;
|
||||
|
||||
if (parentData.type === 'loop') {
|
||||
const cycleVars = parentData.cycle_vars || [];
|
||||
cycleVars.forEach((cycleVar: any) => {
|
||||
const key = `${parentNodeId}_cycle_${cycleVar.name}`;
|
||||
if (!addedKeys.has(key)) {
|
||||
addedKeys.add(key);
|
||||
variableList.push({
|
||||
key,
|
||||
label: cycleVar.name,
|
||||
type: 'variable',
|
||||
dataType: cycleVar.type || 'String',
|
||||
value: `${parentNodeId}.${cycleVar.name}`,
|
||||
nodeData: parentData,
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (parentData.type === 'iteration') {
|
||||
// Add item and index variables for iteration parent
|
||||
const itemKey = `${parentNodeId}_item`;
|
||||
const indexKey = `${parentNodeId}_index`;
|
||||
|
||||
if (!addedKeys.has(itemKey)) {
|
||||
addedKeys.add(itemKey);
|
||||
variableList.push({
|
||||
key: itemKey,
|
||||
label: 'item',
|
||||
type: 'variable',
|
||||
dataType: 'Object',
|
||||
value: `${parentNodeId}.item`,
|
||||
nodeData: parentData,
|
||||
});
|
||||
}
|
||||
|
||||
if (!addedKeys.has(indexKey)) {
|
||||
addedKeys.add(indexKey);
|
||||
variableList.push({
|
||||
key: indexKey,
|
||||
label: 'index',
|
||||
type: 'variable',
|
||||
dataType: 'Number',
|
||||
value: `${parentNodeId}.index`,
|
||||
nodeData: parentData,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Check if parent loop/iteration is connected to http-request via ERROR connection
|
||||
if (parentData.type === 'loop' || parentData.type === 'iteration') {
|
||||
const parentPreviousNodeIds = getAllPreviousNodes(parentLoopNode.id);
|
||||
parentPreviousNodeIds.forEach(prevNodeId => {
|
||||
const prevNode = nodes.find(n => n.id === prevNodeId);
|
||||
if (!prevNode) return;
|
||||
|
||||
const prevNodeData = prevNode.getData();
|
||||
if (prevNodeData.type === 'http-request') {
|
||||
// Check if connected via ERROR connection point
|
||||
const errorEdges = edges.filter(edge => {
|
||||
return edge.getTargetCellId() === parentLoopNode.id &&
|
||||
edge.getSourceCellId() === prevNodeId &&
|
||||
edge.getSourcePortId() === 'ERROR'
|
||||
});
|
||||
|
||||
if (errorEdges.length > 0) {
|
||||
const errorMessageKey = `${prevNodeData.id}_error_message`;
|
||||
const errorTypeKey = `${prevNodeData.id}_error_type`;
|
||||
|
||||
if (!addedKeys.has(errorMessageKey)) {
|
||||
addedKeys.add(errorMessageKey);
|
||||
variableList.push({
|
||||
key: errorMessageKey,
|
||||
label: 'error_message',
|
||||
type: 'variable',
|
||||
dataType: 'string',
|
||||
value: `${prevNodeData.id}.error_message`,
|
||||
nodeData: prevNodeData,
|
||||
});
|
||||
}
|
||||
|
||||
if (!addedKeys.has(errorTypeKey)) {
|
||||
addedKeys.add(errorTypeKey);
|
||||
variableList.push({
|
||||
key: errorTypeKey,
|
||||
label: 'error_type',
|
||||
type: 'variable',
|
||||
dataType: 'string',
|
||||
value: `${prevNodeData.id}.error_type`,
|
||||
nodeData: prevNodeData,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Add variables from nodes preceding the parent loop/iteration node
|
||||
const parentPreviousNodeIds = getAllPreviousNodes(parentLoopNode.id);
|
||||
allRelevantNodeIds.push(...parentPreviousNodeIds);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Add conversation variables from global config
|
||||
const conversationVariables = workflowConfig?.variables || [];
|
||||
|
||||
conversationVariables.forEach((variable: any) => {
|
||||
const key = `CONVERSATION_${variable.name}`;
|
||||
if (!addedKeys.has(key)) {
|
||||
addedKeys.add(key);
|
||||
variableList.push({
|
||||
key,
|
||||
label: variable.name,
|
||||
type: 'variable',
|
||||
dataType: variable.type,
|
||||
value: `conv.${variable.name}`,
|
||||
nodeData: { type: 'CONVERSATION', name: 'CONVERSATION', icon: '' },
|
||||
group: 'CONVERSATION'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
allRelevantNodeIds.forEach(nodeId => {
|
||||
const node = nodes.find(n => n.id === nodeId);
|
||||
if (!node) return;
|
||||
@@ -496,7 +420,7 @@ const Properties: FC<PropertiesProps> = ({
|
||||
key: llmKey,
|
||||
label: 'output',
|
||||
type: 'variable',
|
||||
dataType: 'String',
|
||||
dataType: 'string',
|
||||
value: `${dataNodeId}.output`,
|
||||
nodeData: nodeData,
|
||||
});
|
||||
@@ -565,6 +489,17 @@ const Properties: FC<PropertiesProps> = ({
|
||||
const groupVariables = nodeData.config.group_variables.defaultValue || [];
|
||||
groupVariables?.forEach((groupVar: any) => {
|
||||
if (!groupVar || !groupVar.key) return;
|
||||
|
||||
// Determine dataType from first variable in the group
|
||||
let groupDataType = 'string';
|
||||
if (groupVar.value && Array.isArray(groupVar.value) && groupVar.value.length > 0) {
|
||||
const firstVariableValue = groupVar.value[0];
|
||||
const firstVariable = variableList.find(v => `{{${v.value}}}` === firstVariableValue);
|
||||
if (firstVariable) {
|
||||
groupDataType = firstVariable.dataType;
|
||||
}
|
||||
}
|
||||
|
||||
const groupVarKey = `${dataNodeId}_${groupVar.key}`;
|
||||
if (!addedKeys.has(groupVarKey)) {
|
||||
addedKeys.add(groupVarKey);
|
||||
@@ -572,14 +507,26 @@ const Properties: FC<PropertiesProps> = ({
|
||||
key: groupVarKey,
|
||||
label: groupVar.key,
|
||||
type: 'variable',
|
||||
dataType: 'string',
|
||||
dataType: groupDataType,
|
||||
value: `${dataNodeId}.${groupVar.key}`,
|
||||
nodeData: nodeData,
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// If group=false, add output variable
|
||||
// If group=false, add output variable with type from first group_variable
|
||||
const groupVariables = nodeData.config.group_variables.defaultValue || [];
|
||||
const firstVariable = groupVariables[0];
|
||||
let outputDataType: string = 'any';
|
||||
if (firstVariable) {
|
||||
const filterVo = [...variableList].find(v => {
|
||||
return `{{${v.value}}}` === firstVariable
|
||||
})
|
||||
if (filterVo) {
|
||||
outputDataType = filterVo?.dataType
|
||||
}
|
||||
}
|
||||
|
||||
const varAggregatorKey = `${dataNodeId}_output`;
|
||||
if (!addedKeys.has(varAggregatorKey)) {
|
||||
addedKeys.add(varAggregatorKey);
|
||||
@@ -587,7 +534,7 @@ const Properties: FC<PropertiesProps> = ({
|
||||
key: varAggregatorKey,
|
||||
label: 'output',
|
||||
type: 'variable',
|
||||
dataType: 'string',
|
||||
dataType: outputDataType,
|
||||
value: `${dataNodeId}.output`,
|
||||
nodeData: nodeData,
|
||||
});
|
||||
@@ -684,21 +631,20 @@ const Properties: FC<PropertiesProps> = ({
|
||||
nodeData: nodeData,
|
||||
});
|
||||
}
|
||||
if (!addedKeys.has(outputKey)) {
|
||||
addedKeys.add(outputKey);
|
||||
variableList.push({
|
||||
key: outputKey,
|
||||
label: 'output',
|
||||
type: 'variable',
|
||||
dataType: 'string',
|
||||
value: `${dataNodeId}.output`,
|
||||
nodeData: nodeData,
|
||||
});
|
||||
}
|
||||
// if (!addedKeys.has(outputKey)) {
|
||||
// addedKeys.add(outputKey);
|
||||
// variableList.push({
|
||||
// key: outputKey,
|
||||
// label: 'output',
|
||||
// type: 'variable',
|
||||
// dataType: 'string',
|
||||
// value: `${dataNodeId}.output`,
|
||||
// nodeData: nodeData,
|
||||
// });
|
||||
// }
|
||||
break
|
||||
case 'iteration':
|
||||
const iterationOutputKey = `${dataNodeId}_output`;
|
||||
const iterationItemKey = `${dataNodeId}_item`;
|
||||
if (!addedKeys.has(iterationOutputKey)) {
|
||||
addedKeys.add(iterationOutputKey);
|
||||
// Get the data type from the output configuration, default to string
|
||||
@@ -715,22 +661,11 @@ const Properties: FC<PropertiesProps> = ({
|
||||
key: iterationOutputKey,
|
||||
label: 'output',
|
||||
type: 'variable',
|
||||
dataType: outputDataType,
|
||||
dataType: `array[${outputDataType}]`,
|
||||
value: `${dataNodeId}.output`,
|
||||
nodeData: nodeData,
|
||||
});
|
||||
}
|
||||
if (!addedKeys.has(iterationItemKey)) {
|
||||
addedKeys.add(iterationItemKey);
|
||||
variableList.push({
|
||||
key: iterationItemKey,
|
||||
label: 'item',
|
||||
type: 'variable',
|
||||
dataType: 'string',
|
||||
value: `${dataNodeId}.item`,
|
||||
nodeData: nodeData,
|
||||
});
|
||||
}
|
||||
break
|
||||
case 'loop':
|
||||
const cycleVars = nodeData.config.cycle_vars.defaultValue || [];
|
||||
@@ -760,47 +695,337 @@ const Properties: FC<PropertiesProps> = ({
|
||||
key: toolDataKey,
|
||||
label: 'data',
|
||||
type: 'variable',
|
||||
dataType: 'object',
|
||||
dataType: 'string',
|
||||
value: `${dataNodeId}.data`,
|
||||
nodeData: nodeData,
|
||||
});
|
||||
}
|
||||
break
|
||||
case 'memory-read':
|
||||
const memoryReadAnswerKey = `${dataNodeId}_answer`;
|
||||
const memoryReadIntermediateOutputs = `${dataNodeId}_intermediate_outputs`;
|
||||
if (!addedKeys.has(memoryReadAnswerKey)) {
|
||||
addedKeys.add(memoryReadAnswerKey);
|
||||
variableList.push({
|
||||
key: memoryReadAnswerKey,
|
||||
label: 'answer',
|
||||
type: 'variable',
|
||||
dataType: 'string',
|
||||
value: `${dataNodeId}.answer`,
|
||||
nodeData: nodeData,
|
||||
});
|
||||
}
|
||||
if (!addedKeys.has(memoryReadIntermediateOutputs)) {
|
||||
addedKeys.add(memoryReadIntermediateOutputs);
|
||||
variableList.push({
|
||||
key: memoryReadIntermediateOutputs,
|
||||
label: 'intermediate_outputs',
|
||||
type: 'variable',
|
||||
dataType: 'array[object]',
|
||||
value: `${dataNodeId}.intermediate_outputs`,
|
||||
nodeData: nodeData,
|
||||
});
|
||||
}
|
||||
break
|
||||
}
|
||||
});
|
||||
|
||||
// Add conversation variables from global config
|
||||
const conversationVariables = workflowConfig?.variables || [];
|
||||
|
||||
conversationVariables.forEach((variable: any) => {
|
||||
const key = `CONVERSATION_${variable.name}`;
|
||||
if (!addedKeys.has(key)) {
|
||||
addedKeys.add(key);
|
||||
variableList.push({
|
||||
key,
|
||||
label: variable.name,
|
||||
type: 'variable',
|
||||
dataType: variable.type,
|
||||
value: `conv.${variable.name}`,
|
||||
nodeData: { type: 'CONVERSATION', name: 'CONVERSATION', icon: '' },
|
||||
group: 'CONVERSATION'
|
||||
|
||||
// Add parent loop/iteration node variables if current node is a child
|
||||
if (parentLoopNode) {
|
||||
const parentData = parentLoopNode.getData();
|
||||
const parentNodeId = parentLoopNode.getData().id;
|
||||
|
||||
if (parentData.type === 'loop') {
|
||||
const cycleVars = parentData.cycle_vars || [];
|
||||
cycleVars.forEach((cycleVar: any) => {
|
||||
const key = `${parentNodeId}_cycle_${cycleVar.name}`;
|
||||
if (!addedKeys.has(key)) {
|
||||
addedKeys.add(key);
|
||||
variableList.push({
|
||||
key,
|
||||
label: cycleVar.name,
|
||||
type: 'variable',
|
||||
dataType: cycleVar.type || 'String',
|
||||
value: `${parentNodeId}.${cycleVar.name}`,
|
||||
nodeData: parentData,
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (parentData.type === 'iteration') {
|
||||
// Add item and index variables for iteration parent only if input has value
|
||||
if (parentData.config.input.defaultValue) {
|
||||
const itemKey = `${parentNodeId}_item`;
|
||||
const indexKey = `${parentNodeId}_index`;
|
||||
|
||||
// Determine item dataType from input variable
|
||||
let itemDataType = 'object';
|
||||
const inputVariable = variableList.find(v => `{{${v.value}}}` === parentData.config.input.defaultValue);
|
||||
console.log('itemDataType defaultValue', parentData.config.input.defaultValue, variableList, inputVariable)
|
||||
if (inputVariable && inputVariable.dataType.startsWith('array[')) {
|
||||
itemDataType = inputVariable.dataType.replace(/^array\[(.+)\]$/, '$1');
|
||||
console.log('itemDataType', itemDataType)
|
||||
}
|
||||
|
||||
|
||||
if (!addedKeys.has(itemKey)) {
|
||||
addedKeys.add(itemKey);
|
||||
variableList.push({
|
||||
key: itemKey,
|
||||
label: 'item',
|
||||
type: 'variable',
|
||||
dataType: itemDataType,
|
||||
value: `${parentNodeId}.item`,
|
||||
nodeData: parentData,
|
||||
});
|
||||
}
|
||||
|
||||
if (!addedKeys.has(indexKey)) {
|
||||
addedKeys.add(indexKey);
|
||||
variableList.push({
|
||||
key: indexKey,
|
||||
label: 'index',
|
||||
type: 'variable',
|
||||
dataType: 'number',
|
||||
value: `${parentNodeId}.index`,
|
||||
nodeData: parentData,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if parent loop/iteration is connected to http-request via ERROR connection
|
||||
if (parentData.type === 'loop' || parentData.type === 'iteration') {
|
||||
const parentPreviousNodeIds = getAllPreviousNodes(parentLoopNode.id);
|
||||
parentPreviousNodeIds.forEach(prevNodeId => {
|
||||
const prevNode = nodes.find(n => n.id === prevNodeId);
|
||||
if (!prevNode) return;
|
||||
|
||||
const prevNodeData = prevNode.getData();
|
||||
if (prevNodeData.type === 'http-request') {
|
||||
// Check if connected via ERROR connection point
|
||||
const errorEdges = edges.filter(edge => {
|
||||
return edge.getTargetCellId() === parentLoopNode.id &&
|
||||
edge.getSourceCellId() === prevNodeId &&
|
||||
edge.getSourcePortId() === 'ERROR'
|
||||
});
|
||||
|
||||
if (errorEdges.length > 0) {
|
||||
const errorMessageKey = `${prevNodeData.id}_error_message`;
|
||||
const errorTypeKey = `${prevNodeData.id}_error_type`;
|
||||
|
||||
if (!addedKeys.has(errorMessageKey)) {
|
||||
addedKeys.add(errorMessageKey);
|
||||
variableList.push({
|
||||
key: errorMessageKey,
|
||||
label: 'error_message',
|
||||
type: 'variable',
|
||||
dataType: 'string',
|
||||
value: `${prevNodeData.id}.error_message`,
|
||||
nodeData: prevNodeData,
|
||||
});
|
||||
}
|
||||
|
||||
if (!addedKeys.has(errorTypeKey)) {
|
||||
addedKeys.add(errorTypeKey);
|
||||
variableList.push({
|
||||
key: errorTypeKey,
|
||||
label: 'error_type',
|
||||
type: 'variable',
|
||||
dataType: 'string',
|
||||
value: `${prevNodeData.id}.error_type`,
|
||||
nodeData: prevNodeData,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return variableList;
|
||||
}, [selectedNode, graphRef, workflowConfig?.variables]);
|
||||
|
||||
// Filter out boolean type variables for loop and llm nodes
|
||||
const getFilteredVariableList = (nodeType?: string) => {
|
||||
if (nodeType === 'loop' || nodeType === 'llm') {
|
||||
return variableList.filter(variable => variable.dataType !== 'boolean');
|
||||
const getFilteredVariableList = (nodeType?: string, key?: string) => {
|
||||
// Check if current node is a child of iteration node
|
||||
const parentIterationNode = selectedNode ? (() => {
|
||||
const nodes = graphRef.current?.getNodes() || [];
|
||||
const nodeData = selectedNode.getData();
|
||||
const cycle = nodeData?.cycle;
|
||||
|
||||
if (cycle) {
|
||||
const parentNode = nodes.find(n => n.getData().id === cycle);
|
||||
if (parentNode) {
|
||||
const parentData = parentNode.getData();
|
||||
if (parentData?.type === 'iteration') {
|
||||
return parentNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
})() : null;
|
||||
|
||||
// Helper function to add parent iteration variables
|
||||
const addParentIterationVars = (filteredList: any[]) => {
|
||||
if (parentIterationNode) {
|
||||
const parentData = parentIterationNode.getData();
|
||||
const parentNodeId = parentData.id;
|
||||
|
||||
if (parentData.config?.input?.defaultValue) {
|
||||
const itemKey = `${parentNodeId}_item`;
|
||||
const indexKey = `${parentNodeId}_index`;
|
||||
|
||||
const existingItemVar = filteredList.find(v => v.key === itemKey);
|
||||
const existingIndexVar = filteredList.find(v => v.key === indexKey);
|
||||
|
||||
if (!existingItemVar) {
|
||||
// Determine item dataType from input variable
|
||||
let itemDataType = 'object';
|
||||
const inputVariable = variableList.find(v => `{{${v.value}}}` === parentData.config.input.defaultValue);
|
||||
if (inputVariable && inputVariable.dataType.startsWith('array[')) {
|
||||
itemDataType = inputVariable.dataType.replace(/^array\[(.+)\]$/, '$1');
|
||||
}
|
||||
|
||||
filteredList.push({
|
||||
key: itemKey,
|
||||
label: 'item',
|
||||
type: 'variable',
|
||||
dataType: itemDataType,
|
||||
value: `${parentNodeId}.item`,
|
||||
nodeData: parentData,
|
||||
});
|
||||
}
|
||||
|
||||
if (!existingIndexVar) {
|
||||
filteredList.push({
|
||||
key: indexKey,
|
||||
label: 'index',
|
||||
type: 'variable',
|
||||
dataType: 'number',
|
||||
value: `${parentNodeId}.index`,
|
||||
nodeData: parentData,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return filteredList;
|
||||
};
|
||||
|
||||
if (nodeType === 'llm') {
|
||||
// For LLM nodes that are children of iteration or loop nodes, include parent variables
|
||||
const parentLoopNode = selectedNode ? (() => {
|
||||
const nodes = graphRef.current?.getNodes() || [];
|
||||
const nodeData = selectedNode.getData();
|
||||
const cycle = nodeData?.cycle;
|
||||
|
||||
if (cycle) {
|
||||
const parentNode = nodes.find(n => n.getData().id === cycle);
|
||||
if (parentNode) {
|
||||
const parentData = parentNode.getData();
|
||||
if (parentData?.type === 'loop' || parentData?.type === 'iteration') {
|
||||
return parentNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
})() : null;
|
||||
|
||||
let filteredList = variableList.filter(variable => variable.dataType !== 'boolean');
|
||||
|
||||
// If this LLM node is a child of iteration/loop, ensure parent variables are included
|
||||
if (parentLoopNode) {
|
||||
const parentData = parentLoopNode.getData();
|
||||
const parentNodeId = parentData.id;
|
||||
|
||||
// Ensure parent loop/iteration variables are included
|
||||
if (parentData.type === 'loop') {
|
||||
const cycleVars = parentData.cycle_vars || [];
|
||||
cycleVars.forEach((cycleVar: any) => {
|
||||
const key = `${parentNodeId}_cycle_${cycleVar.name}`;
|
||||
const existingVar = filteredList.find(v => v.key === key);
|
||||
if (!existingVar && cycleVar.name && cycleVar.type !== 'boolean') {
|
||||
filteredList.push({
|
||||
key,
|
||||
label: cycleVar.name,
|
||||
type: 'variable',
|
||||
dataType: cycleVar.type || 'String',
|
||||
value: `${parentNodeId}.${cycleVar.name}`,
|
||||
nodeData: parentData,
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (parentData.type === 'iteration') {
|
||||
// Add item and index variables for iteration parent
|
||||
if (parentData.config?.input?.defaultValue) {
|
||||
const itemKey = `${parentNodeId}_item`;
|
||||
const indexKey = `${parentNodeId}_index`;
|
||||
|
||||
const existingItemVar = filteredList.find(v => v.key === itemKey);
|
||||
const existingIndexVar = filteredList.find(v => v.key === indexKey);
|
||||
|
||||
if (!existingItemVar) {
|
||||
// Determine item dataType from input variable
|
||||
let itemDataType = 'object';
|
||||
const inputVariable = variableList.find(v => `{{${v.value}}}` === parentData.config.input.defaultValue);
|
||||
if (inputVariable && inputVariable.dataType.startsWith('array[')) {
|
||||
itemDataType = inputVariable.dataType.replace(/^array\[(.+)\]$/, '$1');
|
||||
}
|
||||
|
||||
filteredList.push({
|
||||
key: itemKey,
|
||||
label: 'item',
|
||||
type: 'variable',
|
||||
dataType: itemDataType,
|
||||
value: `${parentNodeId}.item`,
|
||||
nodeData: parentData,
|
||||
});
|
||||
}
|
||||
|
||||
if (!existingIndexVar) {
|
||||
filteredList.push({
|
||||
key: indexKey,
|
||||
label: 'index',
|
||||
type: 'variable',
|
||||
dataType: 'Number',
|
||||
value: `${parentNodeId}.index`,
|
||||
nodeData: parentData,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filteredList;
|
||||
}
|
||||
return variableList;
|
||||
if (nodeType === 'knowledge-retrieval' || nodeType === 'parameter-extractor' && key !== 'prompt' || nodeType === 'memory-read' || nodeType === 'memory-write' || nodeType === 'question-classifier') {
|
||||
let filteredList = variableList.filter(variable => variable.dataType === 'string');
|
||||
return addParentIterationVars(filteredList);
|
||||
}
|
||||
if (nodeType === 'parameter-extractor' && key === 'prompt') {
|
||||
let filteredList = variableList.filter(variable => variable.dataType === 'string' || variable.dataType === 'number');
|
||||
return addParentIterationVars(filteredList);
|
||||
}
|
||||
if (nodeType === 'iteration' && key === 'output') {
|
||||
return variableList.filter(variable => variable.value.includes('sys.'));
|
||||
}
|
||||
if (nodeType === 'iteration') {
|
||||
return variableList.filter(variable => variable.dataType.includes('array'));
|
||||
}
|
||||
if (nodeType === 'loop' && key === 'condition') {
|
||||
let filteredList = variableList.filter(variable => variable.nodeData.type !== 'loop');
|
||||
return addParentIterationVars(filteredList);
|
||||
}
|
||||
|
||||
// For all other node types, add parent iteration variables if applicable
|
||||
let baseList = variableList;
|
||||
return addParentIterationVars(baseList);
|
||||
};
|
||||
|
||||
// const defaultVariableList = calculateVariableList(selectedNode as Node, graphRef, workflowConfig )
|
||||
|
||||
console.log('values', values)
|
||||
console.log('variableList', variableList, selectedNode?.data)
|
||||
// console.log('variableList', variableList, defaultVariableList)
|
||||
|
||||
return (
|
||||
<div className="rb:w-75 rb:fixed rb:right-0 rb:top-16 rb:bottom-0 rb:p-3">
|
||||
@@ -901,11 +1126,10 @@ const Properties: FC<PropertiesProps> = ({
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Form.Item key={key} name={key}>
|
||||
<MessageEditor
|
||||
key={key}
|
||||
key={key}
|
||||
options={contextVariableList.filter(variable => variable.nodeData?.type !== 'knowledge-retrieval')}
|
||||
parentName={key}
|
||||
/>
|
||||
@@ -915,7 +1139,12 @@ const Properties: FC<PropertiesProps> = ({
|
||||
if (selectedNode?.data?.type === 'end' && key === 'output') {
|
||||
return (
|
||||
<Form.Item key={key} name={key}>
|
||||
<MessageEditor key={key} isArray={false} parentName={key} options={variableList} />
|
||||
<MessageEditor
|
||||
key={key}
|
||||
isArray={false}
|
||||
parentName={key}
|
||||
options={variableList.filter(variable => variable.nodeData?.type !== 'knowledge-retrieval')}
|
||||
/>
|
||||
</Form.Item>
|
||||
)
|
||||
}
|
||||
@@ -943,7 +1172,7 @@ const Properties: FC<PropertiesProps> = ({
|
||||
isArray={!!config.isArray}
|
||||
parentName={key}
|
||||
enableJinja2={config.enableJinja2 as boolean}
|
||||
options={getFilteredVariableList(selectedNode?.data?.type)}
|
||||
options={getFilteredVariableList(selectedNode?.data?.type, key)}
|
||||
/>
|
||||
</Form.Item>
|
||||
)
|
||||
@@ -964,7 +1193,7 @@ const Properties: FC<PropertiesProps> = ({
|
||||
<Form.Item key={key} name={key}>
|
||||
<GroupVariableList
|
||||
name={key}
|
||||
options={getFilteredVariableList(selectedNode?.data?.type)}
|
||||
options={getFilteredVariableList(selectedNode?.data?.type, key)}
|
||||
isCanAdd={!!(values as any)?.group}
|
||||
/>
|
||||
</Form.Item>
|
||||
@@ -976,7 +1205,7 @@ const Properties: FC<PropertiesProps> = ({
|
||||
<Form.Item key={key} name={key}>
|
||||
<CaseList
|
||||
name={key}
|
||||
options={getFilteredVariableList(selectedNode?.data?.type)}
|
||||
options={getFilteredVariableList(selectedNode?.data?.type, key)}
|
||||
selectedNode={selectedNode}
|
||||
graphRef={graphRef}
|
||||
/>
|
||||
@@ -989,7 +1218,7 @@ const Properties: FC<PropertiesProps> = ({
|
||||
<Form.Item key={key} name={key}
|
||||
label={t(`workflow.config.${selectedNode?.data?.type}.${key}`)}
|
||||
>
|
||||
<MappingList name={key} options={getFilteredVariableList(selectedNode?.data?.type)} />
|
||||
<MappingList name={key} options={getFilteredVariableList(selectedNode?.data?.type, key)} />
|
||||
</Form.Item>
|
||||
|
||||
)
|
||||
@@ -999,7 +1228,7 @@ const Properties: FC<PropertiesProps> = ({
|
||||
<Form.Item key={key} name={key}>
|
||||
<CycleVarsList
|
||||
parentName={key}
|
||||
options={getFilteredVariableList(selectedNode?.data?.type)}
|
||||
options={getFilteredVariableList(selectedNode?.data?.type, key)}
|
||||
/>
|
||||
</Form.Item>
|
||||
)
|
||||
@@ -1013,9 +1242,9 @@ const Properties: FC<PropertiesProps> = ({
|
||||
if (config.filterLoopIterationVars) {
|
||||
const loopIterationVars: Suggestion[] = [];
|
||||
|
||||
return [...getFilteredVariableList(selectedNode?.data?.type), ...loopIterationVars];
|
||||
return [...getFilteredVariableList(selectedNode?.data?.type, key), ...loopIterationVars];
|
||||
}
|
||||
return getFilteredVariableList(selectedNode?.data?.type);
|
||||
return getFilteredVariableList(selectedNode?.data?.type, key);
|
||||
})()
|
||||
}
|
||||
/>
|
||||
@@ -1060,7 +1289,7 @@ const Properties: FC<PropertiesProps> = ({
|
||||
? <VariableSelect
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
options={(() => {
|
||||
const baseVariableList = getFilteredVariableList(selectedNode?.data?.type);
|
||||
const baseVariableList = getFilteredVariableList(selectedNode?.data?.type, key);
|
||||
// Apply filtering if specified in config
|
||||
if (config.filterNodeTypes || config.filterVariableNames) {
|
||||
return baseVariableList.filter(variable => {
|
||||
@@ -1068,7 +1297,7 @@ const Properties: FC<PropertiesProps> = ({
|
||||
(Array.isArray(config.filterNodeTypes) && config.filterNodeTypes.includes(variable.nodeData?.type));
|
||||
const variableNameMatch = !config.filterVariableNames ||
|
||||
(Array.isArray(config.filterVariableNames) && config.filterVariableNames.includes(variable.label));
|
||||
return nodeTypeMatch && variableNameMatch;
|
||||
return nodeTypeMatch || variableNameMatch;
|
||||
});
|
||||
}
|
||||
// Filter child nodes for iteration output
|
||||
@@ -1085,7 +1314,7 @@ const Properties: FC<PropertiesProps> = ({
|
||||
});
|
||||
|
||||
return baseVariableList.filter(variable =>
|
||||
childNodes.some(node => node.id === variable.nodeData?.id)
|
||||
childNodes.some(node => node.id === variable.nodeData?.id) || selectedNode?.data?.type === 'iteration' && key === 'output' && variable.value.includes('sys.')
|
||||
);
|
||||
}
|
||||
return baseVariableList;
|
||||
@@ -1095,7 +1324,12 @@ const Properties: FC<PropertiesProps> = ({
|
||||
: config.type === 'switch'
|
||||
? <Switch onChange={key === 'group' ? () => { form.setFieldValue('group_variables', []) } : undefined} />
|
||||
: config.type === 'categoryList'
|
||||
? <CategoryList parentName={key} selectedNode={selectedNode} graphRef={graphRef} />
|
||||
? <CategoryList
|
||||
parentName={key}
|
||||
selectedNode={selectedNode}
|
||||
graphRef={graphRef}
|
||||
options={getFilteredVariableList(selectedNode?.data?.type, key)}
|
||||
/>
|
||||
: config.type === 'conditionList'
|
||||
? <ConditionList
|
||||
parentName={key}
|
||||
@@ -1109,18 +1343,9 @@ const Properties: FC<PropertiesProps> = ({
|
||||
value: `${selectedNode.getData().id}.${cycleVar.name}`,
|
||||
nodeData: selectedNode.getData(),
|
||||
}));
|
||||
return [...variableList.filter(variable => {
|
||||
// Keep conversation variables
|
||||
if (variable.group === 'CONVERSATION') return true;
|
||||
// Keep sys variables from start nodes
|
||||
if (variable.nodeData?.type === 'start' && variable.value?.startsWith('sys.')) return true;
|
||||
// Keep variables from non-start nodes
|
||||
if (variable.nodeData?.type !== 'start' && variable.nodeData?.type !== 'http-request' && variable.dataType !== 'boolean') return true;
|
||||
// Filter out custom variables from start nodes
|
||||
return false;
|
||||
}), ...cycleVarSuggestions];
|
||||
})()
|
||||
}
|
||||
|
||||
return [...getFilteredVariableList(selectedNode?.data?.type, key), ...cycleVarSuggestions];
|
||||
})()}
|
||||
selectedNode={selectedNode}
|
||||
graphRef={graphRef}
|
||||
addBtnText={t('workflow.config.addCase')}
|
||||
|
||||
@@ -270,7 +270,7 @@ export const nodeLibrary: NodeLibrary[] = [
|
||||
config: {
|
||||
input: {
|
||||
type: 'variableList',
|
||||
filterNodeTypes: ['knowledge-retrieval'],
|
||||
filterNodeTypes: ['knowledge-retrieval', 'iteration', 'loop'],
|
||||
filterVariableNames: ['message']
|
||||
},
|
||||
parallel: {
|
||||
@@ -334,8 +334,7 @@ export const nodeLibrary: NodeLibrary[] = [
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "assigner", icon: assignerIcon,
|
||||
{ type: "assigner", icon: assignerIcon,
|
||||
config: {
|
||||
assignments: {
|
||||
type: 'assignmentList',
|
||||
@@ -656,4 +655,114 @@ export const graphNodeLibrary: Record<string, NodeConfig> = {
|
||||
items: [{ group: 'left' }],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export interface OutputVariable {
|
||||
default?: Array<{
|
||||
name: string;
|
||||
type: string;
|
||||
}>;
|
||||
define?: string[];
|
||||
sys?: Array<{
|
||||
name: string;
|
||||
type: string;
|
||||
}>;
|
||||
error?: Array<{
|
||||
name: string;
|
||||
type: string;
|
||||
}>;
|
||||
}
|
||||
export const outputVariable: { [key: string]: OutputVariable } = {
|
||||
start: {
|
||||
sys: [
|
||||
{ name: "message", type: "string" },
|
||||
{ name: "conversation_id", type: "string" },
|
||||
{ name: "execution_id", type: "string", },
|
||||
{ name: "workspace_id", type: "string" },
|
||||
{ name: "user_id", type: "string" },
|
||||
],
|
||||
define: ['variables']
|
||||
},
|
||||
end: {
|
||||
},
|
||||
llm: {
|
||||
default: [
|
||||
{ name: "output", type: "string" },
|
||||
]
|
||||
},
|
||||
'knowledge-retrieval': {
|
||||
default: [
|
||||
{ name: "output", type: "array[object]" },
|
||||
]
|
||||
},
|
||||
'parameter-extractor': {
|
||||
default: [
|
||||
{ name: "__is_success", type: "number" },
|
||||
{ name: "__reason", type: "string" },
|
||||
],
|
||||
define: ['params']
|
||||
},
|
||||
'memory-read': {
|
||||
default: [
|
||||
{ name: "answer", type: "string" },
|
||||
{ name: "intermediate_outputs", type: "array[object]" },
|
||||
],
|
||||
},
|
||||
'memory-write': {
|
||||
|
||||
},
|
||||
'if-else': {
|
||||
|
||||
},
|
||||
'question-classifier': {
|
||||
default: [
|
||||
{ name: "class_name", type: "string" },
|
||||
// { name: "output", type: "string" },
|
||||
],
|
||||
},
|
||||
'iteration': {
|
||||
default: [
|
||||
// { name: "item", type: "string" }, // 仅内部使用
|
||||
{ name: "output", type: "array[string]" },
|
||||
],
|
||||
},
|
||||
'loop': {
|
||||
define: ['cycle_vars']
|
||||
},
|
||||
'cycle-start': {
|
||||
|
||||
},
|
||||
'break': {
|
||||
|
||||
},
|
||||
'var-aggregator': {
|
||||
// default: [
|
||||
// { name: "output", type: "string" },
|
||||
// ],
|
||||
define: ['group_variables']
|
||||
},
|
||||
'assigner': {
|
||||
|
||||
},
|
||||
'http-request': {
|
||||
default: [
|
||||
{ name: "body", type: "string" },
|
||||
{ name: "status_code", type: "number" },
|
||||
],
|
||||
error: [
|
||||
{ name: "error_message", type: "string" },
|
||||
{ name: "error_type", type: "string" },
|
||||
]
|
||||
},
|
||||
'tool': {
|
||||
default: [
|
||||
{ name: "data", type: "string" },
|
||||
],
|
||||
},
|
||||
'jinja-render': {
|
||||
default: [
|
||||
{ name: "output", type: "string" },
|
||||
],
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user