mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-01 12:02:05 +00:00
fix(matrix): record DM rooms in m.direct on invite to prevent group misclassification
Rebase onto plugins/platforms/matrix/adapter.py (code moved from gateway/platforms/matrix.py). Same logic: _on_invite checks is_direct on invite events and calls _record_dm_room to persist in m.direct account data. Fixes #44679
This commit is contained in:
parent
fde1c8570f
commit
14baeefe1d
2 changed files with 325 additions and 5 deletions
|
|
@ -2885,15 +2885,27 @@ class MatrixAdapter(BasePlatformAdapter):
|
|||
await self.handle_message(msg_event)
|
||||
|
||||
async def _on_invite(self, event: Any) -> None:
|
||||
"""Auto-join rooms when invited."""
|
||||
"""Auto-join rooms when invited, recording DM rooms in m.direct."""
|
||||
|
||||
room_id = str(getattr(event, "room_id", ""))
|
||||
content = getattr(event, "content", None)
|
||||
is_direct = bool(getattr(content, "is_direct", False))
|
||||
inviter = str(getattr(event, "sender", ""))
|
||||
|
||||
logger.info(
|
||||
"Matrix: invited to %s — joining",
|
||||
"Matrix: invited to %s — joining (is_direct=%s)",
|
||||
room_id,
|
||||
is_direct,
|
||||
)
|
||||
# When the invite declares this as a DM, record it in m.direct after
|
||||
# the (non-blocking) join completes so that _resolve_room_identity
|
||||
# treats it correctly even when the bot account has no prior DM
|
||||
# history. The join itself stays off the sync path.
|
||||
self._schedule_invite_join(
|
||||
room_id,
|
||||
is_direct=is_direct and bool(inviter),
|
||||
inviter=inviter,
|
||||
)
|
||||
self._schedule_invite_join(room_id)
|
||||
|
||||
async def _join_room_by_id(self, room_id: str) -> bool:
|
||||
"""Join a room by ID and refresh local caches on success."""
|
||||
|
|
@ -2913,7 +2925,13 @@ class MatrixAdapter(BasePlatformAdapter):
|
|||
logger.warning("Matrix: error joining %s: %s", room_id, exc)
|
||||
return False
|
||||
|
||||
def _schedule_invite_join(self, room_id: str) -> None:
|
||||
def _schedule_invite_join(
|
||||
self,
|
||||
room_id: str,
|
||||
*,
|
||||
is_direct: bool = False,
|
||||
inviter: str = "",
|
||||
) -> None:
|
||||
"""Schedule an invite join without blocking sync or gateway readiness."""
|
||||
if not room_id or room_id in self._joined_rooms:
|
||||
return
|
||||
|
|
@ -2923,7 +2941,13 @@ class MatrixAdapter(BasePlatformAdapter):
|
|||
|
||||
async def _join_invite() -> None:
|
||||
try:
|
||||
await asyncio.wait_for(self._join_room_by_id(room_id), timeout=45.0)
|
||||
joined = await asyncio.wait_for(
|
||||
self._join_room_by_id(room_id), timeout=45.0
|
||||
)
|
||||
# Persist the DM signal from the invite once the join lands,
|
||||
# so m.direct is authoritative even on a fresh bot account.
|
||||
if joined and is_direct and inviter:
|
||||
await self._record_dm_room(room_id, inviter)
|
||||
except asyncio.TimeoutError:
|
||||
logger.warning("Matrix: timed out joining invite %s", room_id)
|
||||
finally:
|
||||
|
|
@ -3779,6 +3803,47 @@ class MatrixAdapter(BasePlatformAdapter):
|
|||
self._room_identities.clear()
|
||||
self._room_identity_cached_at.clear()
|
||||
|
||||
async def _record_dm_room(self, room_id: str, inviter: str) -> None:
|
||||
"""Persist a room as DM in m.direct account data after an invite.
|
||||
|
||||
When the bot account has never been used for DMs, ``m.direct`` is
|
||||
absent (404). This method fetches the current mapping (if any),
|
||||
appends *room_id* under the *inviter*'s entry, and writes it back
|
||||
so that subsequent ``_refresh_dm_cache`` calls treat the room as a
|
||||
DM without requiring manual ``m.direct`` setup.
|
||||
"""
|
||||
if not self._client:
|
||||
return
|
||||
|
||||
dm_data: Dict[str, list] = {}
|
||||
try:
|
||||
resp = await self._client.get_account_data("m.direct")
|
||||
if hasattr(resp, "content") and isinstance(resp.content, dict):
|
||||
dm_data = resp.content
|
||||
elif isinstance(resp, dict):
|
||||
dm_data = resp
|
||||
except Exception:
|
||||
pass # m.direct doesn't exist yet — start fresh
|
||||
|
||||
rooms_for_user = dm_data.get(inviter, [])
|
||||
if not isinstance(rooms_for_user, list):
|
||||
rooms_for_user = []
|
||||
if room_id not in rooms_for_user:
|
||||
rooms_for_user.append(room_id)
|
||||
dm_data[inviter] = rooms_for_user
|
||||
try:
|
||||
await self._client.set_account_data("m.direct", dm_data)
|
||||
logger.info(
|
||||
"Matrix: recorded %s as DM room (inviter=%s)", room_id, inviter
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.warning("Matrix: failed to update m.direct: %s", exc)
|
||||
|
||||
# Update local cache so _resolve_room_identity sees it immediately.
|
||||
self._dm_rooms[room_id] = True
|
||||
self._room_identities.pop(room_id, None)
|
||||
self._room_identity_cached_at.pop(room_id, None)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Mention detection helpers
|
||||
# ------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue