fix(telegram): preserve DM topic routing via reply fallback

This commit is contained in:
Jhin Lee 2026-05-08 21:33:20 -04:00 committed by kshitij
parent 28b5bd7e93
commit b3239572f0
6 changed files with 1331 additions and 152 deletions

View file

@ -108,6 +108,38 @@ class TestHandleBackgroundCommand:
assert "Summarize the top HN stories" in result
assert len(created_tasks) == 1 # background task was created
@pytest.mark.asyncio
async def test_telegram_dm_topic_passes_trigger_anchor_to_task(self):
"""Telegram private-topic completion sends need the original command message id."""
runner = _make_runner()
runner._run_background_task = AsyncMock()
def capture_task(coro, *args, **kwargs):
coro.close()
mock_task = MagicMock()
return mock_task
source = SessionSource(
platform=Platform.TELEGRAM,
user_id="12345",
chat_id="67890",
chat_type="dm",
thread_id="20197",
)
event = MessageEvent(
text="/background summarize",
source=source,
message_id="463",
reply_to_message_id="462",
)
with patch("gateway.run.asyncio.create_task", side_effect=capture_task):
result = await runner._handle_background_command(event)
assert "Background task started" in result
runner._run_background_task.assert_called_once()
assert runner._run_background_task.call_args.kwargs["event_message_id"] == "463"
@pytest.mark.asyncio
async def test_prompt_truncated_in_preview(self):
"""Long prompts are truncated to 60 chars in the confirmation message."""
@ -236,6 +268,57 @@ class TestRunBackgroundTask:
mock_agent_instance.shutdown_memory_provider.assert_called_once()
mock_agent_instance.close.assert_called_once()
@pytest.mark.asyncio
async def test_telegram_dm_topic_completion_preserves_reply_anchor_metadata(self, monkeypatch):
"""Background completion metadata must let Telegram send thread id plus reply id."""
from gateway import run as gateway_run
runner = _make_runner()
runner._resolve_session_agent_runtime = MagicMock(
return_value=("test-model", {"api_key": "test-key"})
)
runner._resolve_session_reasoning_config = MagicMock(return_value=None)
runner._load_service_tier = MagicMock(return_value=None)
runner._resolve_turn_agent_config = MagicMock(
return_value={
"model": "test-model",
"runtime": {"api_key": "test-key"},
"request_overrides": None,
}
)
runner._run_in_executor_with_context = AsyncMock(
return_value={"final_response": "done", "messages": []}
)
monkeypatch.setattr(gateway_run, "_load_gateway_config", lambda: {})
mock_adapter = AsyncMock()
mock_adapter.send = AsyncMock()
mock_adapter.extract_media = MagicMock(return_value=([], "done"))
mock_adapter.extract_images = MagicMock(return_value=([], "done"))
runner.adapters[Platform.TELEGRAM] = mock_adapter
source = SessionSource(
platform=Platform.TELEGRAM,
user_id="12345",
chat_id="67890",
chat_type="dm",
thread_id="20197",
)
await runner._run_background_task(
"say hello",
source,
"bg_test",
event_message_id="463",
)
mock_adapter.send.assert_called_once()
assert mock_adapter.send.call_args.kwargs["metadata"] == {
"thread_id": "20197",
"telegram_dm_topic_reply_fallback": True,
"telegram_reply_to_message_id": "463",
}
@pytest.mark.asyncio
async def test_agent_cleanup_runs_when_background_agent_raises(self):
"""Temporary background agents must be cleaned up on error paths too."""