diff --git a/plugins/platforms/matrix/adapter.py b/plugins/platforms/matrix/adapter.py index 17e47d4244e..ebe9ebbbff8 100644 --- a/plugins/platforms/matrix/adapter.py +++ b/plugins/platforms/matrix/adapter.py @@ -1459,9 +1459,21 @@ class MatrixAdapter(BasePlatformAdapter): # Without this the INVITE handler below never fires. client.add_dispatcher(MembershipEventDispatcher) - client.add_event_handler(EventType.ROOM_MESSAGE, self._on_room_message) - client.add_event_handler(EventType.REACTION, self._on_reaction) - client.add_event_handler(IntEvt.INVITE, self._on_invite) + client.add_event_handler( + EventType.ROOM_MESSAGE, + self._on_room_message, + wait_sync=True, + ) + client.add_event_handler( + EventType.REACTION, + self._on_reaction, + wait_sync=True, + ) + client.add_event_handler( + IntEvt.INVITE, + self._on_invite, + wait_sync=True, + ) # Initial sync to catch up, then start background sync. self._startup_ts = time.time() diff --git a/scripts/release.py b/scripts/release.py index c42ee55e789..9220162ade0 100755 --- a/scripts/release.py +++ b/scripts/release.py @@ -232,6 +232,7 @@ AUTHOR_MAP = { "290859878+synapsesx@users.noreply.github.com": "synapsesx", "157689911+itsflownium@users.noreply.github.com": "itsflownium", "dirtyren@users.noreply.github.com": "dirtyren", + "153708448+hunjaiboy@users.noreply.github.com": "yyzquwu", # PR #47567 salvage (Matrix: register inbound handlers with wait_sync=True so _dispatch_sync's gather awaits them; without it mautrix fire-and-forgets and inbound intake has no completion point) "tgmerritt@gmail.com": "tgmerritt", # PR #43553 salvage (parse vLLM's token-based output-cap error format so over-cap max_tokens 400s reduce the output cap instead of death-looping into compression) "13277570+justin-cyhuang@users.noreply.github.com": "justin-cyhuang", "agent@tranquil-flow.dev": "Tranquil-Flow", diff --git a/tests/gateway/test_matrix.py b/tests/gateway/test_matrix.py index dd413c9f74a..7484220456b 100644 --- a/tests/gateway/test_matrix.py +++ b/tests/gateway/test_matrix.py @@ -106,7 +106,7 @@ def _make_fake_mautrix(): self.crypto = None self._event_handlers = {} - def add_event_handler(self, event_type, handler): + def add_event_handler(self, event_type, handler, **kwargs): self._event_handlers.setdefault(event_type, []).append(handler) def add_dispatcher(self, dispatcher_type): @@ -2727,13 +2727,20 @@ class TestMatrixEncryptedEventHandler: with patch.object(adapter, "_sync_loop", AsyncMock(return_value=None)): assert await adapter.connect() is True - # Verify event handlers were registered. - # In mautrix the order is: add_event_handler(EventType, callback) + # Verify inbound event handlers were registered as sync-awaited + # callbacks. mautrix only returns waited handler tasks from + # handle_sync(), so background-only handlers leave _dispatch_sync() + # without a completion point for Hermes' Matrix intake. handler_calls = mock_client.add_event_handler.call_args_list - registered_types = [call.args[0] for call in handler_calls] + waited_types = { + str(call.args[0]) + for call in handler_calls + if call.kwargs.get("wait_sync") is True + } - # Should have registered handlers for ROOM_MESSAGE, REACTION, INVITE - assert len(handler_calls) >= 3 + assert "m.room.message" in waited_types + assert "m.reaction" in waited_types + assert "internal.invite" in waited_types await adapter.disconnect()