#!/usr/bin/env python3 """Fake OpenAI-compatible endpoint to exercise the LLM proxy path without a real key. Round 1 asks for a search tool; round 2 returns show_cards with ids from the tool results.""" import json, re, sys from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 8798 SEEN = {"auth_ok": 0} class H(BaseHTTPRequestHandler): def log_message(self, *a): pass def do_GET(self): b = json.dumps(SEEN).encode(); self.send_response(200); self.end_headers(); self.wfile.write(b) def do_POST(self): body = json.loads(self.rfile.read(int(self.headers["Content-Length"]))) if body.get("model") in ("busy-model", "busy-model-2"): b = b'{"error":{"message":"rate-limited upstream","code":429}}' self.send_response(429); self.send_header("Content-Type", "application/json"); self.end_headers(); self.wfile.write(b) return if self.headers.get("Authorization") == "Bearer test-dummy-key": SEEN["auth_ok"] += 1 if body.get("model") == "daily-model": b = json.dumps({"error": {"message": "Rate limit exceeded: free-models-per-day.", "code": 429, "metadata": {"headers": {"X-RateLimit-Limit": "50", "X-RateLimit-Remaining": "0", "X-RateLimit-Reset": "4102444800000"}}}}).encode() self.send_response(429); self.send_header("Content-Type", "application/json"); self.end_headers(); self.wfile.write(b) return last = body["messages"][-1]["content"] if "new internet" in last.lower(): # answers like a model that read the prompt: it only knows "top left" = copy.logo if the prompt says so sysmsg = body["messages"][0]["content"] knows = "TOP-LEFT" in sysmsg and '"logo": "Agent Market"' in sysmsg out = ({"reply": "Renamed the top-left logo to New Internet.", "actions": [{"type": "set_theme", "payload": {"copy": {"logo": "New Internet"}}}]} if knows else {"reply": "I can't change that text.", "actions": []}) b = json.dumps({"choices": [{"message": {"role": "assistant", "content": json.dumps(out)}}]}).encode() self.send_response(200); self.send_header("Content-Type", "application/json"); self.end_headers(); self.wfile.write(b) return if "background" in last: out = {"reply": "Done! Sunset gradient applied (lst_deadbeef).", "actions": [{"type": "set_theme", "payload": { "background": {"kind": "gradient", "colors": ["#ff7e5f", "#feb47b", "javascript:alert(1)"], "angle": 180}, "palette": {"accent": "orange"}, "customCss": "@import url(https://evil.example/x.css); .card{border-width:3px;position:fixed}", "copy": {"headline": "Sunset"}}}]} b = json.dumps({"choices": [{"message": {"role": "assistant", "content": json.dumps(out)}}]}).encode() self.send_response(200); self.send_header("Content-Type", "application/json"); self.end_headers(); self.wfile.write(b) return if last.startswith("TOOL_RESULTS"): ids = re.findall(r'"id": "(lst_[a-f0-9]+)"', last)[:3] out = {"reply": "Here are bikes I found (mock LLM). Payments are TEST MODE ONLY.", "actions": [{"type": "show_cards", "payload": {"heading": "Bikes", "listing_ids": ids}}, {"type": "not_allowed_component", "payload": {}}]} else: out = {"reply": "searching", "tools": [{"name": "search", "args": {"q": "bike"}}]} b = json.dumps({"choices": [{"message": {"role": "assistant", "content": json.dumps(out)}}]}).encode() self.send_response(200); self.send_header("Content-Type", "application/json"); self.end_headers(); self.wfile.write(b) ThreadingHTTPServer(("127.0.0.1", PORT), H).serve_forever()