fix(telegram): 修復建議指令被截斷 + decision_manager enum string 補正
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled

根因 1: telegram_gateway.py suggested_action[:35] 剛好截到 deployment/ 後
  → 改為 [:80],完整顯示 kubectl command

根因 2: 舊 Incident proposal_data 存 enum string (RESTART_DEPLOYMENT)
  → decision_manager.py 加入偵測,用規則引擎重新查 kubectl command

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OG T
2026-04-09 11:14:30 +08:00
parent f51ef5e089
commit c5e475121a
2 changed files with 24 additions and 2 deletions

View File

@@ -105,6 +105,28 @@ async def _push_decision_to_telegram(
target = incident.affected_services[0] if incident.affected_services else "unknown" target = incident.affected_services[0] if incident.affected_services else "unknown"
risk_level = proposal_data.get("risk_level", "medium") risk_level = proposal_data.get("risk_level", "medium")
action = _strip_placeholders(proposal_data.get("action", proposal_data.get("kubectl_command", ""))) action = _strip_placeholders(proposal_data.get("action", proposal_data.get("kubectl_command", "")))
# 2026-04-09 Claude Code: 修復舊 Incident proposal_data 存 enum string 導致建議空白
# 舊 code 存 action="RESTART_DEPLOYMENT" 而非 kubectl command
# 偵測:無 kubectl/ssh/docker 關鍵字 → 用規則引擎重新查
_KUBECTL_MARKERS = ("kubectl", "ssh", "docker", "systemctl", "/")
if action and not any(m in action for m in _KUBECTL_MARKERS):
# action 是 enum string嘗試用規則引擎補出 kubectl command
try:
from src.services.alert_rule_engine import match_rule as _match_rule
_labels = incident.signals[0].labels if incident.signals else {}
_rule_resp = _match_rule({
"labels": _labels,
"alert_type": _labels.get("alertname", target),
"message": incident.title or "",
"target_resource": target,
"namespace": incident.signals[0].labels.get("namespace", "awoooi-prod") if incident.signals else "awoooi-prod",
"severity": risk_level,
})
if _rule_resp and _rule_resp.get("kubectl_command", "").strip():
action = _rule_resp["kubectl_command"]
except Exception:
pass # 規則引擎失敗不影響通知,保留原 action
description = proposal_data.get("description", "") description = proposal_data.get("description", "")
reasoning = _strip_placeholders(proposal_data.get("reasoning", "")) reasoning = _strip_placeholders(proposal_data.get("reasoning", ""))
confidence = proposal_data.get("confidence", 0.0) # 🔴 預設 0.0 表示未經 AI 分析 confidence = proposal_data.get("confidence", 0.0) # 🔴 預設 0.0 表示未經 AI 分析

View File

@@ -221,7 +221,7 @@ class TelegramMessage:
# HTML 轉義用戶輸入內容,防止 "Can't parse entities" 錯誤 # HTML 轉義用戶輸入內容,防止 "Can't parse entities" 錯誤
safe_resource = html.escape(self.resource_name[:35]) safe_resource = html.escape(self.resource_name[:35])
safe_root_cause = html.escape(self.root_cause[:50]) safe_root_cause = html.escape(self.root_cause[:50])
safe_action = html.escape(self.suggested_action[:35]) safe_action = html.escape(self.suggested_action[:80])
safe_downtime = html.escape(self.estimated_downtime) safe_downtime = html.escape(self.estimated_downtime)
# 2026-03-29 ogt: AI Token/Cost 顯示 # 2026-03-29 ogt: AI Token/Cost 顯示
@@ -372,7 +372,7 @@ class TelegramMessage:
# HTML 轉義 # HTML 轉義
safe_resource = html.escape(self.resource_name[:35]) safe_resource = html.escape(self.resource_name[:35])
safe_root_cause = html.escape(self.root_cause[:50]) safe_root_cause = html.escape(self.root_cause[:50])
safe_action = html.escape(self.suggested_action[:35]) safe_action = html.escape(self.suggested_action[:80])
safe_downtime = html.escape(self.estimated_downtime) safe_downtime = html.escape(self.estimated_downtime)
# AI Provider 顯示 # AI Provider 顯示