# -*- coding: utf-8 -*- """Verification script: agent_captcha (GoubaLab/reg-factory-github) on Aurora gateway. Run: env -u PYTHONPATH python -u scripts/test_agent_captcha_aurora.py Requires: repo clone (default C:/Users/User/tmp/reg-factory-github, override REPO_PATH), Aurora up on 127.0.0.1:8080, PIL installed. ~30s total (2 live vision rounds).""" import sys, os, json, base64, io, time, re REPO = os.environ.get("REPO_PATH", r"C:\Users\User\tmp\reg-factory-github") sys.path.insert(0, os.path.join(REPO, "common")) AURORA = "http://127.0.0.1:8080" KEY = os.environ.get("AURORA_KEY", "enigothbreach2026master") os.environ["VISION_API_BASE"] = AURORA os.environ["VISION_API_KEY"] = KEY os.environ["VISION_MODEL"] = "cleanapis_com/gemini-3.6-flash" os.environ["VOTE_ZZ_BASE"] = AURORA os.environ["VOTE_ZZ_KEY"] = KEY os.environ["VOTE_GPT_KEY"] = KEY import agent_captcha as AC from PIL import Image, ImageDraw, ImageFont PASSED, FAILED = [], [] def check(name, cond, detail=""): tag = "PASS" if cond else "FAIL" print(f" [{tag}] {name} {detail}") (PASSED if cond else FAILED).append(name) print("=== T1: _looks_like_refusal ===") check("refusal caught", AC._looks_like_refusal("I cannot fulfill this request")) check("empty=refusal", AC._looks_like_refusal("")) check("valid answer passes", not AC._looks_like_refusal("ANSWER=2 the left one")) print("\n=== T2: parse_json_answer ===") check("fence after CoT", AC.parse_json_answer('Sure ```json\n{"answer": 3}\n```') == {"answer": 3}) check("no json => None", AC.parse_json_answer("no json here") is None) print("\n=== T3: fixtures + grid stitch + enhance ===") def make_tile(color, kind): img = Image.new("RGB", (100, 100), "#222") d = ImageDraw.Draw(img) if kind == "square": d.rectangle([25, 25, 75, 75], fill=color) elif kind == "circle": d.ellipse([25, 25, 75, 75], fill=color) else: d.polygon([(50, 20), (20, 80), (80, 80)], fill=color) return img def b64(img): buf = io.BytesIO(); img.save(buf, format="PNG") return base64.b64encode(buf.getvalue()).decode() tiles = [make_tile("#44ff44", "circle"), make_tile("#4477ff", "triangle"), make_tile("#ff4444", "square"), make_tile("#ffff44", "square")] # truth: idx 2 b64_tiles = [b64(t) for t in tiles] ref_b64 = b64(make_tile("#ff4444", "square")) grid_path = os.path.join(os.path.dirname(__file__), "..", "ac_grid_test.png") res = AC.stitch_options_grid(b64_tiles, grid_path, reference_b64=ref_b64, cols=4, return_geom=True) grid_b64 = res[0] if isinstance(res, tuple) else res check("grid stitched", bool(grid_b64)) enh_path = os.path.join(os.path.dirname(__file__), "..", "ac_enh_test.png") AC.enhance_local(b64_tiles[2], enh_path, scale=2) enh_jpg = enh_path.rsplit(".", 1)[0] + ".jpg" # saves .jpg, not .png! check("enhanced 2x (jpg)", os.path.exists(enh_jpg)) print("\n=== T4: ask_vision (live, Aurora) ===") Q = ("Look at this 2x2 grid of colored shapes plus a reference image on top. " "Which numbered tile shows a RED SQUARE exactly like the reference? " "Reply ANSWER=N where N is 0-3.") t0 = time.time() txt = AC.ask_vision(Q, grid_b64, models=["cleanapis_com/gemini-3.6-flash"], max_tokens=150) check("ask_vision answered", txt is not None, f"{time.time()-t0:.1f}s") if txt: m = re.findall(r"ANSWER\s*=\s*(\d+)", txt) check("ask_vision correct (2)", m and int(m[-1]) == 2, f"got {m}") print("\n=== T5: vote_answer (live multi-model) ===") AC.VOTER_MODELS = [ (AURORA, KEY, "cleanapis_com/gemini-3.6-flash"), (AURORA, KEY, "cleanapis_com/gemini-3.1-pro"), (AURORA, KEY, "dashscope_aliyuncs_com/qwen-vl-max"), (AURORA, KEY, "anthropic_com/claude-sonnet-4-6"), ] t0 = time.time() best, votes, raws = AC.vote_answer(Q, grid_b64, n_options=4, deadline=60) print(f" votes={votes} in {time.time()-t0:.1f}s") check("winner returned", best is not None) check("winner correct (2)", best == 2, f"best={best}") print("\n" + "=" * 40) print(f"RESULT: {len(PASSED)} PASS / {len(FAILED)} FAIL") if FAILED: print("FAILED:", FAILED)