fix(buzz): trust explicit DM metadata fallback

This commit is contained in:
Elmar Conradie
2026-08-23 09:53:29 +02:00
committed by Teknium
parent 722209bb51
commit f40edee459
2 changed files with 30 additions and 14 deletions

View File

@@ -1318,10 +1318,8 @@ class BuzzAdapter(BasePlatformAdapter):
``dms list`` is only a best-effort source: on some hosted relays it
returns ``[]`` even when DM conversations exist (#68871). Those DMs
DO surface in ``channels list`` as entries named "DM" with an empty
description, so that listing is scanned as a fallback. Fallback
finds are watched as ``group`` and latch to ``dm`` via p-tag
detection (_is_direct_message_event) rather than trusting the name
alone to unlock the mention-free DM path.
description, so that exact metadata shape is the fallback. Named
rooms and missing metadata still fail closed as groups.
"""
code, out, _err = await self._run_cli(["dms", "list"])
if code == 0:
@@ -1344,12 +1342,15 @@ class BuzzAdapter(BasePlatformAdapter):
continue
self._channel_meta[ch_id] = ch
self._channel_names.setdefault(ch_id, str(ch.get("name") or ch_id))
if ch_id in self._channel_state or not self._may_reclassify_as_dm(ch_id):
if not self._may_reclassify_as_dm(ch_id):
continue
if ch_id in self._channel_state:
self._channel_state[ch_id]["chat_type"] = "dm"
continue
if seed:
await self._seed_channel(ch_id, chat_type="group")
await self._seed_channel(ch_id, chat_type="dm")
else:
self._channel_state[ch_id] = self._new_channel_state("group")
self._channel_state[ch_id] = self._new_channel_state("dm")
async def _poll_channel(self, channel_id: str) -> None:
state = self._channel_state.get(channel_id)
@@ -1459,10 +1460,10 @@ class BuzzAdapter(BasePlatformAdapter):
# ``buzz dms list`` returns [] on some hosted relays even when DM
# conversations exist, so DMs can leak in through ``channels list`` as
# chat_type="group". Relay-materialized DMs are named "DM" with an empty
# description, and their messages carry a structural p-tag to us. Only
# that explicit metadata shape may latch to DM; named channels and missing
# metadata fail closed. In normal channels the same p-tag is an addressing
# signal and must wake the agent without changing the conversation type.
# description, which periodic discovery promotes to DM even when messages
# omit recipient p-tags. Named channels and missing metadata fail closed.
# In normal channels a p-tag is only an addressing signal and must wake the
# agent without changing the conversation type.
def _may_reclassify_as_dm(self, channel_id: str) -> bool:
"""True when the conversation's metadata does not rule out a DM.

View File

@@ -1129,7 +1129,7 @@ class TestDmClassification:
@pytest.mark.asyncio
async def test_dm_shaped_channel_discovered_when_dms_list_empty(self):
"""Fallback discovery: with `dms list` broken (returns []), a
DM-shaped `channels list` entry gets watched; real channels not
DM-shaped `channels list` entry becomes a DM; real channels not
already watched are left alone."""
a = _make_adapter()
cli = _ScriptedCli()
@@ -1141,12 +1141,27 @@ class TestDmClassification:
])
a._run_cli = cli
await a._discover_dms(seed=False)
# Watched as group; the p-tag latch flips it on the first real DM.
assert a._channel_state[DM_CHANNEL]["chat_type"] == "group"
assert a._channel_state[DM_CHANNEL]["chat_type"] == "dm"
assert a._may_reclassify_as_dm(DM_CHANNEL) is True
assert CHANNEL not in a._channel_state
assert a._may_reclassify_as_dm(CHANNEL) is False
@pytest.mark.asyncio
async def test_dm_metadata_promotes_existing_group_without_recipient_tag(self, adapter):
cli = _ScriptedCli()
cli.script("dms", "list", [])
cli.script("channels", "list", [adapter._channel_meta[DM_CHANNEL]])
adapter._run_cli = cli
await adapter._discover_dms(seed=False)
assert adapter._channel_state[DM_CHANNEL]["chat_type"] == "dm"
await self._poll_with(
adapter, DM_CHANNEL,
_tagged_event("e1", DM_CHANNEL, content="no mention and no p tag"),
)
assert [d["message_id"] for d in adapter._dispatched] == ["e1"]
assert adapter._dispatched[0]["chat_type"] == "dm"
class TestThreadRoots: