feat(health): recent XMPP conversation log panel + stale error fix

User requirement: health tab should show recent XMPP conversations.
- bot hooks log_xmpp on inbound (on_msg) and outbound (_deliver_loop)
  so real chats land in xmpp_messages.jsonl (was: only cron/scanner)
- index.html health tab: new '最近对话' panel (last 10 msgs, dir arrow,
  preview, status, time); refreshHealth updates it incrementally
- last_error now shows age and resolved state: once a successful
  outbound happens after an error, it's shown gray as '已恢复'
  instead of alarming red forever; unresolved errors still red
- health() status no longer degraded by errors that were later
  resolved by successful outbound
This commit is contained in:
hmo
2026-07-20 00:07:28 +08:00
parent cb334ddd54
commit 058c42ce27
4 changed files with 95 additions and 6 deletions
+11
View File
@@ -147,6 +147,14 @@ _inbound_lock = threading.Lock()
RECENT_SENT_MAX = 50
# ── XMPP 消息日志(dashboard 健康Tab「最近对话」数据源)──
try:
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..'))
from xmpp_logger import log_xmpp as _log_xmpp
except Exception:
def _log_xmpp(*a, **kw):
pass
def _rs(p):
"""Parse agent arg from sys.argv, returns agent name string."""
@@ -283,6 +291,7 @@ class XmppAgent(slixmpp.ClientXMPP):
log.info(f"📩 收到图片(URL body): from={msg['from']} url={body[:80]}")
body = f"[IMAGE] {body}"
log.info(f"📩 收到: from={msg['from']} type={msg['type']} body={body[:60]}")
_log_xmpp('in', sender_str := str(msg['from']), f"{AGENT_NAME}@yoin.fun", body)
if ('[executor]' in body and 'gateway_zhiwei' in body):
log.info(f"过滤 executor 消息: {body[:80]}...")
return
@@ -322,8 +331,10 @@ def _deliver_loop(bot):
bot.send_message(mto=to, mbody=body, mtype=mtype)
asyncio.run(_send(target, text, msg_type))
bot.mark_sent(text)
_log_xmpp('out', f"{AGENT_NAME}@yoin.fun", target, text)
log.info(f" 已发送到 {target}: {text[:80]}")
except Exception as e:
_log_xmpp('out', f"{AGENT_NAME}@yoin.fun", target, text, status='error', error=str(e)[:150])
log.error(f" 发送到 {target} 失败: {e}")
time.sleep(0.3)
except Exception as e: