Skip to content

Commit 42c15b7

Browse files
committed
Document new assertions, flow control, and recording editors
Mirror the README.md additions into the zh-CN / zh-TW READMEs and the Sphinx docs (Eng + Zh): off-screen assertions (clipboard/process/file/ http), the assert_all/assert_any/assert_eventually combinators, the AC_try and AC_while_var flow-control blocks, and the dedupe_moves / merge_sleeps recording editors.
1 parent 55883cb commit 42c15b7

8 files changed

Lines changed: 280 additions & 14 deletions

File tree

README/README_zh-CN.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@
6565
[`docs/source/Zh/doc/new_features/v3_features_doc.rst`](../docs/source/Zh/doc/new_features/v3_features_doc.rst)
6666

6767
**断言**
68-
- **断言 DSL** — 验证画面状态而不只是操作:`assert_text`(OCR,`regex` + `present=False` 断言不存在)、`assert_image``assert_pixel``assert_window`。返回 `AssertionResult`,不符时抛出 `AutoControlAssertionException`,可选失败截图(`AC_assert_text / _image / _pixel / _window`)。
68+
- **断言 DSL** — 验证画面状态而不只是操作:`assert_text`(OCR,`regex` + `present=False` 断言不存在)、`assert_image``assert_pixel``assert_window``assert_clipboard``equals` / `contains` / `regex``present=False` 可确认机密已清除)、`assert_process`(指定名称的进程是否运行中,通过 psutil)。返回 `AssertionResult`,不符时抛出 `AutoControlAssertionException`,可选失败截图(`AC_assert_text / _image / _pixel / _window / _clipboard / _process`)。
69+
- **画面外断言**`assert_file`(文件存在 / 子串 / SHA-256 / 最小大小,验证下载或导出结果)与 `assert_http`(http/https 端点返回状态码 + 可选正文,一律带显式 timeout)。两者把 DSL 延伸到画面之外,并能接到下方的组合器(`AC_assert_file / AC_assert_http`)。
70+
- **断言组合器**`assert_all([...specs])`*软断言*方式跑完整批(逐一检查、收齐所有失败才抛出)并返回 `GroupAssertionResult``assert_any([...specs])` 是 OR 互补(任一通过即通过、短路 — 例如登录成功对话框**重定向其一出现即可);`assert_eventually(spec, timeout, interval)` 重试单个声明式 spec 直到通过或超时(例如轮询健康检查端点直到返回 200,或等待下载文件出现)。均以 spec 驱动(`{"kind": "text", "text": "Saved"}``{"kind": "http", "url": "..."}`),在 Python、JSON、MCP 中行为一致,涵盖全部断言类型 — text/image/pixel/window/clipboard/process/file/http(`AC_assert_all / AC_assert_any / AC_assert_eventually`)。
6971
- **媒体断言**`assert_audio_activity`(录音 + RMS 阈值判断有声 / 静音)与 `assert_video_changes`(视频区段相邻帧平均差异判断动态 / 静止);纯数值核心,`sounddevice` / OpenCV 延迟加载(`AC_assert_audio / AC_assert_video_changes`)。
7072

7173
**数据驱动执行**
@@ -136,15 +138,15 @@
136138

137139
## 功能特性
138140

