From 2df49458801ad1ade85a39009ce0e5bb8de7f874 Mon Sep 17 00:00:00 2001 From: OG T Date: Tue, 14 Apr 2026 13:23:41 +0800 Subject: [PATCH] =?UTF-8?q?fix(auto-repair):=20=E4=B8=AD=E4=BD=8E=E9=A2=A8?= =?UTF-8?q?=E9=9A=AA+=E7=84=A1kubectl=5Fcommand=20=E2=86=92=20TYPE-1=20?= =?UTF-8?q?=E7=B4=94=E8=B3=87=E8=A8=8A=EF=BC=8C=E4=B8=8D=E9=A1=AF=E7=A4=BA?= =?UTF-8?q?=E5=AF=A9=E6=A0=B8=E6=8C=89=E9=88=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 問題: HostHighCpuLoad 等主機層告警 affected_services=[] → OpenClaw 生成 kubectl unknown → safety guard 攔截 → 退回 READY + TYPE-3 帶按鈕卡片 用戶一直看到帶按鈕的中/低風險告警,按鈕無法修復任何東西 修復三處: 1. openclaw.py: _call_openclaw_analyze() 回傳 suggested_action 欄位 + target_resource 預設改為 "" (避免 "unknown" 進入 safety guard) 2. decision_manager.py: classify_notification() 傳入 suggested_action / risk_level / has_kubectl_command 3. telegram_gateway.py: classify_notification() 新規則 — 無 kubectl_command + risk=low/medium + action=investigate/no_action → TYPE-1 (純資訊,無按鈕) 搭配 clawbot-v5 f4b84d7 (OpenClaw prompt CRITICAL RULES) 一起生效 2026-04-14 Claude Sonnet 4.6 Asia/Taipei Co-Authored-By: Claude Sonnet 4.6 --- apps/api/src/services/decision_manager.py | 6 ++++++ apps/api/src/services/openclaw.py | 3 ++- apps/api/src/services/telegram_gateway.py | 11 +++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/apps/api/src/services/decision_manager.py b/apps/api/src/services/decision_manager.py index fe7ac1af5..60b5e58c5 100644 --- a/apps/api/src/services/decision_manager.py +++ b/apps/api/src/services/decision_manager.py @@ -225,12 +225,18 @@ async def _push_decision_to_telegram( _auto_executed = proposal_data.get("auto_executed", False) _decision_state = proposal_data.get("decision_state", "") _mcp_all_failed = proposal_data.get("mcp_all_failed", False) + _suggested_action_for_classify = proposal_data.get("suggested_action", "") + _risk_level_for_classify = proposal_data.get("risk_level", "medium") + _has_kubectl = bool(proposal_data.get("kubectl_command", "")) _notif_type = classify_notification( incident=incident, confidence=confidence, auto_executed=_auto_executed, mcp_all_failed=_mcp_all_failed, decision_state=_decision_state, + suggested_action=_suggested_action_for_classify, + risk_level=_risk_level_for_classify, + has_kubectl_command=_has_kubectl, ) # 2026-04-12 ogt: ADR-075 — 從 Incident 提取 alert_category/notification_type(各分支共用) diff --git a/apps/api/src/services/openclaw.py b/apps/api/src/services/openclaw.py index 5ef58e18f..aea3cad86 100644 --- a/apps/api/src/services/openclaw.py +++ b/apps/api/src/services/openclaw.py @@ -367,7 +367,8 @@ class OpenClawService: "action": data.get("action_title", "AI 分析"), "description": data.get("description", ""), "kubectl_command": data.get("kubectl_command") or "", - "target_resource": data.get("target_resource", "unknown"), + "suggested_action": data.get("suggested_action", ""), + "target_resource": data.get("target_resource") or "", "namespace": data.get("namespace", "awoooi-prod"), "risk_level": data.get("risk_level", "medium"), "reasoning": data.get("reasoning", ""), diff --git a/apps/api/src/services/telegram_gateway.py b/apps/api/src/services/telegram_gateway.py index d987e9269..5de266141 100644 --- a/apps/api/src/services/telegram_gateway.py +++ b/apps/api/src/services/telegram_gateway.py @@ -1133,6 +1133,9 @@ def classify_notification( auto_executed: bool, mcp_all_failed: bool = False, decision_state: str = "", + suggested_action: str = "", + risk_level: str = "", + has_kubectl_command: bool = True, ) -> NotificationType: """ 告警通知分類器 — 決定要送哪種類型的 Telegram 卡片 @@ -1188,6 +1191,14 @@ def classify_notification( if confidence < 0.5 or mcp_all_failed or decision_state == "ERROR": return NotificationType.TYPE_4 + # TYPE-1:無 kubectl 動作 + 低/中風險 → 純資訊通知(無按鈕) + # 場景:主機層告警 suggested_action=investigate,LLM 無法生成有效 kubectl 指令 + # 2026-04-14 ogt (ADR-075): 中/低風險 + 無 kubectl_command → 不應發帶按鈕卡片 + if (not has_kubectl_command + and risk_level in ("low", "medium") + and suggested_action in ("investigate", "no_action", "alert_team", "")): + return NotificationType.TYPE_1 + # TYPE-3:預設(需人工審核) return NotificationType.TYPE_3