ForcePilot/backend/package/yuxi/channel/extensions/jira/loopbreaker.py
Kris c5d8e3550e feat(channel): 添加 Jira 渠道扩展
新增 Jira 渠道扩展,支持在 Yuxi 平台中集成 Jira 项目管理渠道。

包含以下功能模块:
- config: 渠道配置管理
- gateway: SSE/WebSocket 网关接入
- outbound: 外发消息与工单管理
- streaming: 流式消息处理
- parse: Jira 内容解析
- format: 消息格式转换
- agent_tools: Agent 工具集成
- security: 安全校验
- dedupe: 消息去重
- loopbreaker: 循环响应防护
- monitor: 渠道状态监控
- status: 会话与工单状态管理
- types: 类型定义
2026-05-21 11:10:54 +08:00

43 lines
1.3 KiB
Python

from __future__ import annotations
import logging
import time
from collections import defaultdict
logger = logging.getLogger(__name__)
class JiraLoopBreaker:
def __init__(self, max_comments_per_issue_per_minute: int = 8):
self._counters: dict[str, list[float]] = defaultdict(list)
self._max = max_comments_per_issue_per_minute
self._tripped: dict[str, float] = {}
def record_and_check(self, issue_key: str) -> bool:
now = time.monotonic()
window = [t for t in self._counters.get(issue_key, []) if now - t < 60]
if len(window) >= self._max:
self._tripped[issue_key] = now
logger.warning(
"Jira loop breaker tripped for issue=%s, comments=%d",
issue_key,
len(window),
)
return False
window.append(now)
self._counters[issue_key] = window
return True
def is_tripped(self, issue_key: str) -> bool:
now = time.monotonic()
trip_time = self._tripped.get(issue_key)
if trip_time and now - trip_time < 300:
return True
if trip_time and now - trip_time >= 300:
del self._tripped[issue_key]
return False
def reset_issue(self, issue_key: str):
self._counters.pop(issue_key, None)
self._tripped.pop(issue_key, None)