"""Analyze AI autonomy: tool streaks between user messages, codex system prefix detection.

Key findings:
- Tool streaks: median=4, mean=10.2, max=731, p90=26
- Codex user msgs with system XML prefix: 179/726 (25%)
- Higher streak = AI working more independently

Run: /home/sagar/trace/.venv/bin/python3 analysis-14022026/session_view_scripts/research/03_autonomy_and_streaks.py
"""
import json
import os
import re
import statistics

DIR = os.path.join(os.path.dirname(__file__), "../viewer/public/data/sessions")
IDX = os.path.join(os.path.dirname(__file__), "../viewer/public/data/index.json")

with open(IDX) as f:
    index = json.load(f)

# ---- Part 1: Tool streaks between user messages ----
print("=" * 60)
print("PART 1: Tool streaks (consecutive tool_calls between user msgs)")
print("=" * 60)

streak_lengths = []
session_max_streaks = []

for dev in index["developers"].values():
    for s in dev["sessions"]:
        fpath = os.path.join(DIR, f'{s["id"]}.json')
        if not os.path.exists(fpath):
            continue
        with open(fpath) as f2:
            msgs = json.load(f2)

        current_streak = 0
        max_streak = 0
        for m in msgs:
            if m["type"] in ("tool_call", "tool_result", "assistant"):
                if m["type"] == "tool_call":
                    current_streak += 1
            elif m["type"] == "user":
                if current_streak > 0:
                    streak_lengths.append(current_streak)
                    max_streak = max(max_streak, current_streak)
                current_streak = 0
        if current_streak > 0:
            streak_lengths.append(current_streak)
            max_streak = max(max_streak, current_streak)
        if max_streak > 0:
            session_max_streaks.append(
                {"session_id": s["id"], "source": s["source"], "max_streak": max_streak}
            )

if streak_lengths:
    sorted_sl = sorted(streak_lengths)
    print(
        f"Tool streaks: count={len(streak_lengths)}, "
        f"min={min(streak_lengths)}, "
        f"median={statistics.median(streak_lengths):.0f}, "
        f"mean={statistics.mean(streak_lengths):.1f}, "
        f"max={max(streak_lengths)}, "
        f"p90={sorted_sl[int(0.9 * len(sorted_sl))]:.0f}"
    )

# Show sessions with highest max streaks
session_max_streaks.sort(key=lambda x: x["max_streak"], reverse=True)
print("\nTop 10 sessions by max tool streak:")
for s in session_max_streaks[:10]:
    print(f'  {s["session_id"][:8]} ({s["source"]}): {s["max_streak"]} consecutive tool calls')

# ---- Part 2: Codex system prefix detection ----
print("\n" + "=" * 60)
print("PART 2: Codex CLI system-injected user messages")
print("=" * 60)

CODEX_SYSTEM_TAGS = [
    "<INSTRUCTIONS>",
    "<environment_context>",
    "<repository_context>",
    "<approval_policy>",
    "<context>",
    "# AGENTS.md",
]

codex_has_system_prefix = 0
codex_total_user_msgs = 0

for dev in index["developers"].values():
    for s in dev["sessions"]:
        if s["source"] != "codex_cli":
            continue
        fpath = os.path.join(DIR, f'{s["id"]}.json')
        if not os.path.exists(fpath):
            continue
        with open(fpath) as f2:
            msgs = json.load(f2)

        for m in msgs:
            if m["type"] == "user" and m.get("content"):
                codex_total_user_msgs += 1
                if any(m["content"].startswith(tag) for tag in CODEX_SYSTEM_TAGS):
                    codex_has_system_prefix += 1

print(
    f"Codex user msgs with system prefix: {codex_has_system_prefix}/{codex_total_user_msgs} "
    f"({round(codex_has_system_prefix / max(codex_total_user_msgs, 1) * 100, 1)}%)"
)

# ---- Part 3: URL and JSON-like content in user messages ----
print("\n" + "=" * 60)
print("PART 3: Content signals in user messages")
print("=" * 60)

url_pattern = re.compile(r"https?://\S+")
url_msgs = 0
json_msgs = 0
traceback_msgs = 0
error_msgs = 0
total_user_msgs = 0

for dev in index["developers"].values():
    for s in dev["sessions"]:
        fpath = os.path.join(DIR, f'{s["id"]}.json')
        if not os.path.exists(fpath):
            continue
        with open(fpath) as f2:
            msgs = json.load(f2)
        for m in msgs:
            if m["type"] != "user" or not m.get("content"):
                continue
            c = m["content"]
            total_user_msgs += 1
            if url_pattern.search(c):
                url_msgs += 1
            if c.count("{") >= 3 and c.count("}") >= 3 and c.count(":") >= 3:
                json_msgs += 1
            if "Traceback" in c or "traceback" in c:
                traceback_msgs += 1
            if "Error:" in c or "error:" in c or "FAILED" in c or "ERR!" in c:
                error_msgs += 1

print(f"Total user messages: {total_user_msgs}")
print(f"With URLs: {url_msgs} ({round(url_msgs / total_user_msgs * 100, 1)}%)")
print(
    f"With JSON-like content: {json_msgs} ({round(json_msgs / total_user_msgs * 100, 1)}%)"
)
print(
    f"With Traceback: {traceback_msgs} ({round(traceback_msgs / total_user_msgs * 100, 1)}%)"
)
print(
    f"With error strings: {error_msgs} ({round(error_msgs / total_user_msgs * 100, 1)}%)"
)
