# 可靠 Click 協議 (Reliable Click Protocol) **定位:** 瀏覽器自動化的 ≈ 80% 問題都是 **click 沒中** 或 **誤判狀態**。這份檔案是把 OiiOii demo 裡踩到的所有坑整合成可重複使用的 SOP。每個網站都套得上。 **核心原則:** 每個 irreversible action (click 生成按鈕、送出表單、確認付費) 都要 **先驗證 → 再執行 → 後驗證**。不要相信你以為的狀態,要相信 screenshot。 --- ## Part 1 — Click 決策樹 (Decision Tree) 遇到「我需要點一個元素」時,依這個順序: ``` 1. 是否有確定性連結 (href)? ├── 是 → 直接 navigate (最可靠,一步到位) └── 否 → 2 2. 是否有穩定 accessibility tree? ├── 是 (find 能穩定找到 + ref 短期有效) │ └── find → 立刻 left_click ref (中間不插螢幕截圖) └── 否 → 3 3. 是否能用座標? ├── screenshot → 目視定位元素中心 (x, y) │ → left_click coordinate → screenshot 驗證 └── 坐標打不中 → 4 4. Fallback 連鎖: a. hover (x, y) 確認 cursor 在元素上 → left_click b. 改用 scroll_to ref 先把元素捲到 viewport 中心 → 再 click c. 用 keyboard Tab 跳到元素 → Enter d. 若都失敗 → **停下來問使用者** (不要亂戳) ``` --- ## Part 2 — ref (accessibility reference) 的正確用法 ### ref 的特性 - `find` / `read_page` 回傳的 `ref_N` 是 **該次查詢的短期快照** - 多數網站 ref 有效 30 秒~幾分鐘;**React / Vue / tldraw 等動態渲染站** (如 OiiOii) ref 可能 **下一秒就失效** - ref 失效的訊號:`"No element found with reference: 'ref_N'. The element may have been removed from the page."` ### ref 使用 SOP **✅ 對:** ``` find "送出按鈕" → ref_42 left_click ref_42 # 立刻點 ``` **❌ 錯:** ``` find "送出按鈕" → ref_42 screenshot # ← 這一步可能讓頁面 re-render,ref_42 失效 zoom ... # ← 這一步也會 left_click ref_42 # 💥 "Element may have been removed" ``` ### 原則 - **find → click** 中間 **不插螢幕截圖/zoom/read_page 以外的動作** - 如果需要先看才能決定 click 哪個 → 用 screenshot 決定後 **用座標**,不要先 find 再拖延 - 如果一定要 read_page 拿結構 → read_page 回來後立刻 click,**不 screenshot 再 click** --- ## Part 3 — 座標 click 的精準技巧 ### 座標系統 `computer.left_click coordinate=[x, y]` 使用的是 **viewport 座標**,而 screenshot 回傳常見 1568×751 或 1568×708。**多數環境中座標 ≈ screenshot 像素座標** (不需要手動 1920/1568 縮放)。實測:OiiOii 在 1568×708 的 (290, 410) 打中「中文」按鈕。 ### 定位精度提升 **❌ 粗暴取中心:** ``` 看起來按鈕在 (190, 205) → click (190, 205) # 可能打到邊緣或 padding ``` **✅ 先 zoom 看清 hit area:** ``` zoom region=[x0, y0, x1, y1] # 把按鈕放大 # zoomed image 顯示:按鈕視覺範圍 y 175-230,中心 y=203 # 按鈕實際可能有 4px 內距,實際 hit area 是 y 179-226 # 安全 click 在正中 y=203,x 同理 ``` ### 按鈕 hit area 經驗值 | 按鈕視覺大小 | 安全 click 區 | |---|---| | 40×40 px 小圖示 | 取視覺中心,誤差容忍 ±3 px | | 100×40 px 文字按鈕 | 取中心,誤差 ±5 px | | 大 CTA (400×50 px) | 中心 ±10 px 都 OK,但**避開按鈕邊界 5 px** | | 卡片整塊可點 | 取卡片中心,不要點在卡片內文字上 | ### click 失敗的診斷 若 click 沒反應,**先排查這三件事再重點**: | 症狀 | 原因 | 對策 | |---|---|---| | 點了毫無反應、UI 沒變化 | 座標在 padding 或透明 overlay | zoom 看實際 hit area,往中心挪 | | 出現紅色錯誤 toast (如「選項暫不支援重選」) | 這個 action 已經送出過 | 不要再點,UI 已在下一階段 | | 按鈕視覺變粉框但送不出 | 這是 selected state,不是 activated | 找真正的「送出/確認」按鈕再點 | | 出現 paywall / modal 遮罩 | 有彈窗擋在按鈕上 | 先處理彈窗 (關閉或互動),再回來 | | 頁面在滾動中 | 元素位置漂移 | 先 `wait 1 秒` 或滾到停,再取 screenshot → click | --- ## Part 4 — 驗證狀態:Selected vs Hover vs Active OiiOii demo 的關鍵誤判:**把 hover ring 當成 selected**,導致誤以為 click 沒中。 ### 視覺狀態辨識 | 狀態 | 常見視覺 | |---|---| | **Unselected / default** | 淡色背景、默認邊框 | | **Hover (focus ring)** | **粉色 / 亮色外圈 ring**,但背景還是默認色 | | **Selected / committed** | **填底色變深** (或變 brand 色),邊框也可能變色 | | **Disabled** | 灰化 + 降透明度 | | **Active (正在點擊)** | 短暫的按下陰影,1 幀 | ### 驗證選中的 SOP click 後 **必做**: ``` 1. screenshot (或 zoom 該按鈕區域) 2. 看填底色是否變深 / 變 brand 色 3. 若填底沒變 → click 沒中 → 回 Part 3 重試 4. 若填底有變、但下一步 UI 沒出現 → 正常的「agent 背後處理」,等 60-90s 再看 ``` ### Selected 的其他信號 - 按鈕旁/底部出現「小型確認泡泡」(OiiOii 的粉色氣泡) — 這是系統訊息,強指標 - Checklist 項目加 ✓ (綠勾) - 右下/左下 toast 提示「已送出」「信息已確認」 - URL 改變 (跳到 `/space/xxx` 之類) --- ## Part 5 — Scroll-aware 座標 (對抗漂移) ### 漂移現象 長對話或動態 panel 裡,同一個按鈕的 (x, y) 會因 scroll 位置變化。實測 OiiOii 的「滿意」按鈕 y 在 385 → 573 → 428 之間來回漂。 ### 對策 **Rule of thumb:每次要 click 按鈕,前 5 秒內必須有 screenshot 驗證該按鈕的當前 y 座標。** ``` BAD: screenshot -> see button at y=428 scroll down 10 ticks click (290, 428) # ❌ y 已經變了,打到別處 GOOD: scroll down 10 ticks screenshot # 必須重照 see button at y=290 # 位置變了 click (290, 290) # ✓ ``` ### 避免漂移的招 - **不要在 panel 中隨便 scroll** — 只有在要看 above/below 的內容才 scroll - **click 前不滾動** — 若一定要滾,滾完立刻 screenshot - **固定位置按鈕**:有些按鈕是 sticky (如底部 submit bar),這類座標穩定 --- ## Part 6 — 文字輸入的陷阱 ### 輸入框類型判斷 | HTML 元素 | form_input 支援 | 對策 | |---|---|---| | `` / `