Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion gateway/platforms/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,14 @@ def _thread_metadata_for_source(source, reply_to_message_id: str | None = None)
if thread_id is None:
return None
metadata = {"thread_id": thread_id}
anchor = reply_to_message_id or getattr(source, "message_id", None)
if anchor is not None and _platform_name(getattr(source, "platform", None)) != "telegram":
metadata["reply_to_message_id"] = str(anchor)
if _platform_name(getattr(source, "platform", None)) == "telegram" and getattr(source, "chat_type", None) == "dm":
metadata["telegram_dm_topic_reply_fallback"] = True
tid = str(thread_id)
if tid and tid not in {"", "1"}:
metadata["direct_messages_topic_id"] = tid
anchor = reply_to_message_id or getattr(source, "message_id", None)
if anchor is not None:
metadata["telegram_reply_to_message_id"] = str(anchor)
return metadata
Expand Down
3 changes: 3 additions & 0 deletions gateway/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -14714,6 +14714,9 @@ def _thread_metadata_for_target(
if thread_id is None:
return None
metadata: Dict[str, Any] = {"thread_id": thread_id}
platform_name = str(getattr(platform, "value", platform) or "").lower()
if reply_to_message_id is not None and platform_name != "telegram":
metadata["reply_to_message_id"] = str(reply_to_message_id)
if self._is_telegram_dm_topic_target(
platform,
chat_id,
Expand Down
5 changes: 4 additions & 1 deletion tests/gateway/test_run_progress_topics.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,10 @@ async def test_run_agent_feishu_progress_replies_inside_existing_thread(monkeypa
assert result["final_response"] == "done"
assert adapter.sent
assert adapter.sent[0]["reply_to"] == "om_triggering_user_message"
assert adapter.sent[0]["metadata"] == {"thread_id": "topic_17585"}
assert adapter.sent[0]["metadata"] == {
"thread_id": "topic_17585",
"reply_to_message_id": "om_triggering_user_message",
}
assert adapter.edits
assert adapter.edits[0]["message_id"] == "progress-1"

Expand Down
64 changes: 60 additions & 4 deletions tests/gateway/test_tts_media_routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@


class _MediaRoutingAdapter(BasePlatformAdapter):
def __init__(self):
super().__init__(PlatformConfig(enabled=True, token="test"), Platform.TELEGRAM)
def __init__(self, platform=Platform.TELEGRAM):
super().__init__(PlatformConfig(enabled=True, token="test"), platform)

async def connect(self):
return True
Expand All @@ -35,9 +35,9 @@ async def get_chat_info(self, chat_id):
return {"id": chat_id, "type": "dm"}


def _event(thread_id=None):
def _event(thread_id=None, *, platform=Platform.TELEGRAM, reply_to_message_id=None):
source = SessionSource(
platform=Platform.TELEGRAM,
platform=platform,
chat_id="chat-1",
chat_type="dm",
thread_id=thread_id,
Expand All @@ -47,6 +47,7 @@ def _event(thread_id=None):
message_type=MessageType.TEXT,
source=source,
message_id="msg-1",
reply_to_message_id=reply_to_message_id,
)


Expand Down Expand Up @@ -121,6 +122,27 @@ async def test_base_adapter_routes_voice_tagged_telegram_ogg_media_tag_to_voice_
adapter.send_document.assert_not_awaited()


@pytest.mark.asyncio
async def test_base_adapter_preserves_feishu_thread_reply_anchor_for_image_media(tmp_path, monkeypatch):
adapter = _MediaRoutingAdapter(platform=Platform.FEISHU)
event = _event(
thread_id="omt-thread",
platform=Platform.FEISHU,
reply_to_message_id="om-parent",
)
media_file = _allowed_media_path(tmp_path, monkeypatch, "capture.png")
adapter._message_handler = AsyncMock(return_value=f"MEDIA:{media_file}")
adapter.send_multiple_images = AsyncMock(return_value=None)

await adapter._process_message_background(event, build_session_key(event.source))

adapter.send_multiple_images.assert_awaited_once()
assert adapter.send_multiple_images.await_args.kwargs["metadata"] == {
"thread_id": "omt-thread",
"reply_to_message_id": "om-parent",
}


def _fake_runner(thread_meta):
"""Build a fake GatewayRunner-like object with the helper methods needed by
_deliver_media_from_response."""
Expand All @@ -131,6 +153,40 @@ def _fake_runner(thread_meta):
return runner


@pytest.mark.asyncio
async def test_streaming_delivery_preserves_feishu_thread_reply_anchor_for_image_media(tmp_path, monkeypatch):
event = _event(
thread_id="omt-thread",
platform=Platform.FEISHU,
reply_to_message_id="om-parent",
)
media_file = _allowed_media_path(tmp_path, monkeypatch, "capture.png")
adapter = SimpleNamespace(
name="feishu",
extract_media=BasePlatformAdapter.extract_media,
extract_images=BasePlatformAdapter.extract_images,
extract_local_files=BasePlatformAdapter.extract_local_files,
send_multiple_images=AsyncMock(return_value=None),
send_voice=AsyncMock(return_value=SendResult(success=True, message_id="voice")),
send_document=AsyncMock(return_value=SendResult(success=True, message_id="doc")),
send_image_file=AsyncMock(return_value=SendResult(success=True, message_id="image")),
send_video=AsyncMock(return_value=SendResult(success=True, message_id="video")),
)

await GatewayRunner._deliver_media_from_response(
GatewayRunner.__new__(GatewayRunner),
f"MEDIA:{media_file}",
event,
adapter,
)

adapter.send_multiple_images.assert_awaited_once()
assert adapter.send_multiple_images.await_args.kwargs["metadata"] == {
"thread_id": "omt-thread",
"reply_to_message_id": "om-parent",
}


@pytest.mark.asyncio
async def test_streaming_delivery_routes_telegram_flac_media_tag_to_document_sender(tmp_path, monkeypatch):
event = _event(thread_id="topic-1")
Expand Down
Loading