88 lines
3.2 KiB
Python
88 lines
3.2 KiB
Python
"""诊断微信对话里 wechat_push 发文件失败:dump 绑定状态 + 微信 task 里 wechat_push 工具调用与返回。
|
|
|
|
ASCII 标签(Windows GBK 安全)。用法:.venv/Scripts/python.exe scripts/diag_wechat_push.py [email]
|
|
"""
|
|
import json
|
|
import os
|
|
import sys
|
|
from datetime import datetime, timezone
|
|
from pathlib import Path
|
|
|
|
env = Path(__file__).resolve().parent.parent / ".env"
|
|
for line in env.read_text(encoding="utf-8").splitlines():
|
|
if line.strip().startswith("ZCBOT_DB_URL="):
|
|
os.environ["ZCBOT_DB_URL"] = line.split("=", 1)[1].strip()
|
|
|
|
from sqlalchemy import create_engine, text # noqa: E402
|
|
import builtins # noqa: E402
|
|
|
|
_out = open(Path(__file__).resolve().parent / "_wechat_push_dump.txt", "w", encoding="utf-8")
|
|
|
|
|
|
def print(*a, **k): # noqa: A001
|
|
builtins.print(*a, **k, file=_out)
|
|
|
|
|
|
engine = create_engine(os.environ["ZCBOT_DB_URL"])
|
|
email = sys.argv[1] if len(sys.argv) > 1 else "caoqianming@foxmail.com"
|
|
|
|
|
|
def s(x, n=2000):
|
|
t = str(x or "")
|
|
return t if len(t) <= n else t[:n] + f"...[+{len(t)-n}]"
|
|
|
|
|
|
with engine.connect() as conn:
|
|
row = conn.execute(text("select user_id from users where email=:e"), {"e": email}).fetchone()
|
|
if not row:
|
|
print("[NO USER]", email); sys.exit(1)
|
|
uid = row[0]
|
|
print("[USER]", uid)
|
|
|
|
b = conn.execute(text(
|
|
"select user_im_id, base_url, status, context_token_at, "
|
|
"(latest_context_token is not null) as has_ctx, chat_task_id "
|
|
"from wechat_bot_bindings where user_id=:u"), {"u": uid}).fetchone()
|
|
if not b:
|
|
print("[NO BINDING]"); sys.exit(1)
|
|
print("[BINDING] status=%s user_im_id=%s has_ctx=%s ctx_at=%s base=%s" % (
|
|
b.status, b.user_im_id, b.has_ctx, b.context_token_at, b.base_url))
|
|
print("[BINDING] chat_task_id=%s" % b.chat_task_id)
|
|
if b.context_token_at:
|
|
at = b.context_token_at
|
|
if at.tzinfo is None:
|
|
at = at.replace(tzinfo=timezone.utc)
|
|
age = datetime.now(timezone.utc) - at
|
|
print("[BINDING] ctx age = %s (fresh if <24h)" % age)
|
|
|
|
tid = b.chat_task_id
|
|
if not tid:
|
|
print("[NO CHAT TASK]"); sys.exit(0)
|
|
|
|
# dump messages, focus on wechat_push tool calls/results
|
|
rows = conn.execute(text(
|
|
"select idx, payload from messages where task_id=:t order by idx desc limit 60"),
|
|
{"t": tid}).fetchall()
|
|
print("\n[MESSAGES] last %d (newest first):" % len(rows))
|
|
for idx, payload in rows:
|
|
if isinstance(payload, str):
|
|
try:
|
|
payload = json.loads(payload)
|
|
except Exception:
|
|
pass
|
|
if not isinstance(payload, dict):
|
|
continue
|
|
role = payload.get("role")
|
|
# assistant tool_calls
|
|
tcs = payload.get("tool_calls") or []
|
|
for tc in tcs:
|
|
fn = (tc.get("function") or {})
|
|
if fn.get("name") == "wechat_push":
|
|
print(" #%s [CALL wechat_push] args=%s" % (idx, s(fn.get("arguments"), 800)))
|
|
# tool result
|
|
if role == "tool":
|
|
name = payload.get("name", "")
|
|
content = payload.get("content")
|
|
if name == "wechat_push" or "微信" in s(content, 200) or "wechat" in s(name):
|
|
print(" #%s [TOOL RESULT %s] %s" % (idx, name, s(content, 800)))
|