mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 03:13:41 +08:00
fix(feishu): stop co-mentioned humans being learned as bot aliases
The mention alias-learning fed every identifier of every mention in a delivery into the per-chat alias cache. A single delivery of "@bot @alice" matched the bot by its global id and then learned alice's openId as a bot alias, so every later "@alice" message was misdetected as @bot and the agent replied to messages never addressed to it. Only single-mention deliveries are unambiguous bot identities, so restrict alias learning to them — a multi-mention delivery mixes the bot with co-mentioned humans, and Feishu's dual-delivery alias form is itself a single mention, so this is safe and keeps the learning feature working. Also cap the per-chat alias set size. Adds a [bot, human] co-mention regression test.
This commit is contained in:
parent
74b2607e40
commit
fcc2dd5ccf
@ -94,11 +94,17 @@ public class FeishuChannelAdapter extends AbstractChannelAdapter implements Stre
|
||||
*/
|
||||
private final ConcurrentHashMap<String, Set<String>> chatBotAliases = new ConcurrentHashMap<>();
|
||||
|
||||
/** Max learned aliases retained per chat, to bound memory on busy groups. */
|
||||
private static final int CHAT_ALIAS_MAX = 64;
|
||||
|
||||
/**
|
||||
* Per-messageId mention tracker(带 TTL)。
|
||||
* <p>飞书 SDK 经常对同一条消息双投递:一份 mentions 含 bot 的<em>全局身份</em>(来自 /bot/v3/info),
|
||||
* 另一份含 bot 的<em>群内别名</em>。我们累积同一 messageId 下所有投递看到的 mention 标识,
|
||||
* 一旦其中任何一份被识别为 @bot,就把累积的全部标识写入 {@link #chatBotAliases}。
|
||||
* 另一份含 bot 的<em>群内别名</em>。我们累积同一 messageId 下<em>单 mention</em>投递看到的标识,
|
||||
* 一旦其中任何一份被识别为 @bot,就把累积的标识写入 {@link #chatBotAliases}。
|
||||
* <p>只累积单 mention 投递是有意为之:多 mention 投递(如 {@code @bot @某人})会把 bot 与
|
||||
* 被同时 @ 的人混在一起,无法区分,若整体学习会把人误学成 bot 别名,导致之后 @ 该人的消息
|
||||
* 被误判为 @bot。而飞书双投递里 bot 别名那一份本身就是单 mention,所以这样既安全又不丢功能。
|
||||
*/
|
||||
private final ConcurrentHashMap<String, MentionTrack> mentionTracker = new ConcurrentHashMap<>();
|
||||
|
||||
@ -720,7 +726,13 @@ public class FeishuChannelAdapter extends AbstractChannelAdapter implements Stre
|
||||
MentionTrack track = null;
|
||||
if (messageId != null) {
|
||||
track = mentionTracker.computeIfAbsent(messageId, k -> new MentionTrack());
|
||||
collectMentionIdentifiers(mentions, track.seenIds);
|
||||
// Only single-mention deliveries are unambiguous bot identities. A
|
||||
// multi-mention delivery (e.g. @bot @alice) mixes the bot with
|
||||
// co-mentioned humans that must NOT be learned as aliases; Feishu's
|
||||
// dual-delivery alias form is itself a single mention, so this is safe.
|
||||
if (mentions.length == 1) {
|
||||
collectMentionIdentifiers(mentions, track.seenIds);
|
||||
}
|
||||
}
|
||||
|
||||
// 1. 直接匹配 bot 的全局身份
|
||||
@ -754,6 +766,7 @@ public class FeishuChannelAdapter extends AbstractChannelAdapter implements Stre
|
||||
private void learnFromTrack(String chatId, MentionTrack track) {
|
||||
if (chatId == null || track == null || track.seenIds.isEmpty()) return;
|
||||
Set<String> aliases = chatBotAliases.computeIfAbsent(chatId, k -> ConcurrentHashMap.newKeySet());
|
||||
if (aliases.size() >= CHAT_ALIAS_MAX) return;
|
||||
int before = aliases.size();
|
||||
aliases.addAll(track.seenIds);
|
||||
int added = aliases.size() - before;
|
||||
|
||||
@ -132,6 +132,22 @@ class FeishuMentionTest {
|
||||
new MentionEvent[]{mentionEvent(alias)}, chatB, "m3", BOT_ID, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void learning_coMentionedHumanNotLearnedAsAlias() {
|
||||
FeishuChannelAdapter adapter = newAdapter();
|
||||
String human = "ou_human_alice";
|
||||
String chatA = "oc_chatA";
|
||||
|
||||
// @bot @alice 在同一次投递:bot 用全局身份命中(返回 true),
|
||||
// 但被同时 @ 的人不能被学成 bot 别名。
|
||||
assertTrue(adapter.detectBotMentionWithLearning(
|
||||
new MentionEvent[]{mentionEvent(BOT_ID), mentionEvent(human)}, chatA, "m_co", BOT_ID, null));
|
||||
|
||||
// 之后只 @ 那个人的消息,绝不能被误判为 @bot。
|
||||
assertFalse(adapter.detectBotMentionWithLearning(
|
||||
new MentionEvent[]{mentionEvent(human)}, chatA, "m_human", BOT_ID, null));
|
||||
}
|
||||
|
||||
// ==================== mention tracker TTL ====================
|
||||
|
||||
@Test
|
||||
|
||||
Loading…
Reference in New Issue
Block a user