fix(matrix): isolate room context and restore reliable inbound dispatch (#18505)
* fix(matrix): isolate room context and inbound dispatch * test(matrix): cover room isolation and dispatch regressions * docs(matrix): document room isolation and session scope * fix(matrix): stabilize CI requirement checks * test(matrix): isolate mautrix stubs in requirements tests * fix(matrix): port room-scoped status and resume to slash commands mixin Move Matrix /status scope output and /resume same-room guards from the pre-refactor gateway/run.py into gateway/slash_commands.py so PR #18505 foundation behavior survives the upstream god-file decomposition. Uses i18n keys for Matrix resume/status messages. Preserves upstream session.py fixes (role_authorized, DM user_id isolation). * docs(matrix): explain inbound dispatch via handle_sync loop Document why Hermes uses an explicit sync loop with handle_sync() rather than client.start(), aligning with upstream #7914 diagnostics while preserving Hermes background maintenance tasks. * fix(i18n): add Matrix resume/status keys to all locale catalogs The Matrix /resume and /status slash-command keys added in the foundation PR must exist in every supported locale file. tests/agent/test_i18n.py asserts key and placeholder parity across catalogs. Non-English locales use English strings as interim placeholders until community translators can localize them. * fix(matrix): restore gateway authz for allowed_users; honor config require_mention Revert the early MATRIX_ALLOWED_USERS gate in _on_room_message so inbound sender authorization stays in gateway authz like main. Parse require_mention from config.extra (platforms.matrix / top-level matrix yaml) with env fallback, matching thread_require_mention and fixing Forge when require_mention is set only in profile config.yaml. * fix(matrix): harden status scope and allowlisted DMs * fix(matrix): use session store lookup for resume scope
This commit is contained in:
@@ -294,6 +294,22 @@ def build_session_context_prompt(
|
||||
if context.source.chat_topic:
|
||||
lines.append(f"**Channel Topic:** {context.source.chat_topic}")
|
||||
|
||||
if context.source.platform == Platform.MATRIX:
|
||||
src = context.source
|
||||
room_name = src.chat_name or src.chat_id
|
||||
room_id = _hash_chat_id(src.chat_id) if redact_pii else src.chat_id
|
||||
lines.append("")
|
||||
lines.append(f"**Matrix Room:** {room_name}")
|
||||
lines.append(f"**Matrix Room ID:** {room_id}")
|
||||
if src.thread_id:
|
||||
thread_id = _hash_chat_id(src.thread_id) if redact_pii else src.thread_id
|
||||
lines.append(f"**Matrix Thread:** {thread_id}")
|
||||
lines.append(
|
||||
"**Matrix room boundary:** Treat this turn as scoped to the current "
|
||||
"Matrix room/thread only. Do not assume unresolved references are "
|
||||
"about other Matrix rooms or projects unless the user explicitly says so."
|
||||
)
|
||||
|
||||
# User identity.
|
||||
# In shared multi-user sessions (shared threads OR shared non-thread groups
|
||||
# when group_sessions_per_user=False), multiple users contribute to the same
|
||||
@@ -1264,6 +1280,17 @@ class SessionStore:
|
||||
entries.sort(key=lambda e: e.updated_at, reverse=True)
|
||||
|
||||
return entries
|
||||
|
||||
def lookup_by_session_id(self, session_id: str) -> Optional[SessionEntry]:
|
||||
"""Return the active session entry for a persisted session ID, if any."""
|
||||
if not session_id:
|
||||
return None
|
||||
with self._lock:
|
||||
self._ensure_loaded_locked()
|
||||
for entry in self._entries.values():
|
||||
if entry.session_id == session_id:
|
||||
return entry
|
||||
return None
|
||||
|
||||
def append_to_transcript(self, session_id: str, message: Dict[str, Any], skip_db: bool = False) -> None:
|
||||
"""Append a message to a session's transcript (SQLite).
|
||||
|
||||
Reference in New Issue
Block a user