dsh-mobile-use

remotetested: passnpmMIT

Your phone, live in the DSH right sidebar: one UI read costs 120 ms and 200-1300 tokens, where a screenshot costs 0.5-3.2 s and 1.5-2k image tokens; a tap lands on the real device in 61 ms, and a circled area comes back with its controls. You can tell what is on screen, and whether a tap landed, wit

下载量 / Downloads
8,355
依赖体积 / node_modules
7.25 MB
测试时间 / Tested
2026-11-06
DSH 版本 / Version
0.2.2-rc.1

Install

dsh plugin --profile web add dsh-mobile-use

Sandbox test results

StageResult
1 install✓
2 list✓
3 mount✓
4 boot—

Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).

README

dsh-mobile-use · 把真手机装进 DSH

右栏就是你手机的画面:点一下是设备上点一下,圈一处再写一句话,带圈图和圈内控件一起回到会话。

模型不用截图也知道屏上有哪些字、哪个按钮能点、刚才点了之后变了什么。装一次,DSH 里所有会话都能用——不需要 MCP 行、不需要额外 agent、不上传任何画面。

git clone https://github.com/regrevia/dsh-mobile-use.git dsh-mobile-use
# 在 DSH 里:plugin_manager action=install_bundle target=$HOME/dsh-mobile-use

环境变量(都可选):ADB(adb 路径)、ANDROID_SERIAL(默认设备)、FFMPEG(转码路径)。见 .env.example。

宿主需要 adb(Android platform-tools);镜像还要 ffmpeg。设备端辅助程序(uiautomator2)随包附带,首次使用自动推送。

三个真正不同的地方

① 实时镜像,不是截图循环。 侧栏「实时ADB」走 screenrecord H.264 → 宿主 ffmpeg 抽帧转 fMP4 → MSE 播放:首帧 1380 ms,画面一变到上屏 +163 ms,静止时约 1 帧/秒(内容驱动),最后一个观众走后留 20 秒,重开实测 2440 ms → 18 ms。点按按真实媒体矩形归一化,缩放、平移、横竖屏同一套算法。

② 圈选标注,把「这里」说清楚。 在画面上圈一块,连圈图 + 圈内控件 + 前 12 秒操作时间线 + 最近 6 秒 6 帧拼图一起推回当前会话。拼图取自内存最近 40 帧,265 ms 建好、112 KB,不碰设备、不 seek 还在写的录屏文件。

③ 读界面,不截图。 设备端常驻 uiautomator2:adb_ui 一次 120 ms 返回「文字 + 资源 id + 中心坐标 + ref」,压成 200–1300 token 纯文本;同样一次确认,screencap -p 要 0.5–3.2 s、0.3–8.9 MB,再花一次带图推理。自绘/Flutter 文本树为空时自动补一层本机 Vision OCR 兜底。不想走视觉模型时还有两条免视觉通道:adb_look 把屏幕压成颜色网格并给出区域差异(热 32–41 ms),adb_ocr 直接认右栏直播帧(热 110–116 ms)。

作品牌差异一句话:同类插件多在让 DSH 的网页适配手机或让手机连回电脑,这个方向相反——把手机装进 DSH,让 AI 直接操作真机。

同一块地盘上还有谁

手机方向在 DSH 生态里已经有人做,各自解决的其实不是同一件事(摘自插件市场当前介绍):

  • 从手机连回电脑:liguobao/ds-harness-remote、wenbin-wb/dsh-bridge —— 把正在跑的会话推到手机浏览器里继续,手机是显示器。
  • iOS 设备上的操作:ZSeven-W/dsh-ios —— 模拟器或 USB 连接的 iPhone,按无障碍标识或 OCR 操作,带可点的侧栏面板。

这个插件是第三条:Android 真机、画面进右栏、标注带回去。差别不在「工具数量」,而在模型看到的就是设备本身——文本树 120 ms 给出文字与坐标,画面一变 163 ms 上屏,圈一处就把「这里」变成一条带图的消息。

为什么

原做法是 adb exec-out screencap 出 PNG,再 read_image 让模型看图。一次「确认页面对不对」要花:一次截图进程 + 一张几百 KB~9 MB 的图 + 一次带图的模型步。

实测(小米平板 8,3200×2136,Android 15,2026-10)对比同一动作的两种取法:

取法 · 耗时 · 返回体积 · 模型侧成本

adb -s X exec-out screencap -p · 0.5 s(纯色页)/ 3.2 s(相机页) · 0.3–8.9 MB PNG · 1 张图 ≈ 1.5–2 k token + 一次带图推理

adb -s X exec-out uiautomator dump /dev/tty · 0.33 s(静态页)/ 2.2 s(持续动画页) · 8 KB XML · 压成 460–2872 字符 ≈ 200–1300 token 纯文本

uiautomator dump --compressed · 2.1–2.4 s · 5.6 KB · 不要用,慢 6 倍换 30% 体积

dumpsys activity 取前台 Activity · 0.07–0.09 s · 一行 · 判断「有没有进目标页」用它

logcat -d -t 200 · 0.11–0.14 s · 数 KB · 看报错用它

耗时不是全部:截图那条路每次还要一次 read_image 往返,文本树直接把「文字 + 资源 id + 中心坐标」写进上下文,点击不再需要算坐标。

工具

工具 · 作用

adb_ui · 读界面文本树:ref、控件类型(语义角色:Text / Btn / Img / Input / Switch / List …)、文字、#资源id、@中心坐标,尾部 * 可点击 / ~ 可滚动 / [x] 勾选 / [off] 不可用。支持 filter、full、depth(只列到第 N 层)、max_nodes(默认 400,打满会明说「已截断」并给收窄办法)、wait_for_text / wait_for_id / wait_for_activity / wait_activity_gone(等离开启动页/登录页)/ wait_until_gone(替代 sleep + 反复截图);within_ref / within_rect 只看一块(列表里某一行的内部结构、抽屉里的按钮),框外控件不占行、深度按框内重算;等待也能用 wait_for_xpath / wait_xpath_gone