139-
- **QA / 测试框架** — 断言 DSL(`assert_text` / `_image` / `_pixel` / `_window` 加上音频/视频断言)、数据驱动执行(CSV / JSON / SQLite / Excel → `AC_for_each_row`)、具 setup/teardown/标签的计分 `run_suite`、JUnit + Allure 报告输出、不稳定测试检测与自动隔离、无障碍 / i18n 审计(缺失标签、WCAG 对比度、截断),以及并行的移动设备矩阵。详见 [本次更新 (2026-06)](#本次更新-2026-06)
141+
- **QA / 测试框架** — 断言 DSL(`assert_text` / `_image` / `_pixel` / `_window` / `_clipboard` / `_process` / `_file` / `_http` 加上音频/视频断言,以及 `assert_all` / `assert_any` / `assert_eventually` 组合器)、数据驱动执行(CSV / JSON / SQLite / Excel → `AC_for_each_row`)、具 setup/teardown/标签的计分 `run_suite`、JUnit + Allure 报告输出、不稳定测试检测与自动隔离、无障碍 / i18n 审计(缺失标签、WCAG 对比度、截断),以及并行的移动设备矩阵。详见 [本次更新 (2026-06)](#本次更新-2026-06)
140142
- **鼠标自动化** — 移动、点击、按下、释放、拖拽、滚动,支持精确坐标控制
141143
- **键盘自动化** — 按下/释放单一按键、输入字符串、组合键、按键状态检测
142144
- **图像识别** — 使用 OpenCV 模板匹配在屏幕上定位 UI 元素,支持可配置的检测阈值
143145
- **Accessibility 元件搜索** — 通过操作系统无障碍树(Windows UIA / macOS AX)按名称/角色定位按钮、菜单、控件
144146
- **AI 元件定位(VLM)** — 用自然语言描述 UI 元素,由视觉语言模型(Anthropic / OpenAI)返回屏幕坐标
145147
- **OCR** — 三个可插拔后端(Tesseract 用于 ASCII、EasyOCR 无外部可执行文件且支持 CJK、PaddleOCR 中/日/韩质量最高),统一 API 与标准语言代码;后端由 `backend=` 参数、`AUTOCONTROL_OCR_BACKEND` 环境变量或自动探测决定。可搜索、点击或等待文字出现;支持 regex 搜索与整块区域 dump
146148
- **LLM 动作规划器** — 用 Claude 把自然语言描述翻译成验证过的 `AC_*` 动作清单
147-
- **运行期变量与流程控制** — 执行时 `${var}` 替换,加上 `AC_set_var` / `AC_inc_var` / `AC_if_var` / `AC_for_each` / `AC_loop` / `AC_retry` 让脚本数据驱动
149+
- **运行期变量与流程控制** — 执行时 `${var}` 替换,加上 `AC_set_var` / `AC_inc_var` / `AC_if_var` / `AC_for_each` / `AC_loop` / `AC_while_var` / `AC_retry` / `AC_try` 让脚本数据驱动`AC_while_var` 在变量比较成立时持续循环(每轮重新判断,`max_iter` 安全上限);`AC_try` 提供 try/catch/finally:`body` 失败时改走 `catch` 恢复分支而非中止、`finally` 必定执行、错误通过 `error_var` 暴露、可在清理后 `reraise`(循环 `break`/`continue` 仍能穿透)
148150
- **远程桌面** — 用 token 认证的 TCP 协议串流本机画面并接收输入,**** 连接到他机观看与控制(host + viewer GUI 内置)。可选 TLS(HTTPS 级加密)、WebSocket 传输(``ws://`` + ``wss://``,穿墙/浏览器友好)、持久化 9 位数 Host ID、host→viewer 音频串流、双向剪贴板同步(文字 + 图片)、分块文件传输(拖放 + 进度条;任意目的路径;无大小上限)。另含文件夹同步(增量镜像 — 本地删除不会传出去)与自建 coturn TURN 配置包生成器(turnserver.conf + systemd unit + docker-compose + README)。**AnyDesk 风格弹出窗口**:viewer 认证成功后远程桌面会开在独立的可调整大小顶层窗口,控制面板保持简洁;Remote Desktop 子分页外层包了 `QScrollArea`,小窗口下可滚动、4K 屏幕下会铺满。同时支持 headless API 与 MCP 工具 (`ac_remote_*`) 直接驱动
149151
- **驱动级输入后端(可选)** — 针对忽略 SendInput(Win)或 XTest(Linux)的游戏/应用:**Interception driver 后端**(Windows,HID 层鍵鼠注入,使用 Oblita WHQL-signed driver,通过 `JE_AUTOCONTROL_WIN32_BACKEND=interception` 启用)、**uinput 后端**(Linux,kernel `/dev/uinput` 合成 HID 设备,通过 `JE_AUTOCONTROL_LINUX_BACKEND=uinput` 启用),以及 **ViGEm 虚拟手柄**(Windows,针对只认手柄的游戏,提供虚拟 Xbox 360 手柄 + 友善的 button / dpad / stick / trigger API,并暴露为 `AC_gamepad_*` 执行器命令与 `ac_gamepad_*` MCP 工具)。三者在 driver 没装时都会优雅 fallback,不影响既有部署
150152
- **剪贴板** — 于 Windows / macOS / Linux 读写系统剪贴板文本
@@ -883,10 +885,16 @@ time.sleep(10) # 录制 10 秒
883885
# 停止录制并获取动作列表
884886
actions = je_auto_control.stop_record()
885887

888+
# 回放前先清理录制内容:把连续的鼠标移动采样压缩成最后位置
889+
#(通常能把原始录制缩小一个数量级,且不改变回放行为)
890+
actions = je_auto_control.dedupe_moves(actions)
891+
886892
# 重新播放录制的动作
887893
je_auto_control.execute_action(actions)
888894
```
889895

896+
> 非破坏式录制编辑器(均返回新的 list):`dedupe_moves`(压缩鼠标移动)、`merge_sleeps`(合并连续 `AC_sleep`)、`trim_actions``insert_action``remove_action``filter_actions``adjust_delays`(缩放 `AC_sleep` 延迟)、`scale_coordinates`(以不同分辨率回放)。通过 MCP 暴露为 `ac_dedupe_moves` / `ac_merge_sleeps` / `ac_trim_actions` / `ac_adjust_delays` / `ac_scale_coordinates`
897+
890898
### JSON 脚本执行器
891899

892900
创建 JSON 动作文件(`actions.json`):
@@ -930,7 +938,7 @@ je_auto_control.execute_action([
930938
| LLM 规划器 | `AC_llm_plan`, `AC_llm_run` |
931939
| 剪贴板 | `AC_clipboard_get`, `AC_clipboard_set` |
932940
| 窗口 | `AC_list_windows`, `AC_focus_window`, `AC_wait_window`, `AC_close_window` |
933-
| 流程控制 | `AC_loop`, `AC_break`, `AC_continue`, `AC_if_image_found`, `AC_if_pixel`, `AC_if_var`, `AC_while_image`, `AC_for_each`, `AC_wait_image`, `AC_wait_pixel`, `AC_sleep`, `AC_retry` |
941+
| 流程控制 | `AC_loop`, `AC_break`, `AC_continue`, `AC_if_image_found`, `AC_if_pixel`, `AC_if_var`, `AC_while_image`, `AC_while_var`, `AC_for_each`, `AC_wait_image`, `AC_wait_pixel`, `AC_sleep`, `AC_retry`, `AC_try` |
934942
| 变量 | `AC_set_var`, `AC_get_var`, `AC_inc_var` |
935943
| 远程桌面 | `AC_start_remote_host`, `AC_stop_remote_host`, `AC_remote_host_status`, `AC_remote_connect`, `AC_remote_disconnect`, `AC_remote_viewer_status`, `AC_remote_send_input` |
936944
| 录制 | `AC_record`, `AC_stop_record`, `AC_set_record_enable` |

README/README_zh-TW.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@
6565
[`docs/source/Zh/doc/new_features/v3_features_doc.rst`](../docs/source/Zh/doc/new_features/v3_features_doc.rst)
6666

6767
**斷言**
68-
- **斷言 DSL** — 驗證畫面狀態而不只是操作:`assert_text`(OCR,`regex` + `present=False` 斷言不存在)、`assert_image``assert_pixel``assert_window`。回傳 `AssertionResult`,不符時拋出 `AutoControlAssertionException`,可選失敗截圖(`AC_assert_text / _image / _pixel / _window`)。
68+
- **斷言 DSL** — 驗證畫面狀態而不只是操作:`assert_text`(OCR,`regex` + `present=False` 斷言不存在)、`assert_image``assert_pixel``assert_window``assert_clipboard``equals` / `contains` / `regex``present=False` 可確認機密已清除)、`assert_process`(指定名稱的程序是否執行中,透過 psutil)。回傳 `AssertionResult`,不符時拋出 `AutoControlAssertionException`,可選失敗截圖(`AC_assert_text / _image / _pixel / _window / _clipboard / _process`)。
69+
- **畫面外斷言**`assert_file`(檔案存在 / 子字串 / SHA-256 / 最小大小,驗證下載或匯出結果)與 `assert_http`(http/https 端點回傳狀態碼 + 可選內文,一律帶明確 timeout)。兩者把 DSL 延伸到畫面之外,並能接到下方的組合器(`AC_assert_file / AC_assert_http`)。
70+
- **斷言組合器**`assert_all([...specs])`*軟斷言*方式跑完整批(逐一檢查、收齊所有失敗才拋出)並回傳 `GroupAssertionResult``assert_any([...specs])` 是 OR 互補(任一通過即通過、短路 — 例如登入成功對話框**重新導向其一出現即可);`assert_eventually(spec, timeout, interval)` 重試單一宣告式 spec 直到通過或逾時(例如輪詢健康檢查端點直到回傳 200,或等待下載檔出現)。皆以 spec 驅動(`{"kind": "text", "text": "Saved"}``{"kind": "http", "url": "..."}`),在 Python、JSON、MCP 中行為一致,涵蓋全部斷言種類 — text/image/pixel/window/clipboard/process/file/http(`AC_assert_all / AC_assert_any / AC_assert_eventually`)。
6971
- **媒體斷言**`assert_audio_activity`(錄音 + RMS 門檻判斷有聲 / 靜音)與 `assert_video_changes`(影片區段相鄰影格平均差異判斷動態 / 靜止);純數值核心,`sounddevice` / OpenCV 延遲載入(`AC_assert_audio / AC_assert_video_changes`)。
7072

7173
**資料驅動執行**
@@ -136,15 +138,15 @@
136138

137139
## 功能特色
138140

139-
- **QA / 測試框架** — 斷言 DSL(`assert_text` / `_image` / `_pixel` / `_window` 加上音訊/影片斷言)、資料驅動執行(CSV / JSON / SQLite / Excel → `AC_for_each_row`)、具 setup/teardown/標籤的計分 `run_suite`、JUnit + Allure 報告輸出、不穩定測試偵測與自動隔離、無障礙 / i18n 稽核(缺漏標籤、WCAG 對比度、截斷),以及並行的行動裝置矩陣。詳見 [本次更新 (2026-06)](#本次更新-2026-06)
141+
- **QA / 測試框架** — 斷言 DSL(`assert_text` / `_image` / `_pixel` / `_window` / `_clipboard` / `_process` / `_file` / `_http` 加上音訊/影片斷言,以及 `assert_all` / `assert_any` / `assert_eventually` 組合器)、資料驅動執行(CSV / JSON / SQLite / Excel → `AC_for_each_row`)、具 setup/teardown/標籤的計分 `run_suite`、JUnit + Allure 報告輸出、不穩定測試偵測與自動隔離、無障礙 / i18n 稽核(缺漏標籤、WCAG 對比度、截斷),以及並行的行動裝置矩陣。詳見 [本次更新 (2026-06)](#本次更新-2026-06)
140142
- **滑鼠自動化** — 移動、點擊、按下、釋放、拖曳、滾動,支援精確座標控制
141143
- **鍵盤自動化** — 按下/釋放單一按鍵、輸入字串、組合鍵、按鍵狀態偵測
142144
- **圖像辨識** — 使用 OpenCV 模板匹配在螢幕上定位 UI 元素,支援可設定的偵測閾值
143145
- **Accessibility 元件搜尋** — 透過作業系統無障礙樹(Windows UIA / macOS AX)依名稱/角色定位按鈕、選單、控制項
144146
- **AI 元件定位(VLM)** — 用自然語言描述 UI 元素,交由視覺語言模型(Anthropic / OpenAI)取得螢幕座標
145147
- **OCR** — 三個可插拔後端(Tesseract 用於 ASCII、EasyOCR 不需外部執行檔且支援 CJK、PaddleOCR 中/日/韓品質最佳),統一 API 與標準語言代碼;後端由 `backend=` 參數、`AUTOCONTROL_OCR_BACKEND` 環境變數或自動偵測決定。可搜尋、點擊或等待文字出現;支援 regex 搜尋與整塊區域 dump
146148
- **LLM 動作規劃器** — 用 Claude 把自然語言描述翻譯成驗證過的 `AC_*` 動作清單
147-
- **執行期變數與流程控制** — 執行時 `${var}` 取代,加上 `AC_set_var` / `AC_inc_var` / `AC_if_var` / `AC_for_each` / `AC_loop` / `AC_retry` 讓腳本資料驅動
149+
- **執行期變數與流程控制** — 執行時 `${var}` 取代,加上 `AC_set_var` / `AC_inc_var` / `AC_if_var` / `AC_for_each` / `AC_loop` / `AC_while_var` / `AC_retry` / `AC_try` 讓腳本資料驅動`AC_while_var` 在變數比較成立時持續迴圈(每輪重新判斷,`max_iter` 安全上限);`AC_try` 提供 try/catch/finally:`body` 失敗時改走 `catch` 復原分支而非中止、`finally` 必定執行、錯誤透過 `error_var` 暴露、可在清理後 `reraise`(迴圈 `break`/`continue` 仍能穿透)
148150
- **遠端桌面** — 用 token 認證的 TCP 協定串流本機畫面並接收輸入,**** 連線到他機觀看與控制(host + viewer GUI 皆內建)。可選 TLS(HTTPS 級加密)、WebSocket 傳輸(``ws://`` + ``wss://``,穿牆/瀏覽器友善)、持久化 9 位數 Host ID、host→viewer 音訊串流、雙向剪貼簿同步(文字 + 圖片)、分塊檔案傳輸(拖放 + 進度條;任意目的路徑;無大小上限)。另含資料夾同步(增量鏡像 — 本地刪除不會傳出去)與自架 coturn TURN 設定包產生器(turnserver.conf + systemd unit + docker-compose + README)。**AnyDesk 風格彈出視窗**:viewer 認證成功後遠端桌面會開在獨立的可調整大小頂層視窗,控制面板維持簡潔;Remote Desktop 子分頁外層包了 `QScrollArea`,小視窗下可捲動、4K 螢幕下會延展到整寬。同時可由 headless API 與 MCP 工具(`ac_remote_*`)直接驅動
149151
- **驅動層輸入後端(可選)** — 針對忽略 SendInput(Win)或 XTest(Linux)的遊戲/應用:**Interception driver 後端**(Windows,HID 層鍵鼠注入,使用 Oblita WHQL-signed driver,以 `JE_AUTOCONTROL_WIN32_BACKEND=interception` 啟用)、**uinput 後端**(Linux,kernel `/dev/uinput` 合成 HID 裝置,以 `JE_AUTOCONTROL_LINUX_BACKEND=uinput` 啟用),以及 **ViGEm 虛擬手把**(Windows,針對只認手把的遊戲,提供虛擬 Xbox 360 手把 + 友善的 button / dpad / stick / trigger API,並暴露為 `AC_gamepad_*` 執行器指令與 `ac_gamepad_*` MCP 工具)。三者在 driver 沒裝時都會優雅 fallback,不影響既有部署
150152
- **剪貼簿** — 於 Windows / macOS / Linux 讀寫系統剪貼簿文字
@@ -883,10 +885,16 @@ time.sleep(10) # 錄製 10 秒
883885
# 停止錄製並取得動作列表
884886
actions = je_auto_control.stop_record()
885887

888+
# 回放前先清理錄製內容:把連續的滑鼠移動取樣壓縮成最後位置
889+
#(通常能把原始錄製縮小一個數量級,且不改變回放行為)
890+
actions = je_auto_control.dedupe_moves(actions)
891+
886892
# 重新播放錄製的動作
887893
je_auto_control.execute_action(actions)
888894
```
889895

896+
> 非破壞式錄製編輯器(皆回傳新的 list):`dedupe_moves`(壓縮滑鼠移動)、`merge_sleeps`(合併連續 `AC_sleep`)、`trim_actions``insert_action``remove_action``filter_actions``adjust_delays`(縮放 `AC_sleep` 延遲)、`scale_coordinates`(以不同解析度回放)。透過 MCP 暴露為 `ac_dedupe_moves` / `ac_merge_sleeps` / `ac_trim_actions` / `ac_adjust_delays` / `ac_scale_coordinates`
897+
890898
### JSON 腳本執行器
891899

892900
建立 JSON 動作檔案(`actions.json`):
@@ -930,7 +938,7 @@ je_auto_control.execute_action([
930938
| LLM 規劃器 | `AC_llm_plan`, `AC_llm_run` |
931939
| 剪貼簿 | `AC_clipboard_get`, `AC_clipboard_set` |
932940
| 視窗 | `AC_list_windows`, `AC_focus_window`, `AC_wait_window`, `AC_close_window` |
933-
| 流程控制 | `AC_loop`, `AC_break`, `AC_continue`, `AC_if_image_found`, `AC_if_pixel`, `AC_if_var`, `AC_while_image`, `AC_for_each`, `AC_wait_image`, `AC_wait_pixel`, `AC_sleep`, `AC_retry` |
941+
| 流程控制 | `AC_loop`, `AC_break`, `AC_continue`, `AC_if_image_found`, `AC_if_pixel`, `AC_if_var`, `AC_while_image`, `AC_while_var`, `AC_for_each`, `AC_wait_image`, `AC_wait_pixel`, `AC_sleep`, `AC_retry`, `AC_try` |
934942
| 變數 | `AC_set_var`, `AC_get_var`, `AC_inc_var` |
935943
| 遠端桌面 | `AC_start_remote_host`, `AC_stop_remote_host`, `AC_remote_host_status`, `AC_remote_connect`, `AC_remote_disconnect`, `AC_remote_viewer_status`, `AC_remote_send_input` |
936944
| 錄製 | `AC_record`, `AC_stop_record`, `AC_set_record_enable` |

docs/source/Eng/doc/new_features/new_features_doc.rst

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -363,11 +363,42 @@ over a list while the body sees the current item.
363363
}],
364364
])
365365

366-
Comparison operators for ``AC_if_var``: ``eq``, ``ne``, ``lt``, ``le``,
367-
``gt``, ``ge``, ``contains``, ``startswith``, ``endswith``.
366+
Comparison operators for ``AC_if_var`` (and ``AC_while_var``): ``eq``,
367+
``ne``, ``lt``, ``le``, ``gt``, ``ge``, ``contains``, ``startswith``,
368+
``endswith``.
369+
370+
``AC_while_var`` loops a ``body`` while a variable comparison holds. The
371+
condition is re-evaluated against the live scope before every iteration,
372+
so a body that mutates the variable (e.g. ``AC_inc_var``) terminates the
373+
loop; ``max_iter`` (default 1000) caps a condition that never turns
374+
false. ``AC_break`` / ``AC_continue`` work as in any loop::
375+
376+
executor.execute_action([
377+
["AC_set_var", {"name": "i", "value": 0}],
378+
["AC_while_var", {
379+
"name": "i", "op": "lt", "value": 5,
380+
"body": [["AC_inc_var", {"name": "i"}]],
381+
}],
382+
])
383+
384+
``AC_try`` adds try / catch / finally. When ``body`` raises, the
385+
``catch`` branch runs instead of aborting the script; ``finally`` always
386+
runs (on success, on a caught error, or while a ``reraise`` / loop
387+
break/continue propagates). The error text is exposed to ``error_var``
388+
for the ``catch`` branch to inspect, and ``reraise=true`` re-raises after
389+
cleanup::
390+
391+
executor.execute_action([
392+
["AC_try", {
393+
"body": [["AC_click_image", {"image": "dialog_ok.png"}]],
394+
"catch": [["AC_set_var", {"name": "dismissed", "value": False}]],
395+
"finally": [["AC_screenshot", {"file_path": "after.png"}]],
396+
"error_var": "err",
397+
}],
398+
])
368399

369400
Action-JSON commands: ``AC_set_var``, ``AC_get_var``, ``AC_inc_var``,
370-
``AC_if_var``, ``AC_for_each``.
401+
``AC_if_var``, ``AC_for_each``, ``AC_while_var``, ``AC_try``.
371402

372403
GUI: **Variables** tab — live view of ``executor.variables`` with
373404
single-set, JSON seed, and clear-all controls; reflects what

0 commit comments

Comments
 (0)