fix(message): suppress duplicate sends within same round
This commit is contained in:
parent
c4080436db
commit
a49803ec90
2 changed files with 50 additions and 0 deletions
|
|
@ -12,6 +12,9 @@ type MessageTool struct {
|
|||
defaultChannel string
|
||||
defaultChatID string
|
||||
sentInRound bool // Tracks whether a message was sent in the current processing round
|
||||
lastChannel string
|
||||
lastChatID string
|
||||
lastContent string
|
||||
}
|
||||
|
||||
func NewMessageTool() *MessageTool {
|
||||
|
|
@ -51,6 +54,9 @@ func (t *MessageTool) SetContext(channel, chatID string) {
|
|||
t.defaultChannel = channel
|
||||
t.defaultChatID = chatID
|
||||
t.sentInRound = false // Reset send tracking for new processing round
|
||||
t.lastChannel = ""
|
||||
t.lastChatID = ""
|
||||
t.lastContent = ""
|
||||
}
|
||||
|
||||
// HasSentInRound returns true if the message tool sent a message during the current round.
|
||||
|
|
@ -86,6 +92,15 @@ func (t *MessageTool) Execute(ctx context.Context, args map[string]any) *ToolRes
|
|||
return &ToolResult{ForLLM: "Message sending not configured", IsError: true}
|
||||
}
|
||||
|
||||
// Guard against accidental repeated tool-calls in one LLM round.
|
||||
// If the same target and content were already sent, suppress duplicate delivery.
|
||||
if t.sentInRound && t.lastChannel == channel && t.lastChatID == chatID && t.lastContent == content {
|
||||
return &ToolResult{
|
||||
ForLLM: "Duplicate message suppressed in current round",
|
||||
Silent: true,
|
||||
}
|
||||
}
|
||||
|
||||
if err := t.sendCallback(channel, chatID, content); err != nil {
|
||||
return &ToolResult{
|
||||
ForLLM: fmt.Sprintf("sending message: %v", err),
|
||||
|
|
@ -95,6 +110,9 @@ func (t *MessageTool) Execute(ctx context.Context, args map[string]any) *ToolRes
|
|||
}
|
||||
|
||||
t.sentInRound = true
|
||||
t.lastChannel = channel
|
||||
t.lastChatID = chatID
|
||||
t.lastContent = content
|
||||
// Silent: user already received the message directly
|
||||
return &ToolResult{
|
||||
ForLLM: fmt.Sprintf("Message sent to %s:%s", channel, chatID),
|
||||
|
|
|
|||
|
|
@ -194,6 +194,38 @@ func TestMessageTool_Execute_NotConfigured(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestMessageTool_Execute_SuppressDuplicateInSameRound(t *testing.T) {
|
||||
tool := NewMessageTool()
|
||||
tool.SetContext("test-channel", "test-chat-id")
|
||||
|
||||
callCount := 0
|
||||
tool.SetSendCallback(func(channel, chatID, content string) error {
|
||||
callCount++
|
||||
return nil
|
||||
})
|
||||
|
||||
ctx := context.Background()
|
||||
args := map[string]any{
|
||||
"content": "same message",
|
||||
}
|
||||
|
||||
first := tool.Execute(ctx, args)
|
||||
second := tool.Execute(ctx, args)
|
||||
|
||||
if callCount != 1 {
|
||||
t.Fatalf("send callback call count = %d, want 1", callCount)
|
||||
}
|
||||
if !first.Silent || first.IsError {
|
||||
t.Fatalf("first result unexpected: %+v", first)
|
||||
}
|
||||
if !second.Silent || second.IsError {
|
||||
t.Fatalf("second result unexpected: %+v", second)
|
||||
}
|
||||
if second.ForLLM != "Duplicate message suppressed in current round" {
|
||||
t.Fatalf("second ForLLM = %q", second.ForLLM)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMessageTool_Name(t *testing.T) {
|
||||
tool := NewMessageTool()
|
||||
if tool.Name() != "message" {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue