From 1766eadcf10b16ae3a5320b967977857d538dc66 Mon Sep 17 00:00:00 2001 From: mlogclub Date: Tue, 14 Apr 2026 18:27:45 +0800 Subject: [PATCH] feat: implement buildResumeTargets function and update resume handling logic --- cmd/testdata/skill/init.go | 5 --- internal/ai/runtime/executor/run_options.go | 18 ++++++++++ .../ai/runtime/executor/run_options_test.go | 34 +++++++++++++++++++ internal/ai/runtime/executor/service.go | 13 ++++++- .../tools/analyze_conversation_tool.go | 2 +- .../ai/runtime/tools/handoff_graph_tool.go | 2 +- 6 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 internal/ai/runtime/executor/run_options_test.go diff --git a/cmd/testdata/skill/init.go b/cmd/testdata/skill/init.go index 69def60..65fcd23 100644 --- a/cmd/testdata/skill/init.go +++ b/cmd/testdata/skill/init.go @@ -69,17 +69,12 @@ func buildSeedItems() []models.SkillDefinition { 2. 优先围绕问题定位和升级处理推进,不要输出与当前诉求无关的自我介绍。 3. 如果进入确认流程,明确告知用户你将协助提交或转接,并等待确认结果。`, Examples: `[ - "设备今天开始一直离线,重启也没用,帮我提个工单", "这个问题三天了还没解决,我要投诉一下", "麻烦转人工,你这边解决不了", "售后什么时候联系我?这个故障还没有人跟进", - "帮我登记一下报障,产品型号是AX300,无法联网", "我要申请售后处理,这个问题反复出现", - "你好,你是谁", - "这个产品怎么安装" ]`, ToolWhitelist: `[ - "graph/prepare_ticket_draft", "graph/create_ticket_with_confirmation", "graph/handoff_to_human" ]`, diff --git a/internal/ai/runtime/executor/run_options.go b/internal/ai/runtime/executor/run_options.go index 76d84ab..7f5e2bb 100644 --- a/internal/ai/runtime/executor/run_options.go +++ b/internal/ai/runtime/executor/run_options.go @@ -28,6 +28,24 @@ func buildResumeDataMessage(resumeData map[string]string) *schema.Message { return schema.UserMessage(string(data)) } +func buildResumeTargets(resumeData map[string]string) map[string]any { + if len(resumeData) == 0 { + return nil + } + targets := make(map[string]any, len(resumeData)) + for key, value := range resumeData { + key = strings.TrimSpace(key) + if key == "" { + continue + } + targets[key] = value + } + if len(targets) == 0 { + return nil + } + return targets +} + func buildRunOptions(checkPointID string) []adk.AgentRunOption { options := make([]adk.AgentRunOption, 0, 1) if strings.TrimSpace(checkPointID) != "" { diff --git a/internal/ai/runtime/executor/run_options_test.go b/internal/ai/runtime/executor/run_options_test.go new file mode 100644 index 0000000..32bea0a --- /dev/null +++ b/internal/ai/runtime/executor/run_options_test.go @@ -0,0 +1,34 @@ +package executor + +import "testing" + +func TestBuildResumeTargets(t *testing.T) { + targets := buildResumeTargets(map[string]string{ + " interrupt-1 ": "确认", + "": "ignored", + " ": "ignored", + "interrupt-2": "取消", + }) + + if len(targets) != 2 { + t.Fatalf("expected 2 resume targets, got %d", len(targets)) + } + if got := targets["interrupt-1"]; got != "确认" { + t.Fatalf("unexpected target data for interrupt-1: %#v", got) + } + if got := targets["interrupt-2"]; got != "取消" { + t.Fatalf("unexpected target data for interrupt-2: %#v", got) + } +} + +func TestBuildResumeTargetsEmpty(t *testing.T) { + if got := buildResumeTargets(nil); got != nil { + t.Fatalf("expected nil targets for nil input, got %#v", got) + } + if got := buildResumeTargets(map[string]string{ + "": "ignored", + " ": "ignored", + }); got != nil { + t.Fatalf("expected nil targets for blank keys, got %#v", got) + } +} diff --git a/internal/ai/runtime/executor/service.go b/internal/ai/runtime/executor/service.go index 73c689f..265d064 100644 --- a/internal/ai/runtime/executor/service.go +++ b/internal/ai/runtime/executor/service.go @@ -8,6 +8,7 @@ import ( "cs-agent/internal/ai/runtime/internal/impl/callbacks" "cs-agent/internal/ai/runtime/internal/impl/factory" + "github.com/cloudwego/eino/adk" "github.com/google/uuid" ) @@ -213,7 +214,17 @@ func (s *Service) ExecuteResume(ctx context.Context, req ResumeInput) (*RunResul return summary, fmt.Errorf("%s", summary.ErrorMessage) } resumeData := buildResumeDataMessage(req.ResumeData) - iter, err := runner.Resume(ctx, summary.CheckPointID, buildResumeOptions(summary.CheckPointID, resumeData)...) + resumeTargets := buildResumeTargets(req.ResumeData) + var ( + iter *adk.AsyncIterator[*adk.AgentEvent] + ) + if len(resumeTargets) > 0 { + iter, err = runner.ResumeWithParams(ctx, summary.CheckPointID, &adk.ResumeParams{ + Targets: resumeTargets, + }, buildResumeOptions(summary.CheckPointID, resumeData)...) + } else { + iter, err = runner.Resume(ctx, summary.CheckPointID, buildResumeOptions(summary.CheckPointID, resumeData)...) + } if err != nil { summary.Status = "error" summary.ErrorMessage = err.Error() diff --git a/internal/ai/runtime/tools/analyze_conversation_tool.go b/internal/ai/runtime/tools/analyze_conversation_tool.go index 6e829b1..7fe4369 100644 --- a/internal/ai/runtime/tools/analyze_conversation_tool.go +++ b/internal/ai/runtime/tools/analyze_conversation_tool.go @@ -100,7 +100,7 @@ func (t *AnalyzeConversationTool) Info(ctx context.Context) (*schema.ToolInfo, e }), Extra: map[string]any{ "toolCode": toolx.GraphAnalyzeConversation.Code, - "sourceType": "graph", + "sourceType": toolx.GraphAnalyzeConversation.SourceType, }, }, nil } diff --git a/internal/ai/runtime/tools/handoff_graph_tool.go b/internal/ai/runtime/tools/handoff_graph_tool.go index 2163636..105f8a9 100644 --- a/internal/ai/runtime/tools/handoff_graph_tool.go +++ b/internal/ai/runtime/tools/handoff_graph_tool.go @@ -69,7 +69,7 @@ func (t *HandoffGraphTool) Info(ctx context.Context) (*schema.ToolInfo, error) { }), Extra: map[string]any{ "toolCode": toolx.GraphHandoffConversation.Code, - "sourceType": "graph", + "sourceType": toolx.GraphHandoffConversation.SourceType, }, }, nil }