adb_wait · 只等条件、不返回整棵树,省 token(回执带「N 次轮询」看等待花了多少 dump)(within_ref / within_rect 只看框里的控件,等某一行里的按钮):text / id / desc / gone / texts(全出现)/ any_texts(任一出现)/ activity / activity_gone(等离开启动页/登录页)/ stable(界面静止)。超时会说清停在哪个页面、能点什么;until 等同一个控件进入某状态(enabled / clickable / checked / focused)才返回,灰按钮不会误判成等到;dismiss: true 被权限/升级/评分弹窗挡住时自动点掉确认按钮(最多 2 次)再接着等,回执列 dismissed;没等到会自动留一张截图(shot.path,只失败才抓);也能等 xpath 命中 / xpath_gone 消失;列表刷到 ≥N 项用 count_min(配 text/id/desc/xpath)

adb_tap · 按 ref / text / id / desc / point="x,y" 点击(within_ref 限定在某一行/容器里找,点行内按钮不用先算坐标),long: true 长按;可带 wait_for_text / wait_for_id / wait_until_gone / wait_for_activity / wait_activity_gone 点完直接等结果,或 wait_stable 等界面静止再回执「变了没变」;回执里 changed 说变没变,reason 给原因码(keyboard-covered / obscured / unclickable / gone / page-switched / no-response / same-screen),delta 直接列出这次多/少了哪几行;没生效还会自动留一张截图(shot.path);点后等待也吃得下 wait_for_xpath / wait_xpath_gone;shot: true 点完留一张截图(省一次 adb_shot);tree: true 顺手把点完的新树带回来(判变化时本来就读过,ref 属于新快照,接着点下一项不用再 adb_ui)

adb_input · text(ASCII,空格自动转义)、key(ENTER/BACK/DEL…)、submit(enter / search,输完直接提交)、ime(auto / clipboard / adb,ADBKeyboard 已装且是当前输入法时中文走广播更快)、swipe、clear;回执给 method(ime/paste/input)、field(输入框回读)、verified,verify: true 时 ASCII 直发也回读一次,不用再补 adb_ui

adb_gesture · 真人轨迹:points 折线逐点 DOWN/MOVE/UP,duration_ms、hold_ms;曲线拖拽、按住再拖;滑完可等文字或 wait_for_xpath / wait_xpath_gone

adb_app · list(42 个可启动应用 + 前台,找包名第一步)、info(versionCode/versionName + 前台)、install(-r -d)、start、stop、clear、uninstall、foreground

adb_sh · 设备端任意命令,输出截断到 20k 字符;日志、dumpsys

adb_shot · 只在要看颜色/布局/相机画面时截图,默认缩到长边 900 px,返回路径给 read_image;region="x,y,w,h" 只回一块(看桌宠、小图标时体积降一个量级);带 ref 只截那个控件(实测桌宠页一个图标 126×126 / 1.6 KB,整屏 600×900 / 39 KB)

adb_look · 不看图也能看清画面:把屏幕压成颜色网格(每格一个字母)、列出同色块的位置与占比、给出与上一次的差异;region 只看一块、cols/rows 调网格密度。canvas/游戏/自绘界面、文本树没有文字时用它——比 adb_shot 快、不花图片 token

adb_ocr · 直接读屏上的文字,不花图片 token:给 ref 或 region 只读那一块,回一批带坐标的文字,坐标可直接给 adb_tap point=。优先认右栏直播帧(热 110 ms),文本树能读时优先用 adb_ui

adb_device · 列设备、状态、型号、当前选中设备与分辨率

adb_state · 一次往返:前台 Activity、焦点窗口、窗口栈、键盘、方向、分辨率、亮屏、电量、root(125–195 ms:七条 dumpsys 并发跑,串行要 371 ms)

adb_do · 一串动作一次跑完(最多 20 步):点 / 滑 / 输入 / 按键 / 系统动作 / 等文字,任何一步失败就停并报第几步;每步可 retry 重来注入前的偶发失败;失败时自动留一张截图到 ~/.dsh/adb-evidence/<序列号>/(只留最近 20 张);步骤也能带 until(等同一控件进入某状态)与 dismiss(本步等待时自动点掉挡路弹窗);步骤也能用 xpath 一次定位点掉,tap/id 步与等待/核对步都可配 within_ref(或坐标框 within_rect)只在一行里找、只在一行里等「已关注」;找目标也能用 assert_activity/assert_activity_gone(核对页面)/desc/cls/exact/regex/index/long_ms(长按时长)(同一文字匹配到多个时点第几个,从 0 开始)(和 adb_tap 一致,只有描述的图标按钮、半截类名的控件都能点);输入步可写 clear: true 先清空聚焦输入框;某步写 on_fail: "continue" 就允许它失败(记一笔跳过,后面照跑);同一步要连做几次写 repeat(1–20,配点击/滑动/按键/系统动作/scroll_to,连点「下一集」不用抄十遍);整串跑完可加 shot: true 顺手留一张截图、tree: true 顺手把跑完的界面读回来(ref 归新快照);scroll_to 还能写成对象(text/id/desc/cls/xpath + direction/until/dismiss/max_swipes),滑到「真的能点」的那个再动手;每步还能 wait_for_xpath / wait_xpath_gone / assert_xpath / `assert_xpat

…(truncated)

Rendered from the README published on npm. Formatted only, not edited.

Versions

Published on npm::45,最后更新 2026-11-06

Links

GitHub · Homepage · npm

Same category