From 58dcafd15fb6c2e7dff7f7a16c2c2f981a2b86b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=AC=E6=98=8E?= <83812544+Ed1s0nZ@users.noreply.github.com> Date: Sun, 28 Jun 2026 00:56:22 +0800 Subject: [PATCH] Add files via upload --- internal/multiagent/eino_transient_retry.go | 27 +++++++++---------- .../multiagent/eino_transient_retry_test.go | 15 +++++++++++ 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/internal/multiagent/eino_transient_retry.go b/internal/multiagent/eino_transient_retry.go index b73760a6..bb1d4fae 100644 --- a/internal/multiagent/eino_transient_retry.go +++ b/internal/multiagent/eino_transient_retry.go @@ -190,29 +190,26 @@ func einoMessagesForRunRestart(args *einoADKRunLoopArgs, baseMsgs, accumulated [ return append([]adk.Message(nil), baseMsgs...), einoRestartContextInitial } -// adkMessagesHasUserContent 从尾部向前查找,是否已有与 want 相同的 user 消息(避免重复 append)。 +// adkMessagesHasUserContent reports whether the conversation tail is already a user turn +// with the given content. Only the last message counts: matching text in an earlier round +// (e.g. user repeats the same prompt after an assistant reply) must not suppress appending +// the new user turn — Claude 4.6+ rejects requests whose final message is assistant. func adkMessagesHasUserContent(msgs []adk.Message, want string) bool { want = strings.TrimSpace(want) if want == "" { return true } - for i := len(msgs) - 1; i >= 0; i-- { - m := msgs[i] - if m == nil { - continue - } - if m.Role == schema.User { - return strings.TrimSpace(m.Content) == want - } - if m.Role == schema.Assistant || m.Role == schema.Tool { - continue - } - break + if len(msgs) == 0 { + return false } - return false + last := msgs[len(msgs)-1] + if last == nil || last.Role != schema.User { + return false + } + return strings.TrimSpace(last.Content) == want } -// appendUserMessageIfNeeded 在 history 轨迹之后追加本轮 user 消息(仅当轨迹中尚未包含该句)。 +// appendUserMessageIfNeeded 在 history 轨迹之后追加本轮 user 消息(仅当尾部已是相同 user 句)。 func appendUserMessageIfNeeded(msgs []adk.Message, userMessage string) []adk.Message { if strings.TrimSpace(userMessage) == "" || adkMessagesHasUserContent(msgs, userMessage) { return msgs diff --git a/internal/multiagent/eino_transient_retry_test.go b/internal/multiagent/eino_transient_retry_test.go index 39b9c81c..ef8f0608 100644 --- a/internal/multiagent/eino_transient_retry_test.go +++ b/internal/multiagent/eino_transient_retry_test.go @@ -143,3 +143,18 @@ func TestAppendUserMessageIfNeeded(t *testing.T) { t.Fatalf("should not duplicate user message: len=%d", len(dup)) } } + +func TestAppendUserMessageIfNeeded_repeatPromptAfterAssistant(t *testing.T) { + t.Parallel() + msgs := []adk.Message{ + schema.UserMessage("扫描 example.com"), + schema.AssistantMessage("开始扫描...", nil), + } + out := appendUserMessageIfNeeded(msgs, "扫描 example.com") + if len(out) != 3 { + t.Fatalf("should append new user turn after assistant reply: len=%d", len(out)) + } + if out[2].Role != schema.User || out[2].Content != "扫描 example.com" { + t.Fatalf("tail should be repeated user prompt, got role=%s content=%q", out[2].Role, out[2].Content) + } +}