feat: 完善循环节点配置与作用域输出

- 支持次数与数组独立或组合配置并补齐检查规则

- 统一循环体临时变量与下游正式输出候选

- 稳定知识库对象数组字段并补充前后端测试
This commit is contained in:
2026-07-29 18:10:23 +08:00
parent 19c7b60a65
commit 766554bf63
13 changed files with 1737 additions and 62 deletions

View File

@@ -367,6 +367,107 @@ describe('workflow node fields', () => {
expect(contentParameter?.itemTypeLabel).toBe('数组项字段');
});
it('exposes typed loop variables only to nodes inside the loop body', () => {
const knowledgeNode: Node = {
id: 'knowledge_1',
type: 'knowledgeNode',
position: { x: 0, y: 0 },
data: {
title: '知识库',
outputDefs: [
{
name: 'documents',
dataType: 'Array',
children: [
{ name: 'title', dataType: 'String' },
{ name: 'content', dataType: 'String' },
],
},
],
},
};
const loopNode: Node = {
id: 'loop_1',
type: 'loopNode',
position: { x: 120, y: 0 },
data: {
title: '循环',
loopInputs: {
items: {
name: 'items',
refType: 'ref',
ref: 'knowledge_1.documents',
dataType: 'Array',
},
},
outputDefs: [
{
name: 'res',
dataType: 'Array<String>',
},
],
},
};
const insideNode: Node = {
id: 'llm_inside',
type: 'llmNode',
parentId: 'loop_1',
position: { x: 240, y: 0 },
data: { title: '循环内模型', parameters: [] },
};
const outsideNode: Node = {
id: 'llm_outside',
type: 'llmNode',
position: { x: 240, y: 120 },
data: { title: '循环外模型', parameters: [] },
};
const nodes = [
knowledgeNode,
loopNode,
insideNode,
outsideNode,
];
const insideParameters = buildEditorReferenceParameters(
'llm_inside',
nodes,
[],
[],
);
const outsideParameters = buildEditorReferenceParameters(
'llm_outside',
nodes,
[
{
id: 'loop_to_outside',
source: 'loop_1',
target: 'llm_outside',
},
],
[],
);
expect(insideParameters.map((item) => item.name)).toEqual([
'loop_1.index',
'loop_1.loopItem',
'loop_1.loopItem.title',
'loop_1.loopItem.content',
]);
expect(
insideParameters.find(
(item) => item.name === 'loop_1.loopItem.content',
)?.dataType,
).toBe('String');
expect(
outsideParameters.map((item) => item.name),
).toEqual(['loop_1.res']);
expect(
outsideParameters.some((item) =>
['loop_1.index', 'loop_1.loopItem'].includes(item.name || ''),
),
).toBe(false);
});
it('uses document node child outputs for reference display', () => {
const documentNode: Node = {
id: 'doc_1',