refactor: how to add a node type in workflow (#558)

This commit is contained in:
shentongmartin
2025-08-05 14:02:33 +08:00
committed by GitHub
parent 5dafd81a3f
commit bb6ff0026b
96 changed files with 8305 additions and 8717 deletions

View File

@@ -28,6 +28,9 @@ import (
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity/vo"
compose2 "github.com/coze-dev/coze-studio/backend/domain/workflow/internal/compose"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/batch"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/entry"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/exit"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/schema"
)
func TestBatch(t *testing.T) {
@@ -52,7 +55,7 @@ func TestBatch(t *testing.T) {
return in, nil
}
lambdaNode1 := &compose2.NodeSchema{
lambdaNode1 := &schema.NodeSchema{
Key: "lambda",
Type: entity.NodeTypeLambda,
Lambda: compose.InvokableLambda(lambda1),
@@ -86,7 +89,7 @@ func TestBatch(t *testing.T) {
},
},
}
lambdaNode2 := &compose2.NodeSchema{
lambdaNode2 := &schema.NodeSchema{
Key: "index",
Type: entity.NodeTypeLambda,
Lambda: compose.InvokableLambda(lambda2),
@@ -103,7 +106,7 @@ func TestBatch(t *testing.T) {
},
}
lambdaNode3 := &compose2.NodeSchema{
lambdaNode3 := &schema.NodeSchema{
Key: "consumer",
Type: entity.NodeTypeLambda,
Lambda: compose.InvokableLambda(lambda3),
@@ -135,23 +138,22 @@ func TestBatch(t *testing.T) {
},
}
entry := &compose2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: map[string]any{
"DefaultValues": map[string]any{},
},
entryN := &schema.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: &entry.Config{},
}
ns := &compose2.NodeSchema{
Key: "batch_node_key",
Type: entity.NodeTypeBatch,
ns := &schema.NodeSchema{
Key: "batch_node_key",
Type: entity.NodeTypeBatch,
Configs: &batch.Config{},
InputSources: []*vo.FieldInfo{
{
Path: compose.FieldPath{"array_1"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"array_1"},
},
},
@@ -160,7 +162,7 @@ func TestBatch(t *testing.T) {
Path: compose.FieldPath{"array_2"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"array_2"},
},
},
@@ -214,11 +216,11 @@ func TestBatch(t *testing.T) {
},
}
exit := &compose2.NodeSchema{
exitN := &schema.NodeSchema{
Key: entity.ExitNodeKey,
Type: entity.NodeTypeExit,
Configs: map[string]any{
"TerminalPlan": vo.ReturnVariables,
Configs: &exit.Config{
TerminatePlan: vo.ReturnVariables,
},
InputSources: []*vo.FieldInfo{
{
@@ -246,18 +248,18 @@ func TestBatch(t *testing.T) {
return map[string]any{"success": true}, nil
}
parentLambdaNode := &compose2.NodeSchema{
parentLambdaNode := &schema.NodeSchema{
Key: "parent_predecessor_1",
Type: entity.NodeTypeLambda,
Lambda: compose.InvokableLambda(parentLambda),
}
ws := &compose2.WorkflowSchema{
Nodes: []*compose2.NodeSchema{
entry,
ws := &schema.WorkflowSchema{
Nodes: []*schema.NodeSchema{
entryN,
parentLambdaNode,
ns,
exit,
exitN,
lambdaNode1,
lambdaNode2,
lambdaNode3,
@@ -267,7 +269,7 @@ func TestBatch(t *testing.T) {
"index": "batch_node_key",
"consumer": "batch_node_key",
},
Connections: []*compose2.Connection{
Connections: []*schema.Connection{
{
FromNode: entity.EntryNodeKey,
ToNode: "parent_predecessor_1",

View File

@@ -40,7 +40,11 @@ import (
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity/vo"
compose2 "github.com/coze-dev/coze-studio/backend/domain/workflow/internal/compose"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/emitter"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/entry"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/exit"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/llm"
schema2 "github.com/coze-dev/coze-studio/backend/domain/workflow/internal/schema"
"github.com/coze-dev/coze-studio/backend/infra/contract/modelmgr"
"github.com/coze-dev/coze-studio/backend/internal/testutil"
"github.com/coze-dev/coze-studio/backend/pkg/ctxcache"
@@ -108,22 +112,20 @@ func TestLLM(t *testing.T) {
}
}
entry := &compose2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: map[string]any{
"DefaultValues": map[string]any{},
},
entryN := &schema2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: &entry.Config{},
}
llmNode := &compose2.NodeSchema{
llmNode := &schema2.NodeSchema{
Key: "llm_node_key",
Type: entity.NodeTypeLLM,
Configs: map[string]any{
"SystemPrompt": "{{sys_prompt}}",
"UserPrompt": "{{query}}",
"OutputFormat": llm.FormatText,
"LLMParams": &model.LLMParams{
Configs: &llm.Config{
SystemPrompt: "{{sys_prompt}}",
UserPrompt: "{{query}}",
OutputFormat: llm.FormatText,
LLMParams: &model.LLMParams{
ModelName: modelName,
},
},
@@ -132,7 +134,7 @@ func TestLLM(t *testing.T) {
Path: compose.FieldPath{"sys_prompt"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"sys_prompt"},
},
},
@@ -141,7 +143,7 @@ func TestLLM(t *testing.T) {
Path: compose.FieldPath{"query"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"query"},
},
},
@@ -162,11 +164,11 @@ func TestLLM(t *testing.T) {
},
}
exit := &compose2.NodeSchema{
exitN := &schema2.NodeSchema{
Key: entity.ExitNodeKey,
Type: entity.NodeTypeExit,
Configs: map[string]any{
"TerminalPlan": vo.ReturnVariables,
Configs: &exit.Config{
TerminatePlan: vo.ReturnVariables,
},
InputSources: []*vo.FieldInfo{
{
@@ -181,20 +183,20 @@ func TestLLM(t *testing.T) {
},
}
ws := &compose2.WorkflowSchema{
Nodes: []*compose2.NodeSchema{
entry,
ws := &schema2.WorkflowSchema{
Nodes: []*schema2.NodeSchema{
entryN,
llmNode,
exit,
exitN,
},
Connections: []*compose2.Connection{
Connections: []*schema2.Connection{
{
FromNode: entry.Key,
FromNode: entryN.Key,
ToNode: llmNode.Key,
},
{
FromNode: llmNode.Key,
ToNode: exit.Key,
ToNode: exitN.Key,
},
},
}
@@ -228,27 +230,20 @@ func TestLLM(t *testing.T) {
}
}
entry := &compose2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: map[string]any{
"DefaultValues": map[string]any{},
},
entryN := &schema2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: &entry.Config{},
}
llmNode := &compose2.NodeSchema{
llmNode := &schema2.NodeSchema{
Key: "llm_node_key",
Type: entity.NodeTypeLLM,
Configs: map[string]any{
"SystemPrompt": "you are a helpful assistant",
"UserPrompt": "what's the largest country in the world and it's area size in square kilometers?",
"OutputFormat": llm.FormatJSON,
"IgnoreException": true,
"DefaultOutput": map[string]any{
"country_name": "unknown",
"area_size": int64(0),
},
"LLMParams": &model.LLMParams{
Configs: &llm.Config{
SystemPrompt: "you are a helpful assistant",
UserPrompt: "what's the largest country in the world and it's area size in square kilometers?",
OutputFormat: llm.FormatJSON,
LLMParams: &model.LLMParams{
ModelName: modelName,
},
},
@@ -264,11 +259,11 @@ func TestLLM(t *testing.T) {
},
}
exit := &compose2.NodeSchema{
exitN := &schema2.NodeSchema{
Key: entity.ExitNodeKey,
Type: entity.NodeTypeExit,
Configs: map[string]any{
"TerminalPlan": vo.ReturnVariables,
Configs: &exit.Config{
TerminatePlan: vo.ReturnVariables,
},
InputSources: []*vo.FieldInfo{
{
@@ -292,20 +287,20 @@ func TestLLM(t *testing.T) {
},
}
ws := &compose2.WorkflowSchema{
Nodes: []*compose2.NodeSchema{
entry,
ws := &schema2.WorkflowSchema{
Nodes: []*schema2.NodeSchema{
entryN,
llmNode,
exit,
exitN,
},
Connections: []*compose2.Connection{
Connections: []*schema2.Connection{
{
FromNode: entry.Key,
FromNode: entryN.Key,
ToNode: llmNode.Key,
},
{
FromNode: llmNode.Key,
ToNode: exit.Key,
ToNode: exitN.Key,
},
},
}
@@ -337,22 +332,20 @@ func TestLLM(t *testing.T) {
}
}
entry := &compose2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: map[string]any{
"DefaultValues": map[string]any{},
},
entryN := &schema2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: &entry.Config{},
}
llmNode := &compose2.NodeSchema{
llmNode := &schema2.NodeSchema{
Key: "llm_node_key",
Type: entity.NodeTypeLLM,
Configs: map[string]any{
"SystemPrompt": "you are a helpful assistant",
"UserPrompt": "list the top 5 largest countries in the world",
"OutputFormat": llm.FormatMarkdown,
"LLMParams": &model.LLMParams{
Configs: &llm.Config{
SystemPrompt: "you are a helpful assistant",
UserPrompt: "list the top 5 largest countries in the world",
OutputFormat: llm.FormatMarkdown,
LLMParams: &model.LLMParams{
ModelName: modelName,
},
},
@@ -363,11 +356,11 @@ func TestLLM(t *testing.T) {
},
}
exit := &compose2.NodeSchema{
exitN := &schema2.NodeSchema{
Key: entity.ExitNodeKey,
Type: entity.NodeTypeExit,
Configs: map[string]any{
"TerminalPlan": vo.ReturnVariables,
Configs: &exit.Config{
TerminatePlan: vo.ReturnVariables,
},
InputSources: []*vo.FieldInfo{
{
@@ -382,20 +375,20 @@ func TestLLM(t *testing.T) {
},
}
ws := &compose2.WorkflowSchema{
Nodes: []*compose2.NodeSchema{
entry,
ws := &schema2.WorkflowSchema{
Nodes: []*schema2.NodeSchema{
entryN,
llmNode,
exit,
exitN,
},
Connections: []*compose2.Connection{
Connections: []*schema2.Connection{
{
FromNode: entry.Key,
FromNode: entryN.Key,
ToNode: llmNode.Key,
},
{
FromNode: llmNode.Key,
ToNode: exit.Key,
ToNode: exitN.Key,
},
},
}
@@ -456,22 +449,20 @@ func TestLLM(t *testing.T) {
}
}
entry := &compose2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: map[string]any{
"DefaultValues": map[string]any{},
},
entryN := &schema2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: &entry.Config{},
}
openaiNode := &compose2.NodeSchema{
openaiNode := &schema2.NodeSchema{
Key: "openai_llm_node_key",
Type: entity.NodeTypeLLM,
Configs: map[string]any{
"SystemPrompt": "you are a helpful assistant",
"UserPrompt": "plan a 10 day family visit to China.",
"OutputFormat": llm.FormatText,
"LLMParams": &model.LLMParams{
Configs: &llm.Config{
SystemPrompt: "you are a helpful assistant",
UserPrompt: "plan a 10 day family visit to China.",
OutputFormat: llm.FormatText,
LLMParams: &model.LLMParams{
ModelName: modelName,
},
},
@@ -482,14 +473,14 @@ func TestLLM(t *testing.T) {
},
}
deepseekNode := &compose2.NodeSchema{
deepseekNode := &schema2.NodeSchema{
Key: "deepseek_llm_node_key",
Type: entity.NodeTypeLLM,
Configs: map[string]any{
"SystemPrompt": "you are a helpful assistant",
"UserPrompt": "thoroughly plan a 10 day family visit to China. Use your reasoning ability.",
"OutputFormat": llm.FormatText,
"LLMParams": &model.LLMParams{
Configs: &llm.Config{
SystemPrompt: "you are a helpful assistant",
UserPrompt: "thoroughly plan a 10 day family visit to China. Use your reasoning ability.",
OutputFormat: llm.FormatText,
LLMParams: &model.LLMParams{
ModelName: modelName,
},
},
@@ -503,12 +494,11 @@ func TestLLM(t *testing.T) {
},
}
emitterNode := &compose2.NodeSchema{
emitterNode := &schema2.NodeSchema{
Key: "emitter_node_key",
Type: entity.NodeTypeOutputEmitter,
Configs: map[string]any{
"Template": "prefix {{inputObj.field1}} {{input2}} {{deepseek_reasoning}} \n\n###\n\n {{openai_output}} \n\n###\n\n {{deepseek_output}} {{inputObj.field2}} suffix",
"Mode": nodes.Streaming,
Configs: &emitter.Config{
Template: "prefix {{inputObj.field1}} {{input2}} {{deepseek_reasoning}} \n\n###\n\n {{openai_output}} \n\n###\n\n {{deepseek_output}} {{inputObj.field2}} suffix",
},
InputSources: []*vo.FieldInfo{
{
@@ -542,7 +532,7 @@ func TestLLM(t *testing.T) {
Path: compose.FieldPath{"inputObj"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"inputObj"},
},
},
@@ -551,7 +541,7 @@ func TestLLM(t *testing.T) {
Path: compose.FieldPath{"input2"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"input2"},
},
},
@@ -559,11 +549,11 @@ func TestLLM(t *testing.T) {
},
}
exit := &compose2.NodeSchema{
exitN := &schema2.NodeSchema{
Key: entity.ExitNodeKey,
Type: entity.NodeTypeExit,
Configs: map[string]any{
"TerminalPlan": vo.UseAnswerContent,
Configs: &exit.Config{
TerminatePlan: vo.UseAnswerContent,
},
InputSources: []*vo.FieldInfo{
{
@@ -596,17 +586,17 @@ func TestLLM(t *testing.T) {
},
}
ws := &compose2.WorkflowSchema{
Nodes: []*compose2.NodeSchema{
entry,
ws := &schema2.WorkflowSchema{
Nodes: []*schema2.NodeSchema{
entryN,
openaiNode,
deepseekNode,
emitterNode,
exit,
exitN,
},
Connections: []*compose2.Connection{
Connections: []*schema2.Connection{
{
FromNode: entry.Key,
FromNode: entryN.Key,
ToNode: openaiNode.Key,
},
{
@@ -614,7 +604,7 @@ func TestLLM(t *testing.T) {
ToNode: emitterNode.Key,
},
{
FromNode: entry.Key,
FromNode: entryN.Key,
ToNode: deepseekNode.Key,
},
{
@@ -623,7 +613,7 @@ func TestLLM(t *testing.T) {
},
{
FromNode: emitterNode.Key,
ToNode: exit.Key,
ToNode: exitN.Key,
},
},
}

View File

@@ -26,15 +26,20 @@ import (
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity"
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity/vo"
compose2 "github.com/coze-dev/coze-studio/backend/domain/workflow/internal/compose"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/entry"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/exit"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/loop"
_break "github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/loop/break"
_continue "github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/loop/continue"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/variableassigner"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/schema"
"github.com/coze-dev/coze-studio/backend/pkg/lang/ptr"
)
func TestLoop(t *testing.T) {
t.Run("by iteration", func(t *testing.T) {
// start-> loop_node_key[innerNode->continue] -> end
innerNode := &compose2.NodeSchema{
innerNode := &schema.NodeSchema{
Key: "innerNode",
Type: entity.NodeTypeLambda,
Lambda: compose.InvokableLambda(func(ctx context.Context, in map[string]any) (out map[string]any, err error) {
@@ -54,31 +59,30 @@ func TestLoop(t *testing.T) {
},
}
continueNode := &compose2.NodeSchema{
Key: "continueNode",
Type: entity.NodeTypeContinue,
continueNode := &schema.NodeSchema{
Key: "continueNode",
Type: entity.NodeTypeContinue,
Configs: &_continue.Config{},
}
entry := &compose2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: map[string]any{
"DefaultValues": map[string]any{},
},
entryN := &schema.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: &entry.Config{},
}
loopNode := &compose2.NodeSchema{
loopNode := &schema.NodeSchema{
Key: "loop_node_key",
Type: entity.NodeTypeLoop,
Configs: map[string]any{
"LoopType": loop.ByIteration,
Configs: &loop.Config{
LoopType: loop.ByIteration,
},
InputSources: []*vo.FieldInfo{
{
Path: compose.FieldPath{loop.Count},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"count"},
},
},
@@ -97,11 +101,11 @@ func TestLoop(t *testing.T) {
},
}
exit := &compose2.NodeSchema{
exitN := &schema.NodeSchema{
Key: entity.ExitNodeKey,
Type: entity.NodeTypeExit,
Configs: map[string]any{
"TerminalPlan": vo.ReturnVariables,
Configs: &exit.Config{
TerminatePlan: vo.ReturnVariables,
},
InputSources: []*vo.FieldInfo{
{
@@ -116,11 +120,11 @@ func TestLoop(t *testing.T) {
},
}
ws := &compose2.WorkflowSchema{
Nodes: []*compose2.NodeSchema{
entry,
ws := &schema.WorkflowSchema{
Nodes: []*schema.NodeSchema{
entryN,
loopNode,
exit,
exitN,
innerNode,
continueNode,
},
@@ -128,7 +132,7 @@ func TestLoop(t *testing.T) {
"innerNode": "loop_node_key",
"continueNode": "loop_node_key",
},
Connections: []*compose2.Connection{
Connections: []*schema.Connection{
{
FromNode: "loop_node_key",
ToNode: "innerNode",
@@ -142,12 +146,12 @@ func TestLoop(t *testing.T) {
ToNode: "loop_node_key",
},
{
FromNode: entry.Key,
FromNode: entryN.Key,
ToNode: "loop_node_key",
},
{
FromNode: "loop_node_key",
ToNode: exit.Key,
ToNode: exitN.Key,
},
},
}
@@ -168,7 +172,7 @@ func TestLoop(t *testing.T) {
t.Run("infinite", func(t *testing.T) {
// start-> loop_node_key[innerNode->break] -> end
innerNode := &compose2.NodeSchema{
innerNode := &schema.NodeSchema{
Key: "innerNode",
Type: entity.NodeTypeLambda,
Lambda: compose.InvokableLambda(func(ctx context.Context, in map[string]any) (out map[string]any, err error) {
@@ -188,24 +192,23 @@ func TestLoop(t *testing.T) {
},
}
breakNode := &compose2.NodeSchema{
Key: "breakNode",
Type: entity.NodeTypeBreak,
breakNode := &schema.NodeSchema{
Key: "breakNode",
Type: entity.NodeTypeBreak,
Configs: &_break.Config{},
}
entry := &compose2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: map[string]any{
"DefaultValues": map[string]any{},
},
entryN := &schema.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: &entry.Config{},
}
loopNode := &compose2.NodeSchema{
loopNode := &schema.NodeSchema{
Key: "loop_node_key",
Type: entity.NodeTypeLoop,
Configs: map[string]any{
"LoopType": loop.Infinite,
Configs: &loop.Config{
LoopType: loop.Infinite,
},
OutputSources: []*vo.FieldInfo{
{
@@ -220,11 +223,11 @@ func TestLoop(t *testing.T) {
},
}
exit := &compose2.NodeSchema{
exitN := &schema.NodeSchema{
Key: entity.ExitNodeKey,
Type: entity.NodeTypeExit,
Configs: map[string]any{
"TerminalPlan": vo.ReturnVariables,
Configs: &exit.Config{
TerminatePlan: vo.ReturnVariables,
},
InputSources: []*vo.FieldInfo{
{
@@ -239,11 +242,11 @@ func TestLoop(t *testing.T) {
},
}
ws := &compose2.WorkflowSchema{
Nodes: []*compose2.NodeSchema{
entry,
ws := &schema.WorkflowSchema{
Nodes: []*schema.NodeSchema{
entryN,
loopNode,
exit,
exitN,
innerNode,
breakNode,
},
@@ -251,7 +254,7 @@ func TestLoop(t *testing.T) {
"innerNode": "loop_node_key",
"breakNode": "loop_node_key",
},
Connections: []*compose2.Connection{
Connections: []*schema.Connection{
{
FromNode: "loop_node_key",
ToNode: "innerNode",
@@ -265,12 +268,12 @@ func TestLoop(t *testing.T) {
ToNode: "loop_node_key",
},
{
FromNode: entry.Key,
FromNode: entryN.Key,
ToNode: "loop_node_key",
},
{
FromNode: "loop_node_key",
ToNode: exit.Key,
ToNode: exitN.Key,
},
},
}
@@ -290,14 +293,14 @@ func TestLoop(t *testing.T) {
t.Run("by array", func(t *testing.T) {
// start-> loop_node_key[innerNode->variable_assign] -> end
innerNode := &compose2.NodeSchema{
innerNode := &schema.NodeSchema{
Key: "innerNode",
Type: entity.NodeTypeLambda,
Lambda: compose.InvokableLambda(func(ctx context.Context, in map[string]any) (out map[string]any, err error) {
item1 := in["item1"].(string)
item2 := in["item2"].(string)
count := in["count"].(int)
return map[string]any{"total": int(count) + len(item1) + len(item2)}, nil
return map[string]any{"total": count + len(item1) + len(item2)}, nil
}),
InputSources: []*vo.FieldInfo{
{
@@ -330,16 +333,18 @@ func TestLoop(t *testing.T) {
},
}
assigner := &compose2.NodeSchema{
assigner := &schema.NodeSchema{
Key: "assigner",
Type: entity.NodeTypeVariableAssignerWithinLoop,
Configs: []*variableassigner.Pair{
{
Left: vo.Reference{
FromPath: compose.FieldPath{"count"},
VariableType: ptr.Of(vo.ParentIntermediate),
Configs: &variableassigner.InLoopConfig{
Pairs: []*variableassigner.Pair{
{
Left: vo.Reference{
FromPath: compose.FieldPath{"count"},
VariableType: ptr.Of(vo.ParentIntermediate),
},
Right: compose.FieldPath{"total"},
},
Right: compose.FieldPath{"total"},
},
},
InputSources: []*vo.FieldInfo{
@@ -355,19 +360,17 @@ func TestLoop(t *testing.T) {
},
}
entry := &compose2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: map[string]any{
"DefaultValues": map[string]any{},
},
entryN := &schema.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: &entry.Config{},
}
exit := &compose2.NodeSchema{
exitN := &schema.NodeSchema{
Key: entity.ExitNodeKey,
Type: entity.NodeTypeExit,
Configs: map[string]any{
"TerminalPlan": vo.ReturnVariables,
Configs: &exit.Config{
TerminatePlan: vo.ReturnVariables,
},
InputSources: []*vo.FieldInfo{
{
@@ -382,12 +385,13 @@ func TestLoop(t *testing.T) {
},
}
loopNode := &compose2.NodeSchema{
loopNode := &schema.NodeSchema{
Key: "loop_node_key",
Type: entity.NodeTypeLoop,
Configs: map[string]any{
"LoopType": loop.ByArray,
"IntermediateVars": map[string]*vo.TypeInfo{
Configs: &loop.Config{
LoopType: loop.ByArray,
InputArrays: []string{"items1", "items2"},
IntermediateVars: map[string]*vo.TypeInfo{
"count": {
Type: vo.DataTypeInteger,
},
@@ -408,7 +412,7 @@ func TestLoop(t *testing.T) {
Path: compose.FieldPath{"items1"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"items1"},
},
},
@@ -417,7 +421,7 @@ func TestLoop(t *testing.T) {
Path: compose.FieldPath{"items2"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"items2"},
},
},
@@ -442,11 +446,11 @@ func TestLoop(t *testing.T) {
},
}
ws := &compose2.WorkflowSchema{
Nodes: []*compose2.NodeSchema{
entry,
ws := &schema.WorkflowSchema{
Nodes: []*schema.NodeSchema{
entryN,
loopNode,
exit,
exitN,
innerNode,
assigner,
},
@@ -454,7 +458,7 @@ func TestLoop(t *testing.T) {
"innerNode": "loop_node_key",
"assigner": "loop_node_key",
},
Connections: []*compose2.Connection{
Connections: []*schema.Connection{
{
FromNode: "loop_node_key",
ToNode: "innerNode",
@@ -468,12 +472,12 @@ func TestLoop(t *testing.T) {
ToNode: "loop_node_key",
},
{
FromNode: entry.Key,
FromNode: entryN.Key,
ToNode: "loop_node_key",
},
{
FromNode: "loop_node_key",
ToNode: exit.Key,
ToNode: exitN.Key,
},
},
}

View File

@@ -43,8 +43,11 @@ import (
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity"
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity/vo"
compose2 "github.com/coze-dev/coze-studio/backend/domain/workflow/internal/compose"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/entry"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/exit"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/qa"
repo2 "github.com/coze-dev/coze-studio/backend/domain/workflow/internal/repo"
schema2 "github.com/coze-dev/coze-studio/backend/domain/workflow/internal/schema"
"github.com/coze-dev/coze-studio/backend/infra/impl/checkpoint"
mock "github.com/coze-dev/coze-studio/backend/internal/mock/infra/contract/idgen"
storageMock "github.com/coze-dev/coze-studio/backend/internal/mock/infra/contract/storage"
@@ -106,26 +109,25 @@ func TestQuestionAnswer(t *testing.T) {
mockey.Mock(workflow.GetRepository).Return(repo).Build()
t.Run("answer directly, no structured output", func(t *testing.T) {
entry := &compose2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: map[string]any{
"DefaultValues": map[string]any{},
}}
entryN := &schema2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: &entry.Config{},
}
ns := &compose2.NodeSchema{
ns := &schema2.NodeSchema{
Key: "qa_node_key",
Type: entity.NodeTypeQuestionAnswer,
Configs: map[string]any{
"QuestionTpl": "{{input}}",
"AnswerType": qa.AnswerDirectly,
Configs: &qa.Config{
QuestionTpl: "{{input}}",
AnswerType: qa.AnswerDirectly,
},
InputSources: []*vo.FieldInfo{
{
Path: compose.FieldPath{"input"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"query"},
},
},
@@ -133,11 +135,11 @@ func TestQuestionAnswer(t *testing.T) {
},
}
exit := &compose2.NodeSchema{
exitN := &schema2.NodeSchema{
Key: entity.ExitNodeKey,
Type: entity.NodeTypeExit,
Configs: map[string]any{
"TerminalPlan": vo.ReturnVariables,
Configs: &exit.Config{
TerminatePlan: vo.ReturnVariables,
},
InputSources: []*vo.FieldInfo{
{
@@ -152,20 +154,20 @@ func TestQuestionAnswer(t *testing.T) {
},
}
ws := &compose2.WorkflowSchema{
Nodes: []*compose2.NodeSchema{
entry,
ws := &schema2.WorkflowSchema{
Nodes: []*schema2.NodeSchema{
entryN,
ns,
exit,
exitN,
},
Connections: []*compose2.Connection{
Connections: []*schema2.Connection{
{
FromNode: entry.Key,
FromNode: entryN.Key,
ToNode: "qa_node_key",
},
{
FromNode: "qa_node_key",
ToNode: exit.Key,
ToNode: exitN.Key,
},
},
}
@@ -210,30 +212,28 @@ func TestQuestionAnswer(t *testing.T) {
mockModelManager.EXPECT().GetModel(gomock.Any(), gomock.Any()).Return(oneChatModel, nil, nil).Times(1)
}
entry := &compose2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: map[string]any{
"DefaultValues": map[string]any{},
},
entryN := &schema2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: &entry.Config{},
}
ns := &compose2.NodeSchema{
ns := &schema2.NodeSchema{
Key: "qa_node_key",
Type: entity.NodeTypeQuestionAnswer,
Configs: map[string]any{
"QuestionTpl": "{{input}}",
"AnswerType": qa.AnswerByChoices,
"ChoiceType": qa.FixedChoices,
"FixedChoices": []string{"{{choice1}}", "{{choice2}}"},
"LLMParams": &model.LLMParams{},
Configs: &qa.Config{
QuestionTpl: "{{input}}",
AnswerType: qa.AnswerByChoices,
ChoiceType: qa.FixedChoices,
FixedChoices: []string{"{{choice1}}", "{{choice2}}"},
LLMParams: &model.LLMParams{},
},
InputSources: []*vo.FieldInfo{
{
Path: compose.FieldPath{"input"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"query"},
},
},
@@ -242,7 +242,7 @@ func TestQuestionAnswer(t *testing.T) {
Path: compose.FieldPath{"choice1"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"choice1"},
},
},
@@ -251,7 +251,7 @@ func TestQuestionAnswer(t *testing.T) {
Path: compose.FieldPath{"choice2"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"choice2"},
},
},
@@ -259,11 +259,11 @@ func TestQuestionAnswer(t *testing.T) {
},
}
exit := &compose2.NodeSchema{
exitN := &schema2.NodeSchema{
Key: entity.ExitNodeKey,
Type: entity.NodeTypeExit,
Configs: map[string]any{
"TerminalPlan": vo.ReturnVariables,
Configs: &exit.Config{
TerminatePlan: vo.ReturnVariables,
},
InputSources: []*vo.FieldInfo{
{
@@ -287,7 +287,7 @@ func TestQuestionAnswer(t *testing.T) {
},
}
lambda := &compose2.NodeSchema{
lambda := &schema2.NodeSchema{
Key: "lambda",
Type: entity.NodeTypeLambda,
Lambda: compose.InvokableLambda(func(ctx context.Context, in map[string]any) (out map[string]any, err error) {
@@ -295,26 +295,26 @@ func TestQuestionAnswer(t *testing.T) {
}),
}
ws := &compose2.WorkflowSchema{
Nodes: []*compose2.NodeSchema{
entry,
ws := &schema2.WorkflowSchema{
Nodes: []*schema2.NodeSchema{
entryN,
ns,
exit,
exitN,
lambda,
},
Connections: []*compose2.Connection{
Connections: []*schema2.Connection{
{
FromNode: entry.Key,
FromNode: entryN.Key,
ToNode: "qa_node_key",
},
{
FromNode: "qa_node_key",
ToNode: exit.Key,
ToNode: exitN.Key,
FromPort: ptr.Of("branch_0"),
},
{
FromNode: "qa_node_key",
ToNode: exit.Key,
ToNode: exitN.Key,
FromPort: ptr.Of("branch_1"),
},
{
@@ -324,11 +324,15 @@ func TestQuestionAnswer(t *testing.T) {
},
{
FromNode: "lambda",
ToNode: exit.Key,
ToNode: exitN.Key,
},
},
}
branches, err := schema2.BuildBranches(ws.Connections)
assert.NoError(t, err)
ws.Branches = branches
ws.Init()
wf, err := compose2.NewWorkflow(context.Background(), ws)
@@ -362,28 +366,26 @@ func TestQuestionAnswer(t *testing.T) {
})
t.Run("answer with dynamic choices", func(t *testing.T) {
entry := &compose2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: map[string]any{
"DefaultValues": map[string]any{},
},
entryN := &schema2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: &entry.Config{},
}
ns := &compose2.NodeSchema{
ns := &schema2.NodeSchema{
Key: "qa_node_key",
Type: entity.NodeTypeQuestionAnswer,
Configs: map[string]any{
"QuestionTpl": "{{input}}",
"AnswerType": qa.AnswerByChoices,
"ChoiceType": qa.DynamicChoices,
Configs: &qa.Config{
QuestionTpl: "{{input}}",
AnswerType: qa.AnswerByChoices,
ChoiceType: qa.DynamicChoices,
},
InputSources: []*vo.FieldInfo{
{
Path: compose.FieldPath{"input"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"query"},
},
},
@@ -392,7 +394,7 @@ func TestQuestionAnswer(t *testing.T) {
Path: compose.FieldPath{qa.DynamicChoicesKey},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"choices"},
},
},
@@ -400,11 +402,11 @@ func TestQuestionAnswer(t *testing.T) {
},
}
exit := &compose2.NodeSchema{
exitN := &schema2.NodeSchema{
Key: entity.ExitNodeKey,
Type: entity.NodeTypeExit,
Configs: map[string]any{
"TerminalPlan": vo.ReturnVariables,
Configs: &exit.Config{
TerminatePlan: vo.ReturnVariables,
},
InputSources: []*vo.FieldInfo{
{
@@ -428,7 +430,7 @@ func TestQuestionAnswer(t *testing.T) {
},
}
lambda := &compose2.NodeSchema{
lambda := &schema2.NodeSchema{
Key: "lambda",
Type: entity.NodeTypeLambda,
Lambda: compose.InvokableLambda(func(ctx context.Context, in map[string]any) (out map[string]any, err error) {
@@ -436,26 +438,26 @@ func TestQuestionAnswer(t *testing.T) {
}),
}
ws := &compose2.WorkflowSchema{
Nodes: []*compose2.NodeSchema{
entry,
ws := &schema2.WorkflowSchema{
Nodes: []*schema2.NodeSchema{
entryN,
ns,
exit,
exitN,
lambda,
},
Connections: []*compose2.Connection{
Connections: []*schema2.Connection{
{
FromNode: entry.Key,
FromNode: entryN.Key,
ToNode: "qa_node_key",
},
{
FromNode: "qa_node_key",
ToNode: exit.Key,
ToNode: exitN.Key,
FromPort: ptr.Of("branch_0"),
},
{
FromNode: "lambda",
ToNode: exit.Key,
ToNode: exitN.Key,
},
{
FromNode: "qa_node_key",
@@ -465,6 +467,10 @@ func TestQuestionAnswer(t *testing.T) {
},
}
branches, err := schema2.BuildBranches(ws.Connections)
assert.NoError(t, err)
ws.Branches = branches
ws.Init()
wf, err := compose2.NewWorkflow(context.Background(), ws)
@@ -522,31 +528,29 @@ func TestQuestionAnswer(t *testing.T) {
mockModelManager.EXPECT().GetModel(gomock.Any(), gomock.Any()).Return(chatModel, nil, nil).Times(1)
}
entry := &compose2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: map[string]any{
"DefaultValues": map[string]any{},
},
entryN := &schema2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: &entry.Config{},
}
ns := &compose2.NodeSchema{
ns := &schema2.NodeSchema{
Key: "qa_node_key",
Type: entity.NodeTypeQuestionAnswer,
Configs: map[string]any{
"QuestionTpl": "{{input}}",
"AnswerType": qa.AnswerDirectly,
"ExtractFromAnswer": true,
"AdditionalSystemPromptTpl": "{{prompt}}",
"MaxAnswerCount": 2,
"LLMParams": &model.LLMParams{},
Configs: &qa.Config{
QuestionTpl: "{{input}}",
AnswerType: qa.AnswerDirectly,
ExtractFromAnswer: true,
AdditionalSystemPromptTpl: "{{prompt}}",
MaxAnswerCount: 2,
LLMParams: &model.LLMParams{},
},
InputSources: []*vo.FieldInfo{
{
Path: compose.FieldPath{"input"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"query"},
},
},
@@ -555,7 +559,7 @@ func TestQuestionAnswer(t *testing.T) {
Path: compose.FieldPath{"prompt"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"prompt"},
},
},
@@ -573,11 +577,11 @@ func TestQuestionAnswer(t *testing.T) {
},
}
exit := &compose2.NodeSchema{
exitN := &schema2.NodeSchema{
Key: entity.ExitNodeKey,
Type: entity.NodeTypeExit,
Configs: map[string]any{
"TerminalPlan": vo.ReturnVariables,
Configs: &exit.Config{
TerminatePlan: vo.ReturnVariables,
},
InputSources: []*vo.FieldInfo{
{
@@ -610,20 +614,20 @@ func TestQuestionAnswer(t *testing.T) {
},
}
ws := &compose2.WorkflowSchema{
Nodes: []*compose2.NodeSchema{
entry,
ws := &schema2.WorkflowSchema{
Nodes: []*schema2.NodeSchema{
entryN,
ns,
exit,
exitN,
},
Connections: []*compose2.Connection{
Connections: []*schema2.Connection{
{
FromNode: entry.Key,
FromNode: entryN.Key,
ToNode: "qa_node_key",
},
{
FromNode: "qa_node_key",
ToNode: exit.Key,
ToNode: exitN.Key,
},
},
}

View File

@@ -26,26 +26,28 @@ import (
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity"
"github.com/coze-dev/coze-studio/backend/domain/workflow/entity/vo"
compose2 "github.com/coze-dev/coze-studio/backend/domain/workflow/internal/compose"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/entry"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/exit"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/selector"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/textprocessor"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/nodes/variableaggregator"
"github.com/coze-dev/coze-studio/backend/domain/workflow/internal/schema"
"github.com/coze-dev/coze-studio/backend/pkg/lang/ptr"
)
func TestAddSelector(t *testing.T) {
// start -> selector, selector.condition1 -> lambda1 -> end, selector.condition2 -> [lambda2, lambda3] -> end, selector default -> end
entry := &compose2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: map[string]any{
"DefaultValues": map[string]any{},
}}
entryN := &schema.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: &entry.Config{},
}
exit := &compose2.NodeSchema{
exitN := &schema.NodeSchema{
Key: entity.ExitNodeKey,
Type: entity.NodeTypeExit,
Configs: map[string]any{
"TerminalPlan": vo.ReturnVariables,
Configs: &exit.Config{
TerminatePlan: vo.ReturnVariables,
},
InputSources: []*vo.FieldInfo{
{
@@ -84,7 +86,7 @@ func TestAddSelector(t *testing.T) {
}, nil
}
lambdaNode1 := &compose2.NodeSchema{
lambdaNode1 := &schema.NodeSchema{
Key: "lambda1",
Type: entity.NodeTypeLambda,
Lambda: compose.InvokableLambda(lambda1),
@@ -96,7 +98,7 @@ func TestAddSelector(t *testing.T) {
}, nil
}
LambdaNode2 := &compose2.NodeSchema{
LambdaNode2 := &schema.NodeSchema{
Key: "lambda2",
Type: entity.NodeTypeLambda,
Lambda: compose.InvokableLambda(lambda2),
@@ -108,16 +110,16 @@ func TestAddSelector(t *testing.T) {
}, nil
}
lambdaNode3 := &compose2.NodeSchema{
lambdaNode3 := &schema.NodeSchema{
Key: "lambda3",
Type: entity.NodeTypeLambda,
Lambda: compose.InvokableLambda(lambda3),
}
ns := &compose2.NodeSchema{
ns := &schema.NodeSchema{
Key: "selector",
Type: entity.NodeTypeSelector,
Configs: map[string]any{"Clauses": []*selector.OneClauseSchema{
Configs: &selector.Config{Clauses: []*selector.OneClauseSchema{
{
Single: ptr.Of(selector.OperatorEqual),
},
@@ -136,7 +138,7 @@ func TestAddSelector(t *testing.T) {
Path: compose.FieldPath{"0", selector.LeftKey},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"key1"},
},
},
@@ -151,7 +153,7 @@ func TestAddSelector(t *testing.T) {
Path: compose.FieldPath{"1", "0", selector.LeftKey},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"key2"},
},
},
@@ -160,7 +162,7 @@ func TestAddSelector(t *testing.T) {
Path: compose.FieldPath{"1", "0", selector.RightKey},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"key3"},
},
},
@@ -169,7 +171,7 @@ func TestAddSelector(t *testing.T) {
Path: compose.FieldPath{"1", "1", selector.LeftKey},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"key4"},
},
},
@@ -214,18 +216,18 @@ func TestAddSelector(t *testing.T) {
},
}
ws := &compose2.WorkflowSchema{
Nodes: []*compose2.NodeSchema{
entry,
ws := &schema.WorkflowSchema{
Nodes: []*schema.NodeSchema{
entryN,
ns,
lambdaNode1,
LambdaNode2,
lambdaNode3,
exit,
exitN,
},
Connections: []*compose2.Connection{
Connections: []*schema.Connection{
{
FromNode: entry.Key,
FromNode: entryN.Key,
ToNode: "selector",
},
{
@@ -245,24 +247,28 @@ func TestAddSelector(t *testing.T) {
},
{
FromNode: "selector",
ToNode: exit.Key,
ToNode: exitN.Key,
FromPort: ptr.Of("default"),
},
{
FromNode: "lambda1",
ToNode: exit.Key,
ToNode: exitN.Key,
},
{
FromNode: "lambda2",
ToNode: exit.Key,
ToNode: exitN.Key,
},
{
FromNode: "lambda3",
ToNode: exit.Key,
ToNode: exitN.Key,
},
},
}
branches, err := schema.BuildBranches(ws.Connections)
assert.NoError(t, err)
ws.Branches = branches
ws.Init()
ctx := context.Background()
@@ -303,19 +309,17 @@ func TestAddSelector(t *testing.T) {
}
func TestVariableAggregator(t *testing.T) {
entry := &compose2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: map[string]any{
"DefaultValues": map[string]any{},
},
entryN := &schema.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: &entry.Config{},
}
exit := &compose2.NodeSchema{
exitN := &schema.NodeSchema{
Key: entity.ExitNodeKey,
Type: entity.NodeTypeExit,
Configs: map[string]any{
"TerminalPlan": vo.ReturnVariables,
Configs: &exit.Config{
TerminatePlan: vo.ReturnVariables,
},
InputSources: []*vo.FieldInfo{
{
@@ -339,16 +343,16 @@ func TestVariableAggregator(t *testing.T) {
},
}
ns := &compose2.NodeSchema{
ns := &schema.NodeSchema{
Key: "va",
Type: entity.NodeTypeVariableAggregator,
Configs: map[string]any{
"MergeStrategy": variableaggregator.FirstNotNullValue,
"GroupToLen": map[string]int{
Configs: &variableaggregator.Config{
MergeStrategy: variableaggregator.FirstNotNullValue,
GroupLen: map[string]int{
"Group1": 1,
"Group2": 1,
},
"GroupOrder": []string{
GroupOrder: []string{
"Group1",
"Group2",
},
@@ -358,7 +362,7 @@ func TestVariableAggregator(t *testing.T) {
Path: compose.FieldPath{"Group1", "0"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"Str1"},
},
},
@@ -367,7 +371,7 @@ func TestVariableAggregator(t *testing.T) {
Path: compose.FieldPath{"Group2", "0"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"Int1"},
},
},
@@ -401,20 +405,20 @@ func TestVariableAggregator(t *testing.T) {
},
}
ws := &compose2.WorkflowSchema{
Nodes: []*compose2.NodeSchema{
entry,
ws := &schema.WorkflowSchema{
Nodes: []*schema.NodeSchema{
entryN,
ns,
exit,
exitN,
},
Connections: []*compose2.Connection{
Connections: []*schema.Connection{
{
FromNode: entry.Key,
FromNode: entryN.Key,
ToNode: "va",
},
{
FromNode: "va",
ToNode: exit.Key,
ToNode: exitN.Key,
},
},
}
@@ -448,19 +452,17 @@ func TestVariableAggregator(t *testing.T) {
func TestTextProcessor(t *testing.T) {
t.Run("split", func(t *testing.T) {
entry := &compose2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: map[string]any{
"DefaultValues": map[string]any{},
},
entryN := &schema.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: &entry.Config{},
}
exit := &compose2.NodeSchema{
exitN := &schema.NodeSchema{
Key: entity.ExitNodeKey,
Type: entity.NodeTypeExit,
Configs: map[string]any{
"TerminalPlan": vo.ReturnVariables,
Configs: &exit.Config{
TerminatePlan: vo.ReturnVariables,
},
InputSources: []*vo.FieldInfo{
{
@@ -475,19 +477,19 @@ func TestTextProcessor(t *testing.T) {
},
}
ns := &compose2.NodeSchema{
ns := &schema.NodeSchema{
Key: "tp",
Type: entity.NodeTypeTextProcessor,
Configs: map[string]any{
"Type": textprocessor.SplitText,
"Separators": []string{"|"},
Configs: &textprocessor.Config{
Type: textprocessor.SplitText,
Separators: []string{"|"},
},
InputSources: []*vo.FieldInfo{
{
Path: compose.FieldPath{"String"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"Str"},
},
},
@@ -495,20 +497,20 @@ func TestTextProcessor(t *testing.T) {
},
}
ws := &compose2.WorkflowSchema{
Nodes: []*compose2.NodeSchema{
ws := &schema.WorkflowSchema{
Nodes: []*schema.NodeSchema{
ns,
entry,
exit,
entryN,
exitN,
},
Connections: []*compose2.Connection{
Connections: []*schema.Connection{
{
FromNode: entry.Key,
FromNode: entryN.Key,
ToNode: "tp",
},
{
FromNode: "tp",
ToNode: exit.Key,
ToNode: exitN.Key,
},
},
}
@@ -527,19 +529,17 @@ func TestTextProcessor(t *testing.T) {
})
t.Run("concat", func(t *testing.T) {
entry := &compose2.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: map[string]any{
"DefaultValues": map[string]any{},
},
entryN := &schema.NodeSchema{
Key: entity.EntryNodeKey,
Type: entity.NodeTypeEntry,
Configs: &entry.Config{},
}
exit := &compose2.NodeSchema{
exitN := &schema.NodeSchema{
Key: entity.ExitNodeKey,
Type: entity.NodeTypeExit,
Configs: map[string]any{
"TerminalPlan": vo.ReturnVariables,
Configs: &exit.Config{
TerminatePlan: vo.ReturnVariables,
},
InputSources: []*vo.FieldInfo{
{
@@ -554,20 +554,20 @@ func TestTextProcessor(t *testing.T) {
},
}
ns := &compose2.NodeSchema{
ns := &schema.NodeSchema{
Key: "tp",
Type: entity.NodeTypeTextProcessor,
Configs: map[string]any{
"Type": textprocessor.ConcatText,
"Tpl": "{{String1}}_{{String2.f1}}_{{String3.f2[1]}}",
"ConcatChar": "\t",
Configs: &textprocessor.Config{
Type: textprocessor.ConcatText,
Tpl: "{{String1}}_{{String2.f1}}_{{String3.f2[1]}}",
ConcatChar: "\t",
},
InputSources: []*vo.FieldInfo{
{
Path: compose.FieldPath{"String1"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"Str1"},
},
},
@@ -576,7 +576,7 @@ func TestTextProcessor(t *testing.T) {
Path: compose.FieldPath{"String2"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"Str2"},
},
},
@@ -585,7 +585,7 @@ func TestTextProcessor(t *testing.T) {
Path: compose.FieldPath{"String3"},
Source: vo.FieldSource{
Ref: &vo.Reference{
FromNodeKey: entry.Key,
FromNodeKey: entryN.Key,
FromPath: compose.FieldPath{"Str3"},
},
},
@@ -593,20 +593,20 @@ func TestTextProcessor(t *testing.T) {
},
}
ws := &compose2.WorkflowSchema{
Nodes: []*compose2.NodeSchema{
ws := &schema.WorkflowSchema{
Nodes: []*schema.NodeSchema{
ns,
entry,
exit,
entryN,
exitN,
},
Connections: []*compose2.Connection{
Connections: []*schema.Connection{
{
FromNode: entry.Key,
FromNode: entryN.Key,
ToNode: "tp",
},
{
FromNode: "tp",
ToNode: exit.Key,
ToNode: exitN.Key,
},
},
}