diff --git a/apps/api/src/agents/diagnostician_agent.py b/apps/api/src/agents/diagnostician_agent.py index 15367e13..aed2f8b2 100644 --- a/apps/api/src/agents/diagnostician_agent.py +++ b/apps/api/src/agents/diagnostician_agent.py @@ -202,7 +202,35 @@ Phase 4 動態異常偵測(AI 主動巡檢結果,可作為高信心佐證) # ───────────────────────────────────────────────────────────────────────────── def _extract_hypotheses(parsed: dict[str, Any]) -> list[Hypothesis]: - """從 LLM 解析結果提取假設列表(按信心降序)。""" + """從 LLM 解析結果提取假設列表(按信心降序)。 + + 支援兩種格式: + 1. 標準格式:{"hypotheses": [{description, confidence, evidence_chain, category}]} + 2. OpenClaw Nemo 格式:{"action_title": "...", "risk_level": "...", "confidence": 0.85} + (openclaw_nemo 呼叫 ClawBot /api/v1/analyze/incident 回傳) + + 2026-04-16 ogt + Claude Sonnet 4.6: 修復 openclaw_nemo 格式不相容 + 根因: ai_router DIAGNOSE→openclaw_nemo 回傳 action_title 格式, + diagnostician 只解析 hypotheses 格式 → 永遠 0 hypotheses → ABSTAIN + """ + # OpenClaw Nemo 格式轉換(有 action_title 但無 hypotheses) + if "action_title" in parsed and "hypotheses" not in parsed: + action_title = str(parsed.get("action_title", "")) + confidence = float(parsed.get("confidence", 0.5)) + risk_level = str(parsed.get("risk_level", "medium")) + # risk_level → category 映射 + risk_to_cat = {"critical": "CriticalFailure", "high": "HighRisk", + "medium": "ModerateIssue", "low": "LowRisk"} + category = risk_to_cat.get(risk_level.lower(), "Unknown") + if action_title and confidence > 0: + return [Hypothesis( + description=action_title[:500], + confidence=confidence, + evidence_chain=[], + category=category, + )] + return [] + raw = parsed.get("hypotheses", []) hypotheses = [] for item in raw: