真正的跨平台 AI 自动化框架,甚至还支持鸿蒙

之前介绍过最好用的 Flutter AI 测试框架,然后有很多人在问有没有原生平台的,刚好就看到了一个原生平台的开源测试框架 agent-device ,甚至它还支持鸿蒙:

agent-device 是专门为 AI Agent 设计的设备自动化 CLI 工具 ,可以类比 Vercel 的 agent-browser 是给 AI 用的浏览器自动化工具那样,agent-device 是给 AI 用的 App 准备的标准化通道,例如:

sql 复制代码
agent-device apps --platform ios
agent-device open <app> --platform ios
agent-device snapshot -i
agent-device press @e12
agent-device diff snapshot -i
agent-device close

比如这里的 snapshot -i ,它会把当前 UI 转成 Agent 更容易理解的结构化树,同时给可交互元素生成 @e1@e2 这种引用。

它最核心的能力是不用截图去识别控件agent-device 是通过检查真实 App UI,输出无障碍访问树(accessibility snapshot) ,然后将 UI 中的可交互元素映射为短引用(@e1, @e2, @e3),让 AI 知道屏幕上有什么:

java 复制代码
agent-device snapshot -i
# @e1 [heading] "Settings"
# @e2 [button] "Sign In"
# @e3 [text-field] "Email"

这样 AI 就可以直接用 @e3 操作 「[text-field] "Email"」,不需要自己去读坐标,也不需要每次截图分析,同时功能上支持:

  • 截图:用于 debug/回放
  • 视频录制(record):录制操作流程
  • 日志(logs):app 日志流
  • 网络流量(network):HTTP 请求抓包
  • 性能采样(perf):CPU/内存
  • 崩溃上下文:crash 时的现场信息

甚至它还支持工作流回放,将 AI 探索过的交互录制成 .ad 脚本,然后可以在 CI、本地、重复场景中回放执行,等效于 e2e 测试用例。

agent-device 的场景其实就是:Agent 写代码,之后安装到对应设备,然后 agent-device 打开 App ,通过 snapshot 读取当前 UI 结构,之后 Agent 根据 @e1 / @e2 / selector 操作 UI ,然后得到 「截图 / 录屏 / 日志 / 网络 / 性能」等证据存档,最后再让 Agent 根据测试结果修复问题。

当然,最最最最重要的是它是多平台支持:

  • iOS 真机/Simulator(XCTest 驱动)
  • Android Emulator / 真机(ADB 驱动)
  • tvOS / Android TV
  • macOS App
  • Linux (AT-SPI)
  • HarmonyOS (HDC 驱动)

整个流程大概如下图所示:

如果拆开来看,整个架构大概如下:

  • Session 模型 :先 open 一个设备会话,后续所有命令在这个 session 上下文内执行(锁住设备资源、保持状态)
  • Daemon 架构 :后台运行一个长驻进程(daemon),CLI 命令通过 IPC 与 daemon 通信
  • 提升效率 :snapshot 使用无障碍树而不是视觉截图,让 AI 用最少 token 获取 UI 信息;-i(interactive only)进一步只返回可交互元素,而且截图测试的方式是真的死慢
  • 语义引用系统 (Refs):@e1~@eN 是每次 snapshot 后分配的临时引用,命令可直接用 ref 而不是坐标,降低 AI 犯错概率,比如坐标在滚动后就失效,但 ref 是语义感知的
  • Interactor 模式 :每个平台实现一个统一的 Interactor 接口(tap, swipe, snapshot, screenshot...),核心调度层面对接口编程,平台差异被隔离在各自的 platforms/ 目录
  • 可控范围src/core/capabilities.ts 给每条命令定义哪些平台/设备类型支持,防止 AI 调用不支持的命令,会在 admission 阶段直接报错而不是无意义地发送到设备

当然,也存在一些平台限制,例如:

局限 具体表现
pinch/rotate 手势 仅支持 iOS Simulator + Android,HarmonyOS 不支持 pinch/rotate
read(文本识别) 只支持 iOS/Android
logs/network/perf HarmonyOS 均不支持
clipboard HarmonyOS 需要 app-level 授权,读写均可能失败
权限管理 HarmonyOS 仅支持 grant,deny/reset 未实现

然后在平台链路上,每个平台都有自己一套实现,从代码看,你会看到一套非常复杂的工作流程。

iOS 体系

首先是 iOS,iOS 核心用的还是我们熟悉的 XCTest Runner ,iOS 本身没有开放的 UI 自动化 API 给外部进程用,这里agent-device 的做法是:

在目标设备上动态构建并运行一个 XCTest bundle(.xctestrun),通过 XCTest 框架的 XCUITest 能力操控 UI,然后在这个 Runner 进程和 CLI 之间建立 TCP 通信通道。

更具体的结构是:

  • runner-xctestrun.ts :动态生成 .xctestrun 配置文件(相当于 Xcode 的测试 scheme)、构建参数、signing 配置
  • runner-session.ts :管理 Runner 进程的生命周期,启动 xcodebuild test-without-building、等待 ready、保持 session 热启动
  • runner-transport.ts :TCP 通信层,发送 JSON 命令到 Runner,接收响应,超时/重连处理
  • runner-client.ts :命令执行的上层入口,完整的故障恢复逻辑
  • runner-contract.ts :Runner 通信协议定义,命令类型枚举
  • interactions.ts :将 tap/swipe/type 等抽象命令翻译为 Runner 命令
  • xml.ts :解析 XCTest 返回的 Accessibility XML 快照
  • simctl.ts :调用 xcrun simctl 操作模拟器(boot/shutdown/install)
  • devicectl.ts : 调用 Xcode 15+ 的 xcrun devicectl 操作真机
  • perf.ts :通过 xcodebuild + Instruments XML 采集性能数据(CPU/内存/帧率)

这里最有意思的就是Runner 故障恢复机制 ,由于 XCTest Runner 是一个独立进程,TCP 通信可能在命令执行过程中断(网络抖动、Runner 崩溃),所以项目设计了一套 lifecycle 状态机

  • 每个命令发出前打上唯一 commandId

  • 如果传输中断,发送 status 命令查询该 commandId 的状态

  • 根据 lifecycleState 决策:

    • completed(已完成):从 lifecycleResponseJson 取结果,session 保留
    • failed(已失败):抛出 Runner 报告的错误,session 保留
    • accepted/started(仍在飞行中): 抛 in-flight 错误,session 保留
    • 未知状态 : 保守路径:invalidate session,重新启动

比如 CLI 发出了一个 tap 命令,TCP 连接中途断了,CLI 根本不知道 Runner 是否已经执行了这个 tap,如果重试可能会 double-tap ,但是如果不重试,可能 tap 根本没发生,这时候就需要通过 lifecycle 判断。

另外 macOS 和 iOS 共用了一套后端,所以逻辑基本可以复用,另外截图功能上也是做了很多细节处理,比如:

状态栏内容覆盖,将时间/电量伪造为固定值,让截图更容易区分。

Android

Android 平台就是 ADB + 自定义 Snapshot Helper APK ,类似 iOS 的 Runner transport,只是 Android 的走的是 adb 命令(adb shelladb exec-outadb install 等):

  • 本地 adb -s <serial> 直连
  • Provider 注入模式(可以支持云端/远程 Android 设备)
  • 文本注入 provider 覆盖(用于非 ASCII 字符)

Android 平台最有意思的就是双引擎架构快照实现

为什么需要自定义 Helper APK?因为 Android 原生的 uiautomator dump 有严重缺陷:

  • 经常超时(UI 繁忙时 hang 住)
  • 返回的节点数有限,无法获取完整 can-scroll-forward/backward 属性
  • 不支持多窗口

所以 agent-device 开发了一个 android-snapshot-helper APK(项目根目录有独立子包),通过 Android Instrumentation 框架运行,能返回更完整和稳定的 UI 树 XML,同时它还维护了一个 persistent session(长驻后台进程),避免每次快照都 cold start ,比如:

  • snapshot-helper-install.ts : 检测版本/安装 APK
  • snapshot-helper-session.ts :长驻 session 管理
  • snapshot-helper-capture.ts :通过 instrumentation 调用获取 XML

另外一个就是滚动内容提示,这个也挺有意思,Android 快照时,agent-device 会额外执行 adb shell dumpsys activity top,从 Activity 状态中推断每个 ScrollView/RecyclerView 是否还有隐藏内容(上方/下方),然后标注到节点上,让 AI 知道「这个列表下面还有更多内容」。

Linux

Linux 平台用的就是AT-SPI2(Assistive Technology Service Provider Interface)+ Python 桥 ,之前 agent-device 也尝试过 node-gtk(Node.js 原生绑定),但 ABI 不兼容、CI 编译问题太多,所以现在改用 Python3 + python3-gi(PyGObject)调用 AT-SPI2,Node.js 负责启动 Python 子进程、读取 JSON 输。

AT-SPI2 是 Linux 桌面辅助功能标准(GNOME/KDE 等都支持),类似 macOS 的 Accessibility API,每个 GTK/Qt 窗口会把自己的 UI 树注册到 D-Bus 上,通过 AT-SPI2 可以遍历所有应用的 UI 节点。

鸿蒙

最后鸿蒙平台主要通过 HDC 链路来适配 ,可以类比 Android 的 ADB,HarmonyOS 使用的是 hdc 命令行工具,核心是 runHarmonyHdc(device, args) 会自动带上 -t <serial> 设备序列号,与 ADB 的用法完全镜像。

UI 快照层 ArkUI Hierarchy(等价于 iOS 的 XCTest / Android 的 ViewHierarchy) ,比如 hdc shell uitest dumpLayout -p /data/local/tmp/xxx.json ,最终得到 @e1, @e2... 等节点,最重要的是他还出来了鸿蒙本身的一个问题兼容:

uitest uiRecord 卡死时 dumpLayout 会 hang,所以项目加了预检,发现 stuck 进程时直接报错提示 reboot。

所以鸿蒙的 snapshot 是通过 uitest dumpLayout 生成 ArkUI component tree,然后支持 interactiveOnlycompactdepthscoperaw 模式,同时通过 snapshot_display 进行截图。

还有一些有意思的,比如 Alert 识别(纯 ArkUI 节点分析),不像 iOS 有原生的 alert API,HarmonyOS 的弹窗是普通 ArkUI 组件,所以 agent-device 是通过关键词匹配识别弹窗并提取按钮坐标 ,同时支持中英文按钮文本(确定/取消/允许/拒绝/知道了...):

less 复制代码
if (type.includes('dialog') || type.includes('alert') || 
    label.includes('暂无可用打开方式') || label.includes('权限') ...) {
  // 识别为弹窗,提取 buttons
}

最后

对比 Appium、Detox、Maestro 这些传统 mobile automation framework, agent-device 是为 AI Agent 优化的,更适合 AI 自动化测试,当然它对人写的场景就不是很友好了,如果真要对比,我理解是:

  • Appium / Detox / Maestro: 支持人写,重点是稳定、可维护、CI 回归
  • agent-device:面向 AI Agent 现场探索、验证、debug、采证、沉淀 replay

目前看起来它还不是特别适合大规模的稳定回归测试,一些复杂 UI 的测试也还不够稳定,所以它更适合作用 Agent 开发过程中的实时反馈和修复支持,让 Agent 改完代码后自己跑起来看、自己点、自己截图、自己抓日志,然后基于真实结果继续修,而且支持原生跨平台,最重要是,开源,免费,MIT。

链接

github.com/callstack/a...

相关推荐
AI浩1 小时前
【数据处理】基于 SAM3 的 LabelMe 标注统一校正方法
android·开发语言·kotlin
IT_陈寒1 小时前
Redis的LRU淘汰策略坑了我一天血汗
前端·人工智能·后端
晓得迷路了1 小时前
栗子前端技术周刊第 132 期 - date-fns 支持 Temporal、npm 攻击事件、VoidZero...
前端·javascript·css
雨季mo浅忆1 小时前
记录Vue3项目中的各类问题
前端·bug·vue3
亿元程序员1 小时前
Cocos游戏开发中的弯的箭头游戏效果
前端
ct9781 小时前
Promise
前端·javascript·vue.js
怕浪猫1 小时前
Electron 开发实战(十一):自动更新机制|服务架构、公私网更新、版本回滚全解
前端·javascript·electron
AI视觉网奇1 小时前
three-bvh-csg glb分割
开发语言·前端·javascript
私人珍藏库1 小时前
【Android】 VidFetch一键下载各大平台视-内置播放器
android·app·工具·软件·多功能