From a07daf7e3f7f09cf6d825684631bc51b635693ff Mon Sep 17 00:00:00 2001 From: OG T Date: Thu, 16 Apr 2026 02:21:53 +0800 Subject: [PATCH] =?UTF-8?q?fix(incidents):=20GET=20/incidents=20=E5=8A=A0?= =?UTF-8?q?=2048h=20age=20filter=EF=BC=8C=E9=98=BB=E6=AD=A2=E8=88=8A=20inc?= =?UTF-8?q?ident=20=E5=8F=8D=E8=A6=86=E8=A7=B8=E7=99=BC=20AI=20=E5=88=86?= =?UTF-8?q?=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根本原因: DECISION_TOKEN_TTL=3600s → 舊 incident token 每小時過期 → GET /api/v1/incidents 重複觸發 get_or_create_decision → OPENCLAW_NEMO timeout → Expert System fallback (confidence=20%) → Telegram 洪水 修復: 只對 created_at 在 48h 內的 incident 觸發背景 AI 分析 48h+ 的舊 incident 不再觸發(仍顯示在列表,只是不重新分析) 2026-04-16 Claude Sonnet 4.6 Asia/Taipei Co-Authored-By: Claude Sonnet 4.6 --- apps/api/src/api/v1/incidents.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/apps/api/src/api/v1/incidents.py b/apps/api/src/api/v1/incidents.py index ed1f8ceb..bcfa11d3 100644 --- a/apps/api/src/api/v1/incidents.py +++ b/apps/api/src/api/v1/incidents.py @@ -166,10 +166,20 @@ async def list_incidents() -> IncidentListResponse: else: # 無快取 → 背景觸發,本次返回 None(前端看到 decision=null 會 poll) responses.append(IncidentResponse.from_incident(incident, None)) - timeout = 120.0 if incident.severity in (Severity.P0, Severity.P1) else 180.0 - background_tasks.append( - decision_manager.get_or_create_decision(incident=incident, timeout_sec=timeout) - ) + # 2026-04-16 Claude Sonnet 4.6: 只對 48h 內的 incident 觸發 AI 分析 + # 舊 incident token 每小時過期,若不限制會反覆重新分析歷史事件 → Telegram 洪水 + from datetime import datetime, timezone, timedelta + _created = getattr(incident, "created_at", None) + _too_old = False + if _created: + if _created.tzinfo is None: + _created = _created.replace(tzinfo=timezone.utc) + _too_old = (_created < datetime.now(timezone.utc) - timedelta(hours=48)) + if not _too_old: + timeout = 120.0 if incident.severity in (Severity.P0, Severity.P1) else 180.0 + background_tasks.append( + decision_manager.get_or_create_decision(incident=incident, timeout_sec=timeout) + ) except Exception as e: logger.warning( "decision_generation_failed",