diff --git a/apps/api/src/services/telegram_gateway.py b/apps/api/src/services/telegram_gateway.py index d7544c30..304b8cf6 100644 --- a/apps/api/src/services/telegram_gateway.py +++ b/apps/api/src/services/telegram_gateway.py @@ -1860,6 +1860,8 @@ class TelegramGateway: nemotron_validation=nemotron_validation, nemotron_latency_ms=nemotron_latency_ms, incident_id=incident_id, + alert_category=alert_category, + notification_type=notification_type, ) ) @@ -1893,6 +1895,8 @@ class TelegramGateway: nemotron_validation: str = "", nemotron_latency_ms: float = 0.0, incident_id: str = "", + alert_category: str = "", + notification_type: str = "", ) -> None: """ 發送告警卡片到 SRE 群組 — 與個人 chat 相同的完整 v7.0 格式 @@ -1940,7 +1944,16 @@ class TelegramGateway: nemotron_latency_ms=nemotron_latency_ms, ) text = message.format_with_nemotron() if nemotron_enabled else message.format() - resp = await self.send_to_group(text=text) + + # 2026-04-25 ogt + Claude Sonnet 4.6: 群組卡片使用完整 _build_inline_keyboard + # 統帥決策: 群組成員為受信任 SRE,完整批准/拒絕/暫默/詳情/重診/歷史按鈕從 DM 移植至群組 + _group_keyboard = self._build_inline_keyboard( + approval_id=approval_id, + incident_id=incident_id, + alert_category=alert_category, + notification_type=notification_type, + ) + resp = await self.send_to_group(text=text, reply_markup=_group_keyboard) # 2026-04-10 Claude Sonnet 4.6: 儲存 message_id 到 Redis,供 append_incident_update 使用 # tg_msg:{incident_id} → Telegram message_id (TTL 24h) @@ -1967,10 +1980,13 @@ class TelegramGateway: severity: str = "info", ) -> dict: """ - TYPE-1 純資訊通知 — 無按鈕,FYI 類告警 + TYPE-1 純資訊通知 — FYI 類告警 用於: severity=info 成功類 / Backup 完成 / AlertChainHealthy 等 - 格式: 簡潔文字,無 InlineKeyboard + 格式: 簡潔文字 + [詳情][歷史] 查類按鈕(read-only,2-part info 格式,ADR-050) + + 2026-04-25 ogt + Claude Sonnet 4.6: 補充 read-only 按鈕(鬼魂按鈕鐵律: + detail/history 已有 handler 且無副作用,符合三條件才加) Args: incident_id: 事件 ID @@ -1987,16 +2003,23 @@ class TelegramGateway: ) if alertname: text += f"🔔 告警: {html.escape(alertname)}\n" - text += ( - f"\n{html.escape(message)}\n" - f"\n此為純資訊通知,無需操作。" - ) + text += f"\n{html.escape(message)}" + + # read-only 查類按鈕(2-part info 格式,handler 已在 handle_callback 實作) + # detail/history 均在 INFO_ACTIONS 白名單,無 nonce 無副作用 + keyboard = { + "inline_keyboard": [[ + {"text": "📋 詳情", "callback_data": f"detail:{incident_id}"}, + {"text": "📊 歷史", "callback_data": f"history:{incident_id}"}, + ]] + } return await self._send_request( "sendMessage", { "chat_id": settings.OPENCLAW_TG_CHAT_ID, "text": text, "parse_mode": "HTML", + "reply_markup": keyboard, }, )