# Fake OpenAI-compatible model: the first agent request overflows the context, later ones answer.
import json, sys, time, threading
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
state = {"agent_calls": 0}
lock = threading.Lock()
LOG = open(sys.argv[2], "a", buffering=1)
def sse(handler, text):
    handler.send_response(200)
    handler.send_header("Content-Type", "text/event-stream")
    handler.end_headers()
    def chunk(delta, finish=None):
        body = {"id": "c1", "object": "chat.completion.chunk", "created": int(time.time()), "model": "fake",
                "choices": [{"index": 0, "delta": delta, "finish_reason": finish}]}
        handler.wfile.write(f"data: {json.dumps(body)}\n\n".encode()); handler.wfile.flush()
    chunk({"role": "assistant", "content": ""})
    for word in text.split(" "):
        chunk({"content": word + " "}); time.sleep(0.05)
    chunk({}, "stop")
    usage = {"id": "c1", "object": "chat.completion.chunk", "created": int(time.time()), "model": "fake", "choices": [],
             "usage": {"prompt_tokens": 1000, "completion_tokens": 10, "total_tokens": 1010}}
    handler.wfile.write(f"data: {json.dumps(usage)}\n\n".encode())
    handler.wfile.write(b"data: [DONE]\n\n"); handler.wfile.flush()
class H(BaseHTTPRequestHandler):
    def log_message(self, *a): pass
    def do_GET(self):
        self.send_response(200); self.send_header("Content-Type", "application/json"); self.end_headers()
        self.wfile.write(json.dumps({"object": "list", "data": [{"id": "fake", "object": "model"}]}).encode())
    def do_POST(self):
        raw = self.rfile.read(int(self.headers.get("Content-Length", 0)))
        body = raw.decode(errors="replace")
        if "title generator" in body.lower() or "generate a title" in body.lower():
            kind = "title"
        elif "context summarization agent" in body.lower():
            kind = "compaction"
        else:
            kind = "agent"
        with lock:
            n = state["agent_calls"] = state["agent_calls"] + (1 if kind == "agent" else 0)
        LOG.write(f"{time.strftime('%H:%M:%S')} POST {self.path} kind={kind} agent_call={n} bytes={len(raw)}\n")
        if kind == "agent" and n == 1:
            err = {"error": {"message": "This model's maximum context length is 131070 tokens. However, your messages resulted in 140049 tokens.",
                             "type": "invalid_request_error", "param": None, "code": "context_length_exceeded"}}
            self.send_response(400); self.send_header("Content-Type", "application/json"); self.end_headers()
            self.wfile.write(json.dumps(err).encode()); return
        if kind == "title": return sse(self, "Overflow repro")
        if kind == "compaction": return sse(self, "Summary: the user asked for a short reply; nothing done yet.")
        time.sleep(int(__import__("os").environ.get("POST_COMPACT_DELAY","3")))  # keep the post-compaction step visibly running after T3 would have failed the turn
        return sse(self, f"Post-compaction step {n}: continuing the task after compaction.")
ThreadingHTTPServer(("127.0.0.1", int(sys.argv[1])), H).serve_forever()
