"""C2 rerun with large hosted models (OpenRouter free tier, 2026-10-20 UTC+8).
Method copied UNCHANGED from c2b_llm.py (evidence 09): same slices (synthetic_logs[1250:1430], wiki_search[:100]),
same compress() call (Headroom 0.41.0, model="gpt-4o", same 4 messages), same 10 questions, same prompt text,
same exact-match scoring (norm + 'contained, <=12 extra chars'). Only the answering model changed:
Ollama local Qwen -> OpenRouter chat/completions, single user message = the same prompt string, temperature 0, seed 1.
API key read from env OPENROUTER_API_KEY (never written anywhere). Resumable: answers cached in the output JSON.
usage: python c2_hosted.py OUT.json MODEL_ID"""
import json, sys, time, os, re, urllib.request, urllib.error
from headroom import compress
P = "../payloads/"
OUT, MODEL = sys.argv[1], sys.argv[2]
lg = json.load(open(P + "synthetic_logs.json"))[1250:1430]
wk = json.load(open(P + "wiki_search.json"))[:100]
def comp(raw):
    msgs = [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Here is the tool output. Answer questions about it."},
            {"role": "assistant", "content": None, "tool_calls": [{"id": "call_1", "type": "function", "function": {"name": "fetch", "arguments": "{}"}}]},
            {"role": "tool", "tool_call_id": "call_1", "content": raw}]
    r = compress(msgs, model="gpt-4o")
    c = r.messages[-1]["content"]
    return (json.loads(c) if c.startswith('"') else c), r
fatal = next(x for x in lg if x["level"] == "FATAL")
Q = {
 "synthetic_logs_slice": (lg, [
   ("What is the request_id of the FATAL entry?", fatal["request_id"]),
   ("Which service logged the FATAL entry?", fatal["service"]),
   ("What is the latency_ms of request %s?" % lg[10]["request_id"], str(lg[10]["latency_ms"])),
   ("What is the level of request %s?" % lg[150]["request_id"], lg[150]["level"]),
   ("Which service handled request %s?" % lg[90]["request_id"], lg[90]["service"])]),
 "wiki_search_slice": (wk, [
   ("What is the pageid of the article titled '%s'?" % wk[5]["title"], str(wk[5]["pageid"])),
   ("What is the wordcount of the article titled '%s'?" % wk[20]["title"], str(wk[20]["wordcount"])),
   ("What is the title of the article with pageid %d?" % wk[40]["pageid"], wk[40]["title"]),
   ("What is the size of the article titled '%s'?" % wk[70]["title"], str(wk[70]["size"])),
   ("What is the title of the very first result?", wk[0]["title"])]),
}
KEY = os.environ["OPENROUTER_API_KEY"]
REQS = {"n": 0}
def ask(ctx, q):
    prompt = "Tool output:\n" + ctx + "\n\nQuestion: " + q + "\nAnswer with only the value, nothing else."
    body = {"model": MODEL, "messages": [{"role": "user", "content": prompt}], "temperature": 0, "seed": 1, "max_tokens": 16000}
    for attempt in range(6):
        REQS["n"] += 1
        t = time.time()
        try:
            req = urllib.request.Request("https://openrouter.ai/api/v1/chat/completions", data=json.dumps(body).encode(),
                  headers={"Content-Type": "application/json", "Authorization": "Bearer " + KEY, "X-Title": "triedagents try-tools C2 rerun"})
            o = json.load(urllib.request.urlopen(req, timeout=900))
            if "choices" not in o: raise RuntimeError(json.dumps(o)[:300])
            m = o["choices"][0]["message"]
            return (m.get("content") or "").strip(), (o.get("usage") or {}).get("prompt_tokens"), round(time.time() - t, 1), o.get("model"), o.get("provider"), attempt
        except urllib.error.HTTPError as e:
            msg = e.read().decode(errors="replace")[:300]
            print("HTTP", e.code, msg, file=sys.stderr, flush=True)
            if e.code == 429: time.sleep(30 * (attempt + 1)); continue
            if e.code >= 500: time.sleep(15); continue
            raise
        except Exception as e:
            print("ERR", repr(e)[:300], file=sys.stderr, flush=True); time.sleep(15)
    raise RuntimeError("gave up")
def norm(s): return re.sub(r"[\s'\"`.]+", "", s).lower()
out = json.load(open(OUT)) if os.path.exists(OUT) else {"model": MODEL, "via": "OpenRouter free tier", "method": "unchanged from c2b_llm.py; see docstring", "slices": {}}
os.makedirs("payloads_slices", exist_ok=True)
for name, (rows, qs) in Q.items():
    raw = json.dumps(rows, indent=1)
    c, r = comp(raw)
    open("payloads_slices/%s.original.json" % name, "w").write(raw)
    open("payloads_slices/%s.compressed.txt" % name, "w").write(c)
    rec = out["slices"].get(name) or {"tokens_before": r.tokens_before, "tokens_after": r.tokens_after, "transforms": list(r.transforms_applied), "ccr_markers": c.count("<<ccr:"), "questions": []}
    done = {(x["input"], x["q"]) for x in rec["questions"]}
    for label, ctx in (("original", raw), ("compressed", c)):
        for q, a in qs:
            if (label, q) in done: continue
            ans, pt, s, served, prov, retries = ask(ctx, q)
            ok = norm(a) == norm(ans) or (norm(a) in norm(ans) and len(norm(ans)) <= len(norm(a)) + 12)
            rec["questions"].append({"input": label, "q": q, "truth": a, "model": ans[:200], "correct": ok, "prompt_tokens": pt, "seconds": s, "served_model": served, "provider": prov, "retries": retries})
            print(name, label, ok, repr(a), repr(ans[:80]), pt, s, flush=True)
            out["slices"][name] = rec; out["http_requests_this_process"] = REQS["n"]
            json.dump(out, open(OUT, "w"), indent=1, ensure_ascii=False)
    rec["questions"].sort(key=lambda x: (x["input"] != "original", [q for q, _ in qs].index(x["q"])))
    for label in ("original", "compressed"):
        rec[label + "_correct"] = sum(1 for x in rec["questions"] if x["input"] == label and x["correct"])
    rec["same_answer_both"] = sum(1 for i in range(len(qs)) if norm(rec["questions"][i]["model"]) == norm(rec["questions"][i + len(qs)]["model"]))
    out["slices"][name] = rec
    json.dump(out, open(OUT, "w"), indent=1, ensure_ascii=False)
tot = lambda k: sum(v[k] for v in out["slices"].values())
out["summary"] = {"questions_per_input": 10, "original_correct": tot("original_correct"), "compressed_correct": tot("compressed_correct"), "identical_answers": tot("same_answer_both")}
json.dump(out, open(OUT, "w"), indent=1, ensure_ascii=False)
print(json.dumps(out["summary"]))
