Files
2026-07-13 12:55:23 +08:00

10 KiB
Raw Permalink Blame History

MacroCLI Demo — gedit 完整测试方案

本文档记录 MacroCLI 在 Linux 无头服务器 + Xvfb + noVNC 环境下的完整测试过程, 包括虚拟桌面搭建、VNC 远程查看、宏执行和录制回放的全链路验证。


环境架构

本地浏览器
    │  SSH 隧道 (16080 → 16080)
    ▼
远程 Linux 服务器
    │
    ├─ Xvfb :99         虚拟显示器 1920x1080
    ├─ openbox          窗口管理器
    ├─ x11vnc           VNC 服务 (只监听 localhost:5900)
    ├─ websockify       WebSocket → VNC 代理 (16080)
    └─ gedit            被操控的 GUI 应用

第一步:安装依赖

# 虚拟显示器和 VNC
sudo apt install xvfb x11vnc openbox xdotool wmctrl

# GUI 应用(demo 目标)
sudo apt install gedit

# noVNC(浏览器查看桌面)
sudo apt install novnc websockify

# AT-SPI 语义控制(可选,GTK 应用)
sudo apt install python3-pyatspi

# MacroCLI Python 依赖
conda activate macrocli   # 或你的环境名
pip install -e "path/to/macrocli/agent-harness[visual]"
# 等价于: pip install mss Pillow numpy pynput

第二步:启动虚拟桌面

# 1. 启动 Xvfb 虚拟显示器(:99 号,1920x1080 24位色)
Xvfb :99 -screen 0 1920x1080x24 -ac &

# 2. 设置 DISPLAY(后续所有命令都需要)
export DISPLAY=:99

# 3. 启动窗口管理器(让窗口能正常显示和拖动)
openbox &

# 4. 设置桌面背景色(避免纯黑)
xsetroot -solid gray

# 5. 启动 VNC 服务,只监听本地,允许多连接
x11vnc -display :99 -nopw -listen localhost -rfbport 5900 \
    -forever -shared -bg -o /tmp/x11vnc.log

# 6. 启动 noVNC websocket 代理
websockify --web /usr/share/novnc 16080 localhost:5900 &

# 验证服务启动
ss -tlnp | grep -E "5900|16080"

期望输出:

LISTEN  127.0.0.1:5900   ← x11vnc
LISTEN  0.0.0.0:16080    ← websockify

第三步:连接 VNC 查看桌面

本地机器开 SSH 隧道:

ssh -L 16080:localhost:16080 user@your-server -N

然后浏览器访问:

http://localhost:16080/vnc.html

点击 Connect,无需密码,即可看到虚拟桌面。

注意: 如果 Connect 后显示"连接已中断",通常是 x11vnc 的客户端连接数超限。 重启 x11vnc 并加 -shared 参数即可:

pkill x11vnc
x11vnc -display :99 -nopw -listen localhost -rfbport 5900 -forever -shared -bg

第四步:检查后端可用性

export DISPLAY=:99
conda activate macrocli
cd path/to/macrocli/agent-harness

cli-anything-macrocli --json backends

期望输出(所有后端 available: true):

{
  "native_api":    { "available": true,  "priority": 100 },
  "gui_macro":     { "available": true,  "priority": 80  },
  "visual_anchor": { "available": true,  "priority": 75  },
  "file_transform":{ "available": true,  "priority": 70  },
  "semantic_ui":   { "available": true,  "priority": 50  },
  "recovery":      { "available": true,  "priority": 10  }
}

Demo A:手写宏执行

A1. 打开 gedit

cli-anything-macrocli --json macro run gedit_new_window

VNC 里能看到 gedit 窗口弹出。

输出示例:

{
  "success": true,
  "telemetry": { "duration_ms": 39, "backends_used": ["native_api", "semantic_ui"] }
}

实现细节: gedit_new_windownative_apistart_process action 后台 启动 gedit(不等待进程退出),然后 semantic_uiwait_for_window 等待窗口出现。

A2. 输入文字并保存

cli-anything-macrocli --json macro run gedit_type_and_save \
    --param "text=Hello from MacroCLI!"

VNC 里能看到文字逐字输入到 gedit,然后触发 Ctrl+S。

输出示例:

{
  "success": true,
  "steps": [
    { "backend_used": "semantic_ui",   "output": {"focused": "gedit", "method": "wmctrl"} },
    { "backend_used": "visual_anchor", "output": {"typed": 20} },
    { "backend_used": "visual_anchor", "output": {"hotkey": "ctrl+s"} }
  ],
  "telemetry": { "duration_ms": 774 }
}

实现细节: 三个后端串联——semantic_ui 用 wmctrl 聚焦窗口,visual_anchor 用 pynput 注入键盘事件,visual_anchor 发送 Ctrl+S 快捷键。

A3. 另存为指定路径

cli-anything-macrocli --json macro run gedit_save_as \
    --param output_path=/tmp/macrocli_demo.txt

执行过程(可在 VNC 观察):

  1. Ctrl+Shift+S 弹出 Save As 对话框
  2. Ctrl+L 打开路径输入框
  3. Ctrl+A 清空已有内容
  4. 输入 /tmp/macrocli_demo.txt
  5. Enter 确认
# 验证文件已创建
cat /tmp/macrocli_demo.txt

Demo B:录制宏(核心功能)

录制功能把一次手工操作自动转成可重复调用的宏。

