mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
Prevent Telegram polling handoffs and flood-control send failures
Telegram polling can inherit a stale webhook registration when a deployment switches transport modes, which leaves getUpdates idle even though the gateway starts cleanly. Outbound send also treats Telegram retry_after responses as terminal errors, so brief flood control can drop tool progress and replies. Constraint: Keep the PR narrowly scoped to upstream/main Telegram adapter behavior Rejected: Port OpenClaw's broader polling supervisor and offset persistence | too broad for an isolated fix PR Confidence: high Scope-risk: narrow Reversibility: clean Directive: Polling mode should clear webhook state before starting getUpdates, and send-path retry logic must distinguish flood control from timeouts Tested: uv run --extra dev pytest tests/gateway/test_telegram_* -q Not-tested: Live Telegram webhook-to-polling migration and real Bot API 429 behavior
This commit is contained in:
parent
74ff62f5ac
commit
1d2e34c7eb
3 changed files with 96 additions and 3 deletions
|
|
@ -37,6 +37,12 @@ class FakeTimedOut(FakeNetworkError):
|
|||
pass
|
||||
|
||||
|
||||
class FakeRetryAfter(Exception):
|
||||
def __init__(self, seconds):
|
||||
super().__init__(f"Retry after {seconds}")
|
||||
self.retry_after = seconds
|
||||
|
||||
|
||||
# Build a fake telegram module tree so the adapter's internal imports work
|
||||
_fake_telegram = types.ModuleType("telegram")
|
||||
_fake_telegram_error = types.ModuleType("telegram.error")
|
||||
|
|
@ -230,3 +236,25 @@ async def test_thread_fallback_only_fires_once():
|
|||
# Second chunk: should use thread_id=None directly (effective_thread_id
|
||||
# was cleared per-chunk but the metadata doesn't change between chunks)
|
||||
# The key point: the message was delivered despite the invalid thread
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_send_retries_retry_after_errors():
|
||||
"""Telegram flood control should back off and retry instead of failing fast."""
|
||||
adapter = _make_adapter()
|
||||
|
||||
attempt = [0]
|
||||
|
||||
async def mock_send_message(**kwargs):
|
||||
attempt[0] += 1
|
||||
if attempt[0] == 1:
|
||||
raise FakeRetryAfter(2)
|
||||
return SimpleNamespace(message_id=300)
|
||||
|
||||
adapter._bot = SimpleNamespace(send_message=mock_send_message)
|
||||
|
||||
result = await adapter.send(chat_id="123", content="test message")
|
||||
|
||||
assert result.success is True
|
||||
assert result.message_id == "300"
|
||||
assert attempt[0] == 2
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue