feat: auto-heal pipeline — detect+restart gateway/bot/ejabberd on failure

This commit is contained in:
hmo
2026-07-19 14:18:45 +08:00
parent 0802046d5c
commit 6398f595b2
2 changed files with 58 additions and 0 deletions
+14
View File
@@ -1315,6 +1315,20 @@ def api_xmpp_stats():
return jsonify({"today": {"sent": 0, "failed": 0, "latency_avg": 0}, "week": {"sent": 0, "failed": 0}})
@app.route("/api/xmpp/autoheal", methods=["GET", "POST"])
def api_xmpp_autoheal():
"""自愈:检测异常并自动修复。GET=查看状态, POST=执行修复"""
try:
from xmpp_logger import auto_heal
if request.method == "POST":
result = auto_heal()
return jsonify(result)
else:
return jsonify({"usage": "POST to trigger auto-heal"})
except ImportError:
return jsonify({"error": "xmpp_logger not available"}), 500
# 注册提示词管理路由
register_routes(app)
+44
View File
@@ -9,6 +9,7 @@
"""
import json
import time as _time
import subprocess as _sp
from pathlib import Path
from datetime import datetime, timedelta
@@ -230,3 +231,46 @@ def health():
elif la > 0: result["status"] = "ok"
return result
def auto_heal():
"""自愈:检测并尝试修复 XMPP 通信问题。"""
h = health()
actions = []
# 1. LLM Provider 超时 → 重启 Hermes Gateway
if h.get("llm_provider", {}).get("status") in ("timeout", "error"):
gw = h.get("gateways", {}).get("zhiwei", {})
if gw.get("alive"):
try:
r = _sp.run(["sudo", "-n", "systemctl", "restart", "hermes-gw-pa"],
capture_output=True, timeout=30, text=True)
ok = r.returncode == 0
actions.append({"action": "restart_hermes_gateway", "target": "position-analyst",
"success": ok, "detail": "restarted" if ok else r.stderr[:100]})
except Exception as e:
actions.append({"action": "restart_hermes_gateway", "target": "position-analyst",
"success": False, "detail": str(e)[:100]})
# 2. Bot 无出站 → 重启知微 Bot
ba = h.get("bot_activity", {})
if ba.get("inbound", 0) > 0 and ba.get("outbound", 0) == 0 and ba.get("errors", 0) > 0:
try:
r = _sp.run(["sudo", "-n", "systemctl", "restart", "xmpp-zhiwei"], capture_output=True, timeout=30, text=True)
actions.append({"action": "restart_zhiwei_bot", "target": "xmpp-zhiwei",
"success": r.returncode == 0, "detail": "restarted" if r.returncode == 0 else r.stderr[:100]})
except Exception as e:
actions.append({"action": "restart_zhiwei_bot", "target": "xmpp-zhiwei",
"success": False, "detail": str(e)[:100]})
# 3. ejabberd → 重启容器
if h.get("ejabberd", "") and "Up" not in str(h["ejabberd"]):
try:
r = _sp.run(["sudo", "-n", "docker", "restart", "ejabberd"], capture_output=True, timeout=30, text=True)
actions.append({"action": "restart_ejabberd", "target": "ejabberd",
"success": r.returncode == 0, "detail": "restarted" if r.returncode == 0 else r.stderr[:100]})
except Exception as e:
actions.append({"action": "restart_ejabberd", "target": "ejabberd",
"success": False, "detail": str(e)[:100]})
return {"actions": actions, "status": h.get("status", "unknown")}