# Codex OAuth onboarding: token-lite automation flow (2026-05-10) Goal: future runs should be script-driven and low-token. The agent should not paste every browser/5sim/mail intermediate state into chat. Use compact status lines, local logs, screenshots only on blockers, and one final summary. ## Core state machine Use one orchestrator script that owns the flow and writes structured JSONL logs under a run directory, e.g. ```text ~/.Hermes/workspace/runs/codex-oauth// run.json events.jsonl screenshots/ cdp-targets.json fivesim-orders.jsonl ``` Recommended phases: 1. `preflight` - Read `~/.hermes/env/codex_oauth_onboarding.env` once. - Redact secrets in all printed output. - Validate selected target mode, Codex2API origin/admin key, ClawEmail profile, browser proxy, and 5sim settings. - Verify proxy TCP + exit IP with short timeouts. - If creating a fresh ClawEmail sub-mailbox, immediately open external receive before OpenAI submission: set/verify `commLevel=2` and `extReceiveType=1` via the logged-in ClawEmail Dashboard API `POST /api/v1/mailboxes/comm-settings?id=` with `{commLevel:2, extReceiveType:1, extSendType:0}`. If Dashboard login requires QQ master-mailbox OTP and the agent cannot read QQ mail, pause only for that 6-digit code. 2. `identity_gate` - Before any 5sim purchase, confirm there is a usable OpenAI identity path. - If creating a fresh ClawEmail sub-mailbox returns `OPEN_API_1004` / quota full, parse `data.mailbox.subMailboxes` and only reuse a mailbox after proving OpenAI login or signup can proceed. - After creating a fresh ClawEmail sub-mailbox, verify its communication rules before submitting it to OpenAI: target state is `commLevel=2` and `extReceiveType=1`. New sub-mailboxes can default to internal-only (`commLevel=1`, `extReceiveType=0`), which blocks OpenAI verification mail. If internal-only, stop with `blocked_requires_dashboard` and ask BOSS to enable `通讯规则 -> 开放外部通信 -> 收信范围:所有人` in the ClawEmail Dashboard. - Mark sub-mailbox outcomes locally (`deactivated`, `password_mismatch`, `usable`, `external_receive_blocked`, `unknown`). - If all candidates are deactivated/password-mismatch and quota is full, stop with `no_usable_mailbox` instead of buying SMS activations. 3. `browser_start` - Kill only the dedicated CDP Chrome process for port 9223. - Start visible Chrome with a dedicated profile and `--proxy-server`. - Verify CDP `/json/version` and browser target. 3. `oauth_start` - Generate a fresh target OAuth URL via target API. - For Codex2API, derive API origin if `CODEX2API_URL` includes `/admin/accounts`. - Open URL through CDP `/json/new`. 4. `email_login` - Submit ClawEmail address. - Poll `mail-cli --profile codex-current mail list --fid 1 --limit 50 --json`. - Select latest OpenAI code by timestamp, not message-list order. - Fill code through CDP with React-safe value setter. - If OpenAI returns `account_deactivated`, stop the current account and mark run failed before buying 5sim numbers. 5. `phone_verify` - Enter only if URL/text indicates `add-phone`. - Country priority: `FIVE_SIM_COUNTRY_ORDER` -> `FIVE_SIM_COUNTRY_ID` -> `vietnam` fallback only if both empty. - For each country, rotate up to `PHONE_VERIFICATION_REPLACEMENT_LIMIT` numbers. - Before buying/submitting, set visible OpenAI country selector to the intended country and verify it. - Buy SMS activation: `/v1/user/buy/activation/{country}/{operator}/openai`. - Submit local phone digits by visible paste/click or React-safe setter + visible submit. - If direct rejection (`无法向此电话号码发送验证码`), cancel activation and rotate. - If accepted/no direct rejection, poll `/v1/user/check/{activationId}`; if no SMS, click `重新发送`, poll again, retry resend at least once, then cancel/rotate. 6. `oauth_callback` - After phone/email success, continue consent screen if present. - Capture/submit callback to target API. - Verify target platform shows account/session. 7. `cleanup/report` - Cancel any active 5sim order on failure. - Save screenshot on blocker. - Final response includes: phase, outcome, account email, target session id (safe), current URL class, orders tried (activation IDs + country + outcome), screenshot path if blocker. No secrets/callback codes. ## Token-minimizing output rules - Do not stream full DOM/body text to chat. - Scripts should print compact JSON or single-line events, e.g. ```json {"phase":"phone_verify","country":"argentina","attempt":1,"activation_id":"100...","result":"direct_reject"} {"phase":"phone_verify","country":"netherlands","attempt":2,"result":"accepted_no_sms_after_resend"} {"phase":"email_login","result":"account_deactivated","screenshot":"/tmp/...png"} ``` - Store verbose outputs in files and only surface paths. - Only send screenshots for blockers or when BOSS asks. - Use `execute_code` or one `terminal` script for loops; avoid repeated tool calls for each 5sim poll. - Avoid `browser_snapshot`/full DOM dumps unless diagnosing a selector bug. - Prefer CDP helper functions that return exact state classes: - `login_page` - `email_code_page` - `add_phone_page` - `phone_code_page` - `account_deactivated` - `cloudflare_or_challenge` - `unknown` ## Correct 5sim country handling Current env can include both: ```bash FIVE_SIM_COUNTRY_ORDER=argentina,netherlands,indonesia FIVE_SIM_COUNTRY_ID= PHONE_VERIFICATION_REPLACEMENT_LIMIT=3 ``` Do **not** ignore `FIVE_SIM_COUNTRY_ORDER`. Country order should be: 1. Split non-empty `FIVE_SIM_COUNTRY_ORDER` by comma and trim. 2. Else use non-empty `FIVE_SIM_COUNTRY_ID`. 3. Else fallback to original extension default `vietnam`. Known OpenAI Chinese labels/prefixes used in visible country selector: ```text argentina 阿根廷 (+54) netherlands 荷兰 (+31) indonesia 印度尼西亚 (+62) vietnam 越南 (+84) england 英国 (+44) japan 日本 (+81) germany 德国 (+49) ``` ## Known pitfalls from completed run - Proxy switch can invalidate OpenAI auth session; always be ready to regenerate target OAuth URL and redo email login. - `CODEX2API_URL` may be a web admin page; use origin for API calls. - CDP-only phone/country changes can desync React state and submit the number under `美国 (+1)`. Verify visible selector before buying/submitting. - A page returning `account_deactivated` after email-code submit means the current account is no longer usable; do not spend 5sim numbers on it. - Clicking/resending on a non-rejected phone may leave the flow at `电子邮件地址已验证`; if continuing same account, reopen current OAuth URL and redo login. If `account_deactivated`, stop. - Chrome stable may require visible profile/UI; keep a visible browser for auth pages. ## Suggested implementation artifact Create or maintain a reusable local script, e.g. ```text /Users/chick/.Hermes/workspace/scripts/codex_oauth_onboarding_runner.py ``` It should accept flags: ```bash python3 codex_oauth_onboarding_runner.py \ --env ~/.hermes/env/codex_oauth_onboarding.env \ --mode codex2api \ --proxy-from-env \ --run-once \ --max-phone-countries-from-env \ --screenshot-on-blocker ``` The script should be idempotent enough to resume from `email_login` or `phone_verify` if the browser is already open, but should default to a clean profile per run. ## Final report template ```text 结果:失败/成功 阶段:email_login / phone_verify / oauth_callback 邮箱:... 代理:socks5://192.168.2.8:1085(出口 IP: ...) 目标:Codex2API session_id=... 手机验证:argentina[...], netherlands[...], indonesia[...] 阻塞原因:account_deactivated / no_sms_after_resend / direct_reject_all / challenge 截图:MEDIA:/path/to/screenshot.png 下一步:... ```