"""判断 task 里:① tool 结果有多少带 [Error] / 失败;② 重复调用是否跟在错误后面。"""
import json
import os
import sys
from collections import Counter
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

engine = create_engine(os.environ["ZCBOT_DB_URL"])
prefix = sys.argv[1] if len(sys.argv) > 1 else "ab063233"

with engine.connect() as conn:
    tid = conn.execute(
        text("select task_id from tasks where task_id::text like :p"), {"p": prefix + "%"}
    ).fetchone()[0]
    msgs = conn.execute(
        text("select idx, payload from messages where task_id=:t order by idx"),
        {"t": tid},
    ).fetchall()

# 收集 tool 结果文本(role=tool)和它们的 name
results = {}  # idx -> (name, text)
calls = []    # (idx, name, args_fingerprint)
for idx, payload in msgs:
    role = payload.get("role")
    if role == "tool":
        results[idx] = (payload.get("name"), str(payload.get("content") or ""))
    elif role == "assistant":
        for tc in payload.get("tool_calls") or []:
            fn = tc.get("function") or {}
            try:
                args = json.loads(fn.get("arguments") or "{}")
            except Exception:
                args = {}
            fp = fn.get("name") + "|" + json.dumps(args, ensure_ascii=False, sort_keys=True)
            calls.append((idx, fn.get("name"), fp))

n_tool = len(results)
n_err = sum(1 for _, (_, t) in results.items() if "[Error" in t or "Traceback" in t or "exit 1" in t or "[stderr]" in t)
print(f"task {tid}")
print(f"tool 结果总数: {n_tool}  含错误/stderr/exit1: {n_err}  ({100*n_err/max(n_tool,1):.0f}%)\n")

# 完全同名同参指纹的重复
c = Counter(fp for _, _, fp in calls)
exactdup = [(fp, n) for fp, n in c.most_common() if n > 1]
print(f"完全同名同参(含全部参数)的调用指纹: 重复 {len(exactdup)} 种")
print("=== 同名同参重复 TOP 10(连参数都一字不差) ===")
for fp, n in c.most_common(10):
    if n > 1:
        name, _, rest = fp.partition("|")
        print(f"  {n:>3}x  {name}: {rest[:70]}")

# 错误样本
print("\n=== 前 5 条错误结果样本 ===")
shown = 0
for idx in sorted(results):
    name, t = results[idx]
    if any(k in t for k in ("[Error", "Traceback", "exit 1", "[stderr]")):
        print(f"  [{idx}] {name}: {t[:160].strip()}")
        shown += 1
        if shown >= 5:
            break
