mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-12 14:15:00 +00:00
fix(feishu): preserve group context without sender name
This commit is contained in:
1 parent
aa27354d16
commit
e4e4bb33fb
2 files changed
+145
-3
No files matched your search
@@ -101,6 +101,10 @@ func (c *Channel) handleMessageEventFrom(ctx context.Context, event *MessageEven
|
||||
|
||||
// 3. Resolve sender name (cached)
|
||||
senderName := c.resolveSenderName(ctx, mc.SenderID)
|
||||
senderLabel := senderName
|
||||
if senderLabel == "" {
|
||||
senderLabel = mc.SenderID
|
||||
}
|
||||
|
||||
// 4. Resolve media BEFORE mention gate so non-mentioned messages
|
||||
// also have their files downloaded and stored in pending history.
|
||||
@@ -166,7 +170,7 @@ func (c *Channel) handleMessageEventFrom(ctx context.Context, event *MessageEven
|
||||
historyKey = fmt.Sprintf("%s:topic:%s", mc.ChatID, mc.RootID)
|
||||
}
|
||||
c.GroupHistory().Record(historyKey, channels.HistoryEntry{
|
||||
Sender: senderName,
|
||||
Sender: senderLabel,
|
||||
SenderID: mc.SenderID,
|
||||
Body: mc.Content,
|
||||
Media: earlyMediaPaths,
|
||||
@@ -307,9 +311,12 @@ func (c *Channel) handleMessageEventFrom(ctx context.Context, event *MessageEven
|
||||
}
|
||||
|
||||
// Annotate content with sender identity so the agent knows who is messaging.
|
||||
if senderName != "" {
|
||||
if mc.ChatType == "group" || senderName != "" {
|
||||
if mc.ChatType == "group" {
|
||||
annotated := fmt.Sprintf("[From: %s]\n%s", senderName, content)
|
||||
annotated := content
|
||||
if senderLabel != "" {
|
||||
annotated = fmt.Sprintf("[From: %s]\n%s", senderLabel, content)
|
||||
}
|
||||
if c.HistoryLimit() > 0 {
|
||||
content = c.GroupHistory().BuildContext(chatID, annotated, c.HistoryLimit())
|
||||
} else {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -80,6 +81,140 @@ func TestCheckGroupPolicy_Pairing_GroupAllowListBypasses(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleMessageEvent_GroupContextFallsBackToSenderIDWhenNameLookupFails(t *testing.T) {
|
||||
requireMention := true
|
||||
msgBus := bus.New()
|
||||
defer msgBus.Close()
|
||||
|
||||
ch, err := New(config.FeishuConfig{
|
||||
AppID: "app",
|
||||
AppSecret: "secret",
|
||||
GroupPolicy: "open",
|
||||
RequireMention: &requireMention,
|
||||
}, msgBus, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("New: %v", err)
|
||||
}
|
||||
ch.SetName("feishu-test")
|
||||
ch.botOpenID = "ou_target_bot"
|
||||
srv := newSimpleMockServer(t, `{"code":50000,"msg":"name lookup failed"}`)
|
||||
ch.client = NewLarkClient("app", "secret", srv.URL)
|
||||
|
||||
first := feishuGroupTextEvent(t, "om_context", "ou_duc", "oc_group", "Send AGENTS.md again", nil)
|
||||
ch.handleMessageEvent(context.Background(), first)
|
||||
assertNoFeishuInbound(t, msgBus)
|
||||
|
||||
entries := ch.GroupHistory().GetEntries("oc_group")
|
||||
if len(entries) != 1 {
|
||||
t.Fatalf("history entries = %d, want 1", len(entries))
|
||||
}
|
||||
if entries[0].Sender != "ou_duc" {
|
||||
t.Fatalf("history sender = %q, want sender ID fallback", entries[0].Sender)
|
||||
}
|
||||
|
||||
second := feishuGroupTextEvent(t, "om_mention", "ou_duc", "oc_group", "@_user_1", []EventMention{
|
||||
feishuMention("@_user_1", "ou_target_bot", "Techlead"),
|
||||
})
|
||||
ch.handleMessageEvent(context.Background(), second)
|
||||
|
||||
msg := assertFeishuInbound(t, msgBus)
|
||||
for _, want := range []string{
|
||||
"[From: ou_duc]",
|
||||
"[empty message]",
|
||||
"Send AGENTS.md again",
|
||||
} {
|
||||
if !strings.Contains(msg.Content, want) {
|
||||
t.Errorf("content missing %q:\n%s", want, msg.Content)
|
||||
}
|
||||
}
|
||||
if got := ch.GroupHistory().GetEntries("oc_group"); len(got) != 0 {
|
||||
t.Fatalf("history entries after publish = %d, want 0", len(got))
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleMessageEvent_GroupContextPreservesResolvedSenderName(t *testing.T) {
|
||||
requireMention := true
|
||||
msgBus := bus.New()
|
||||
defer msgBus.Close()
|
||||
|
||||
ch, err := New(config.FeishuConfig{
|
||||
AppID: "app",
|
||||
AppSecret: "secret",
|
||||
GroupPolicy: "open",
|
||||
RequireMention: &requireMention,
|
||||
}, msgBus, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("New: %v", err)
|
||||
}
|
||||
ch.SetName("feishu-test")
|
||||
ch.botOpenID = "ou_target_bot"
|
||||
srv := newSimpleMockServer(t, `{"code":0,"msg":"ok","data":{"user":{"name":"Duc Nguyen"}}}`)
|
||||
ch.client = NewLarkClient("app", "secret", srv.URL)
|
||||
|
||||
event := feishuGroupTextEvent(t, "om_named", "ou_duc", "oc_group", "@_user_1 hello", []EventMention{
|
||||
feishuMention("@_user_1", "ou_target_bot", "Techlead"),
|
||||
})
|
||||
ch.handleMessageEvent(context.Background(), event)
|
||||
|
||||
msg := assertFeishuInbound(t, msgBus)
|
||||
if msg.Content != "[From: Duc Nguyen]\nhello" {
|
||||
t.Fatalf("content = %q, want resolved sender name", msg.Content)
|
||||
}
|
||||
if msg.Metadata["sender_name"] != "Duc Nguyen" {
|
||||
t.Fatalf("sender_name metadata = %q", msg.Metadata["sender_name"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleMessageEvent_P2PContextRemainsNameBased(t *testing.T) {
|
||||
msgBus := bus.New()
|
||||
defer msgBus.Close()
|
||||
|
||||
ch, err := New(config.FeishuConfig{AppID: "app", AppSecret: "secret", DMPolicy: "open"}, msgBus, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("New: %v", err)
|
||||
}
|
||||
ch.SetName("feishu-test")
|
||||
srv := newSimpleMockServer(t, `{"code":0,"msg":"ok","data":{"user":{"name":"Duc Nguyen"}}}`)
|
||||
ch.client = NewLarkClient("app", "secret", srv.URL)
|
||||
|
||||
event := feishuGroupTextEvent(t, "om_p2p", "ou_duc", "oc_p2p", "hello", nil)
|
||||
event.Event.Message.ChatType = "p2p"
|
||||
ch.handleMessageEvent(context.Background(), event)
|
||||
|
||||
msg := assertFeishuInbound(t, msgBus)
|
||||
if msg.Content != "[From: Duc Nguyen]\nhello" {
|
||||
t.Fatalf("content = %q, want unchanged p2p name context", msg.Content)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleMessageEvent_GroupContextDoesNotEmitEmptySenderLabel(t *testing.T) {
|
||||
requireMention := true
|
||||
msgBus := bus.New()
|
||||
defer msgBus.Close()
|
||||
|
||||
ch, err := New(config.FeishuConfig{
|
||||
AppID: "app",
|
||||
AppSecret: "secret",
|
||||
GroupPolicy: "open",
|
||||
RequireMention: &requireMention,
|
||||
}, msgBus, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("New: %v", err)
|
||||
}
|
||||
ch.SetName("feishu-test")
|
||||
ch.botOpenID = "ou_target_bot"
|
||||
|
||||
event := feishuGroupTextEvent(t, "om_no_sender", "", "oc_group", "@_user_1", []EventMention{
|
||||
feishuMention("@_user_1", "ou_target_bot", "Techlead"),
|
||||
})
|
||||
ch.handleMessageEvent(context.Background(), event)
|
||||
|
||||
msg := assertFeishuInbound(t, msgBus)
|
||||
if msg.Content != "[empty message]" {
|
||||
t.Fatalf("content = %q, want no empty sender annotation", msg.Content)
|
||||
}
|
||||
}
|
||||
|
||||
type feishuPolicyPairingStore struct {
|
||||
requests int
|
||||
lastSenderID string
|
||||
|
||||
Reference in new issue
Block a user