Implement handoff to human functionality in workflow executor and update registry output schema

This commit is contained in:
mlogclub
2026-06-23 21:48:20 +08:00
parent ec9e4a852a
commit 8992f263aa
3 changed files with 247 additions and 10 deletions
+31 -10
View File
@@ -14,6 +14,7 @@ import (
workflowregistry "agent-desk/internal/ai/workflow/registry"
"agent-desk/internal/models"
"agent-desk/internal/pkg/utils"
"agent-desk/internal/services"
)
const maxWorkflowSteps = 128
@@ -133,16 +134,7 @@ func (e *Executor) executeNode(ctx context.Context, state *runState, node dsl.No
"replyMessageId": int64(0),
})
case workflowregistry.NodeTypeHandoffToHuman:
reason := strings.TrimSpace(toString(state.resolveInput(node, "reason")))
replyText := strings.TrimSpace(readStringConfig(node.Config, "replyText"))
if replyText == "" {
replyText = "已为你转接人工客服,请稍候。"
}
state.result.ReplyText = replyText
state.setNodeVars(node.ID, map[string]any{
"handoffId": int64(0),
"reason": reason,
})
return e.executeHandoffToHuman(state, node)
case workflowregistry.NodeTypeEnd:
state.setNodeVars(node.ID, map[string]any{"status": "completed"})
default:
@@ -151,6 +143,35 @@ func (e *Executor) executeNode(ctx context.Context, state *runState, node dsl.No
return nil
}
func (e *Executor) executeHandoffToHuman(state *runState, node dsl.Node) error {
reason := strings.TrimSpace(toString(state.resolveInput(node, "reason")))
result, err := services.ConversationHumanDispatchService.HandoffByAIWithRequestID(
state.input.Conversation.ID,
state.input.AIAgent,
reason,
strings.TrimSpace(state.input.UserMessage.RequestID),
)
if err != nil {
return err
}
output := map[string]any{
"handoffId": int64(0),
"reason": reason,
"decision": "",
"teamId": int64(0),
"assigneeId": int64(0),
"message": "",
}
if result != nil {
output["decision"] = string(result.Decision)
output["teamId"] = result.TeamID
output["assigneeId"] = result.AssigneeID
output["message"] = strings.TrimSpace(result.Message)
}
state.setNodeVars(node.ID, output)
return nil
}
func (e *Executor) executeKnowledgeRetrieve(ctx context.Context, state *runState, node dsl.Node) error {
query := strings.TrimSpace(toString(state.resolveInput(node, "query")))
retriever := retrievers.NewKnowledgeRetriever(state.input.AIAgent)