From 1f6ea00c731541d6a18e96c51e29876de8c14033 Mon Sep 17 00:00:00 2001 From: ogt Date: Fri, 10 Jul 2026 09:25:54 +0800 Subject: [PATCH] fix(agent99): mirror telegram sendmessage alerts --- apps/api/src/services/telegram_gateway.py | 12 ++-- .../tests/test_telegram_message_templates.py | 59 +++++++++++++++++++ 2 files changed, 63 insertions(+), 8 deletions(-) diff --git a/apps/api/src/services/telegram_gateway.py b/apps/api/src/services/telegram_gateway.py index 3ab6574bf..a544dabc1 100644 --- a/apps/api/src/services/telegram_gateway.py +++ b/apps/api/src/services/telegram_gateway.py @@ -4936,6 +4936,10 @@ class TelegramGateway: payload = normalize_telegram_send_message_payload(method, payload) source_envelope_extra = payload.pop(_AWOOOP_SOURCE_ENVELOPE_EXTRA_KEY, None) await self._attach_incident_thread_reply(method, payload) + _schedule_agent99_ai_alert_card_mirror( + str(payload.get("text") or payload.get("caption") or ""), + source="send_request", + ) url = f"{self.api_url}/{method}" @@ -9340,10 +9344,6 @@ class TelegramGateway: reply_markup_present=bool(reply_markup), ) ) - _schedule_agent99_ai_alert_card_mirror( - payload["text"], - source="send_alert_notification", - ) return await self._send_request("sendMessage", payload) # ========================================================================= @@ -9383,10 +9383,6 @@ class TelegramGateway: "parse_mode": effective_parse_mode, "disable_web_page_preview": disable_web_page_preview, } - _schedule_agent99_ai_alert_card_mirror( - payload["text"], - source="send_text", - ) return await self._send_request("sendMessage", payload) async def send_controlled_apply_result_receipt( diff --git a/apps/api/tests/test_telegram_message_templates.py b/apps/api/tests/test_telegram_message_templates.py index 0d2e2316c..94d1bca4d 100644 --- a/apps/api/tests/test_telegram_message_templates.py +++ b/apps/api/tests/test_telegram_message_templates.py @@ -5,6 +5,8 @@ test_telegram_message_templates.py - Telegram 訊息模板測試 符合 feedback_no_mock_testing.md 規範 - 測試實際格式化輸出 """ +import asyncio + import pytest import src.services.telegram_gateway as telegram_gateway_module @@ -462,6 +464,63 @@ def test_send_request_payload_normalizer_blocks_direct_host_raw_dump() -> None: assert '"product":"prisma"' not in result["text"] +@pytest.mark.asyncio +async def test_send_request_mirrors_direct_ai_alert_card_to_agent99(monkeypatch) -> None: + """direct sendMessage AI cards must reach Agent99 even without wrapper helpers.""" + mirrored: list[dict[str, str]] = [] + gateway = TelegramGateway() + gateway._initialized = True + + class FakeResponse: + def raise_for_status(self) -> None: + return None + + def json(self) -> dict: + return {"ok": True, "result": True} + + class FakeHttpClient: + async def post(self, url, json): # type: ignore[no-untyped-def] + return FakeResponse() + + async def fake_mirror(text: str, *, source: str = "telegram_gateway") -> str: + mirrored.append({"text": text, "source": source}) + return "mirrored" + + monkeypatch.setattr(TelegramGateway, "api_url", property(lambda _self: "https://telegram.test/botx")) + monkeypatch.setattr( + telegram_gateway_module, + "_agent99_ai_alert_card_mirror_configured", + lambda: True, + ) + monkeypatch.setattr( + telegram_gateway_module, + "_mirror_ai_automation_alert_card_to_agent99", + fake_mirror, + ) + gateway._http_client = FakeHttpClient() + + result = await gateway._send_request( + "sendMessage", + { + "chat_id": "chat", + "text": ( + "SourceProviderIngestionStale provider_freshness_signal freshness " + "window timeout Sentry SigNoz provider freshness last seen missing " + "direct ref verifier readback" + ), + "parse_mode": "MarkdownV2", + }, + ) + await asyncio.sleep(0) + + assert result == {"ok": True, "result": True} + assert mirrored + assert mirrored[0]["source"] == "send_request" + assert "ai_automation_alert_card_v1" in mirrored[0]["text"] + assert "provider_freshness_signal" in mirrored[0]["text"] + assert "runtime_write_gate=controlled" in mirrored[0]["text"] + + def test_weekly_report_marks_all_zero_as_low_trust_anomaly() -> None: report = WeeklyReportMessage( week_range="2026-W24",