feat: Enhance AI Workflow with Variable Contracts and Input Mapping
- Added ConfigSchema, InputSchema, OutputSchema, and DefaultInputs to AIWorkflowNodeSpecResponse. - Implemented BuildAIWorkflowNodeSpecs to include variable contracts for start and send_reply nodes. - Introduced applyAutoInputMappings to automatically map inputs based on node connections. - Enhanced validation to check for required input mappings in workflows. - Updated workflow editor to support variable selection for node inputs. - Translated node names and labels to Chinese for better localization. - Added tests for variable mapping and validation logic.
This commit is contained in:
@@ -50,6 +50,12 @@ func TestAIAgentServiceCreatesDefaultWorkflow(t *testing.T) {
|
||||
if stored.EntryNodeID == "" {
|
||||
t.Fatalf("expected default draft definition")
|
||||
}
|
||||
if len(stored.Nodes) < 5 {
|
||||
t.Fatalf("expected product-ready default workflow, got nodes: %#v", stored.Nodes)
|
||||
}
|
||||
if !workflowHasNodeType(stored, "knowledge_retrieve") || !workflowHasNodeType(stored, "llm_reply") || !workflowHasNodeType(stored, "send_reply") {
|
||||
t.Fatalf("expected default workflow to include retrieve, llm reply, and send reply nodes: %#v", stored.Nodes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAIWorkflowServicePublishAgentWorkflowBindsAgentVersion(t *testing.T) {
|
||||
@@ -169,3 +175,12 @@ func aiAgentWorkflowTestOperator() *dto.AuthPrincipal {
|
||||
Nickname: "agent-workflow-tester",
|
||||
}
|
||||
}
|
||||
|
||||
func workflowHasNodeType(def dsl.Definition, nodeType string) bool {
|
||||
for _, node := range def.Nodes {
|
||||
if node.Type == nodeType {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -337,10 +337,25 @@ func defaultAgentWorkflowDefinition() dsl.Definition {
|
||||
SchemaVersion: 1,
|
||||
EntryNodeID: "start_1",
|
||||
Nodes: []dsl.Node{
|
||||
{ID: "start_1", Type: workflowregistry.NodeTypeStart, Name: "Start", Position: dsl.Position{X: 0, Y: 80}},
|
||||
{ID: "end_1", Type: workflowregistry.NodeTypeEnd, Name: "End", Position: dsl.Position{X: 360, Y: 80}},
|
||||
{ID: "start_1", Type: workflowregistry.NodeTypeStart, Name: "开始", Position: dsl.Position{X: 0, Y: 120}},
|
||||
{ID: "retrieve_1", Type: workflowregistry.NodeTypeKnowledgeRetrieve, Name: "知识检索", Position: dsl.Position{X: 260, Y: 120}, Inputs: map[string]dsl.VariableSelector{
|
||||
"query": {NodeID: "start_1", Field: "userMessage"},
|
||||
}},
|
||||
{ID: "reply_1", Type: workflowregistry.NodeTypeLLMReply, Name: "AI 回复", Position: dsl.Position{X: 520, Y: 120}, Inputs: map[string]dsl.VariableSelector{
|
||||
"userMessage": {NodeID: "start_1", Field: "userMessage"},
|
||||
"knowledgeItems": {NodeID: "retrieve_1", Field: "items"},
|
||||
}},
|
||||
{ID: "send_1", Type: workflowregistry.NodeTypeSendReply, Name: "发送回复", Position: dsl.Position{X: 780, Y: 120}, Inputs: map[string]dsl.VariableSelector{
|
||||
"replyText": {NodeID: "reply_1", Field: "replyText"},
|
||||
}},
|
||||
{ID: "end_1", Type: workflowregistry.NodeTypeEnd, Name: "结束", Position: dsl.Position{X: 1040, Y: 120}},
|
||||
},
|
||||
Edges: []dsl.Edge{
|
||||
{ID: "edge_start_retrieve", Source: "start_1", Target: "retrieve_1"},
|
||||
{ID: "edge_retrieve_reply", Source: "retrieve_1", Target: "reply_1"},
|
||||
{ID: "edge_reply_send", Source: "reply_1", Target: "send_1"},
|
||||
{ID: "edge_send_end", Source: "send_1", Target: "end_1"},
|
||||
},
|
||||
Edges: []dsl.Edge{{ID: "edge_start_end", Source: "start_1", Target: "end_1"}},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -174,7 +174,9 @@ func validAIWorkflowDefinition() dsl.Definition {
|
||||
EntryNodeID: "start_1",
|
||||
Nodes: []dsl.Node{
|
||||
{ID: "start_1", Type: "start"},
|
||||
{ID: "reply_1", Type: "send_reply", Config: json.RawMessage(`{"text":"hello"}`)},
|
||||
{ID: "reply_1", Type: "send_reply", Config: json.RawMessage(`{"text":"hello"}`), Inputs: map[string]dsl.VariableSelector{
|
||||
"replyText": {NodeID: "start_1", Field: "userMessage"},
|
||||
}},
|
||||
{ID: "end_1", Type: "end"},
|
||||
},
|
||||
Edges: []dsl.Edge{
|
||||
|
||||
Reference in New Issue
Block a user