fix(slack): count pipe-form bot mentions as mentioned in ignore gate

The ignore_other_user_mentions gate relied solely on is_mentioned, which
only recognises exact <@UID> markup, so a message mentioning the bot in
pipe form (<@UID|name>) alongside a leading other-user mention was
wrongly suppressed. The gate now also scans for the bot's own mention in
either markup before ignoring a message.

Claude-Session: https://claude.ai/code/session_01TKsNdptNdo9CqT2u7JMdkH
This commit is contained in:
Ben Phillips 2026-07-16 09:27:50 +01:00 committed by Teknium
parent 7f9cab15d8
commit 286ec6afb3
2 changed files with 63 additions and 0 deletions

View file

@ -4453,6 +4453,7 @@ class SlackAdapter(BasePlatformAdapter):
if (
self._slack_ignore_other_user_mentions()
and not is_mentioned
and not self._slack_message_mentions_self(routing_text, self_uids)
and self._slack_message_addressed_to_other_user(routing_text, self_uids)
):
logger.debug(
@ -6766,6 +6767,21 @@ class SlackAdapter(BasePlatformAdapter):
return False
return match.group(1) not in self_uids
def _slack_message_mentions_self(self, text: str, self_uids: set) -> bool:
"""Return True when ``text`` @-mentions this bot anywhere in the message.
Matches both mention markups ``<@U123>`` and the pipe form
``<@U123|name>`` so the ignore_other_user_mentions gate treats a
pipe-form bot mention as "also mentioned" even though the exact-markup
``is_mentioned`` check only recognises ``<@U123>``.
"""
if not text:
return False
return any(
re.search(rf"<@{re.escape(uid)}(?:\|[^>]*)?>", text)
for uid in self_uids
)
def _slack_free_response_channels(self) -> set:
"""Return channel IDs where no @mention is required."""
raw = self.config.extra.get("free_response_channels")

View file

@ -159,6 +159,35 @@ def test_addressed_channel_and_broadcast_tokens_are_not_users():
assert _addressed("<#C0000000000|general> see here") is False
# ---------------------------------------------------------------------------
# _slack_message_mentions_self()
# ---------------------------------------------------------------------------
def _mentions_self(text):
return _make_adapter()._slack_message_mentions_self(text, SELF_UIDS)
def test_mentions_self_plain_form():
assert _mentions_self(f"hello <@{BOT_USER_ID}>") is True
def test_mentions_self_pipe_form():
assert _mentions_self(f"hello <@{BOT_USER_ID}|hermes>") is True
def test_mentions_self_other_user_only():
assert _mentions_self(f"hello <@{OTHER_USER_ID}|rasha>") is False
def test_mentions_self_id_prefix_is_not_a_match():
# <@U_BOT_123X> is a different user whose ID merely starts with ours.
assert _mentions_self(f"hello <@{BOT_USER_ID}X>") is False
def test_mentions_self_empty():
assert _mentions_self("") is False
# ---------------------------------------------------------------------------
# Integration: real _handle_slack_message
# ---------------------------------------------------------------------------
@ -245,6 +274,24 @@ async def test_free_response_replies_when_bot_also_mentioned(adapter):
adapter.handle_message.assert_awaited_once()
@pytest.mark.asyncio
async def test_free_response_replies_when_bot_mentioned_in_pipe_form(adapter):
"""A pipe-form bot mention (``<@U123|name>``) counts as "also mentioned"
even though the exact-markup ``is_mentioned`` check misses it."""
adapter.config.extra["free_response_channels"] = CHANNEL_ID
adapter.config.extra["ignore_other_user_mentions"] = True
await _run(
adapter,
_event(
f"<@{OTHER_USER_ID}|rasha> and <@{BOT_USER_ID}|hermes> please compare",
ts="1700000000.000004",
),
)
adapter.handle_message.assert_awaited_once()
@pytest.mark.asyncio
async def test_mentioned_thread_ignores_followup_addressed_to_other_user(adapter):
"""Ben's case: once the bot has been mentioned in a thread it auto-follows,