"""Export an account-owner-approved Arena Playwright storage_state. Run this only on your own computer. The generated files contain active session credentials and must be stored as secrets, never committed to Git. For Google OAuth, launch a regular installed Chrome with a dedicated profile and local CDP port, complete login manually, then run this tool with --cdp-url. This avoids asking Google to authenticate inside Playwright's bundled Chromium. """ from __future__ import annotations import argparse import base64 import gzip import json from pathlib import Path from urllib.parse import urlparse from playwright.sync_api import sync_playwright def find_arena_page(context): for page in context.pages: if "arena.ai" in page.url: return page return None def is_arena_host(host: str) -> bool: normalized = host.strip().lower().lstrip(".") return normalized == "arena.ai" or normalized.endswith(".arena.ai") or normalized == "lmarena.ai" or normalized.endswith(".lmarena.ai") def write_state(context, state_path: Path, base64_path: Path) -> None: raw_state = context.storage_state() # CDP may expose cookies for every site in the dedicated profile. Export only # Arena data so Google account cookies are never placed in the Space Secret. state = { "cookies": [ cookie for cookie in raw_state.get("cookies", []) if is_arena_host(str(cookie.get("domain") or "")) ], "origins": [ origin for origin in raw_state.get("origins", []) if is_arena_host(urlparse(str(origin.get("origin") or "")).hostname or "") ], } if not state["cookies"] and not state["origins"]: raise RuntimeError( "No Arena cookies or Local Storage were found. Complete Arena login and send a " "message in the connected browser before exporting." ) state_text = json.dumps(state, ensure_ascii=False, separators=(",", ":")) state_path.write_text(state_text, encoding="utf-8") base64_path.write_text( base64.b64encode(gzip.compress(state_text.encode("utf-8"), compresslevel=9)).decode( "ascii" ), encoding="ascii", ) def main() -> None: parser = argparse.ArgumentParser() parser.add_argument("--state-file", default="arena_storage_state.json") parser.add_argument("--base64-file", default="arena_storage_state.b64") parser.add_argument( "--cdp-url", default="", help=( "Connect to a regular Chrome/Edge launched with a local remote-debugging port, " "for example http://127.0.0.1:9222" ), ) args = parser.parse_args() state_path = Path(args.state_file) base64_path = Path(args.base64_file) with sync_playwright() as playwright: if args.cdp_url: browser = playwright.chromium.connect_over_cdp(args.cdp_url) if not browser.contexts: raise RuntimeError("The CDP browser has no available browser context") context = browser.contexts[0] page = find_arena_page(context) if page is None: page = context.new_page() page.goto("https://arena.ai/text/direct", wait_until="domcontentloaded") page.bring_to_front() print("\n已連接到一般 Chrome/Edge。") else: # Non-Google/manual flow. Google may reject authentication inside this # Playwright-managed Chromium; use --cdp-url for Google OAuth. browser = playwright.chromium.launch( headless=False, args=["--start-maximized"], ) context = browser.new_context(no_viewport=True) page = context.new_page() page.goto("https://arena.ai/text/direct", wait_until="domcontentloaded") print("\n請在剛開啟或已連接的官方 Arena 視窗中:") print("1. 使用自己的帳號登入。") print("2. 自行閱讀並決定是否接受服務條款。") print("3. 完成必要的人工驗證。") print("4. 實際傳送一則訊息並確認模型能回答。") input("\n全部完成後回到這個終端機,按 Enter 匯出 storage_state...") write_state(context, state_path, base64_path) if not args.cdp_url: browser.close() print(f"\n已建立:{state_path}") print(f"已建立:{base64_path}") print("將 .b64 檔案的完整內容設為 Hugging Face Secret ARENA_STORAGE_STATE_B64。") print("警告:輸出檔與 CDP 專用瀏覽器 profile 都包含登入 Session。") print("設定 Secret 後請安全刪除,不可提交 Git,也不要公開 remote-debugging port。") if __name__ == "__main__": main()