录制原理

用户操作 GUI
    │
pynput 监听鼠标键盘事件
    │
每次点击:
  xdotool getwindowfocus → 获取焦点窗口名称和位置
  计算点击在窗口内的百分比坐标 (x_pct, y_pct)
  → 生成 click_relative 步骤(窗口锚点,不依赖绝对坐标)
    │
键盘输入:
  累积字符(含空格)→ 生成 type_text 步骤
  快捷键组合 → 生成 hotkey 步骤
    │
Ctrl+Alt+S 停止录制
    │
自动写出 YAML 宏文件

为什么用窗口锚点而不是绝对坐标: 点击空白文本区会截到全白图片,模板匹配无法识别。改用窗口相对坐标 (click_relative),回放时先找到窗口位置,再按百分比算出实际坐标, 窗口移动到任何地方都能正确点击。

录制操作

# 开始录制,命名为 my_workflow
cli-anything-macrocli macro record my_workflow \
    --output-dir /tmp/my_recording \
    --timeout 30    # 30秒后自动停止,或手动 Ctrl+Alt+S

终端显示:

Recording 'my_workflow'. Press Ctrl+Alt+S to stop.
[recorder] Recording 'my_workflow'. Press Ctrl+Alt+S to stop.

现在操作 gedit(录制器会捕获这些动作):

  1. 在 VNC 里点击 gedit 文本区
  2. 输入一段文字
  3. 按 Ctrl+S 保存

按 Ctrl+Alt+S 停止(或等待超时),自动生成:

/tmp/my_recording/
├── my_workflow.yaml              ← 宏定义文件
└── my_workflow_templates/        ← 有特征区域的截图模板
    └── step_001_click.png        ← 若点击区域有特征才会保存

生成的 YAML 示例:

name: my_workflow
steps:
  - id: step_001_click
    backend: visual_anchor
    action: click_relative         # 窗口锚点,不是绝对坐标
    params:
      window_title: gedit          # 从 xdotool getwindowfocus 获取
      x_pct: 0.35                  # 点击位置在窗口宽度的 35%
      y_pct: 0.33                  # 点击位置在窗口高度的 33%

  - id: step_002_type
    backend: visual_anchor
    action: type_text
    params:
      text: hello world            # 空格正确合并(不再被切成 hotkey)

  - id: step_003_hotkey
    backend: visual_anchor
    action: hotkey
    params:
      keys: ctrl+s

回放录制的宏

# 先清空 gedit 内容
# 然后回放
cli-anything-macrocli --json macro run my_workflow \
    --macro-file /tmp/my_recording/my_workflow.yaml

实际测试输出:

{
  "success": true,
  "telemetry": {
    "duration_ms": 486,
    "steps_run": 3,
    "backends_used": ["visual_anchor"]
  }
}

VNC 截图验证(hello world 出现在 gedit):

gedit 窗口标题: macrocli_test_final.txt (/tmp) - gedit
内容: hello world
状态: 已保存(标题栏无 * 号)

Demo Ctransform_jsonfile_transform 后端)

⚠️ 未在本次测试中验证,仅供参考。

不需要 GUI,直接操作 JSON 文件:

# 创建测试文件
echo '{"app": "draw.io", "version": 1}' > /tmp/config.json

# 用宏修改嵌套 key
cli-anything-macrocli --json macro run transform_json \
    --param file=/tmp/config.json \
    --param key=settings.theme \
    --param value=dark

# 验证
cat /tmp/config.json
# {"app": "draw.io", "version": 1, "settings": {"theme": "dark"}}

常见问题

Q: macro run gedit_new_window 超时 30 秒

原因:run_command 会等待进程退出,GUI 应用永远不会退出。 解决:改用 start_process action(本项目已修复)。

Q: wait_for_window 找不到窗口

原因:conda run 会清除 DISPLAY 环境变量。 解决:激活 conda 环境后直接运行,不要用 conda run

conda activate macrocli
export DISPLAY=:99
cli-anything-macrocli ...

Q: VNC Connect 后显示"连接已中断"

原因:x11vnc 默认不允许多个客户端同时连接。 解决:重启 x11vnc 并加 -shared

pkill x11vnc
x11vnc -display :99 -nopw -listen localhost -rfbport 5900 -forever -shared -bg

Q: 录制回放时点击位置不准

原因:窗口大小与录制时不同,百分比坐标偏移。 解决:确保回放时窗口大小与录制时一致,或调整宏里的 x_pct/y_pct

Q: 模板图全白,click_image 永远超时

原因:点击了空白区域(如文本编辑区),截图无特征。 解决:录制器已自动检测低方差图片,改用 click_relative 替代。


验证结果汇总

后端 结果 耗时
gedit_new_window native_api + semantic_ui ~40ms
gedit_type_and_save semantic_ui + visual_anchor ~774ms
gedit_save_as semantic_ui + visual_anchor ~1847ms
transform_json file_transform ⚠️ 未验证
macro record + 回放 visual_anchor ~486ms

对接其他应用

同样的流程适用于任何 Linux GUI 应用:

应用 推荐后端 说明
Inkscape native_api (--actions) 有完整命令行接口
GIMP native_api (Script-Fu) 脚本接口强大
LibreOffice native_api (--headless) UNO API
draw.io file_transform + visual_anchor XML 格式可直接编辑
任意 GUI 应用 macro record + visual_anchor 录制一次,窗口锚点回放