From 060e2a4286433134a71573c2aac5e16dd5fd50d8 Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Mon, 14 Sep 2026 21:33:45 -0700 Subject: [PATCH] fix: exempt the Matrix quote block from the mention strip only on real replies The reply-pill fix split the body on a leading "> " so the strip would not rewrite the "> <@bot:srv>" pill. That keyed the exemption on the body shape, not on the relation: a hand-typed blockquote in a plain (non-reply) message that mentions the bot inside the quote reached the agent with the raw "@hermes:example.org" text, which main used to strip. Split around the quote only when m.relates_to carries m.in_reply_to; otherwise strip the whole body. Review finding: quote-block exemption keyed on body.startswith('> ') instead of m.in_reply_to. --- plugins/platforms/matrix/adapter.py | 10 +++++++--- .../test_matrix_message_event_metadata.py | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/plugins/platforms/matrix/adapter.py b/plugins/platforms/matrix/adapter.py index 64e1126d7c..418882f908 100644 --- a/plugins/platforms/matrix/adapter.py +++ b/plugins/platforms/matrix/adapter.py @@ -2025,9 +2025,13 @@ class MatrixAdapter(BasePlatformAdapter): # Strip the mention from the reply text only: the quote block carries the # ``> <@bot:srv> ...`` reply pill, which _extract_reply_context parses later # for reply_to_author_id. A whole-body replace rewrote the pill to ``> <>`` - # and silently dropped the replied-to author (#111233). - quote_block, reply_text = _split_reply_fallback(body) - body = quote_block + self._strip_mention(reply_text) + # and silently dropped the replied-to author (#111233). Only a real reply carries a + # pill; a hand-typed blockquote in a plain message is stripped whole as before. + if relates_to.get("m.in_reply_to"): + quote_block, reply_text = _split_reply_fallback(body) + body = quote_block + self._strip_mention(reply_text) + else: + body = self._strip_mention(body) # Real thread roots are preserved above; synthetic roots (this event) follow policy: DM # @mention threads / DM auto-thread, or room auto-thread unless session_scope pins the room. if not thread_id: diff --git a/tests/gateway/test_matrix_message_event_metadata.py b/tests/gateway/test_matrix_message_event_metadata.py index ee61090916..89cb5ea66a 100644 --- a/tests/gateway/test_matrix_message_event_metadata.py +++ b/tests/gateway/test_matrix_message_event_metadata.py @@ -290,3 +290,19 @@ async def test_reply_with_explicit_mention_still_strips_it_from_reply_text(monke assert msg.reply_to_author_id == "@carol:example.org" assert msg.reply_to_text == "original question" assert msg.text == "because reasons" + + +@pytest.mark.asyncio +async def test_plain_blockquote_without_reply_is_stripped_whole(monkeypatch): + """The quote exemption keys on m.in_reply_to, not on a leading ``> ``: a hand-typed + blockquote mentioning the bot in a non-reply message must not reach the agent raw.""" + adapter = _make_adapter(require_mention=True, monkeypatch=monkeypatch) + adapter._startup_ts = time.time() - 10 + + event = _make_event("> @hermes:example.org please summarise\n\nthanks", event_id="$evt_quote") + await adapter._on_room_message(event) + + msg = adapter.handle_message.await_args.args[0] + assert msg.reply_to_message_id is None + assert "@hermes:example.org" not in msg.text + assert "thanks" in msg.text