@momasiku/dsh-pilot
让 DeepSeek Harness 看见并操作 Windows 上的任何程序。模型直接看真实屏幕,自己驱动鼠标、键盘和窗口。特点是快:好几步动作在一次往返里跑完,输入前还能先把目标窗口聚焦,点击就落在正确的窗口上。你在桌面上能做的事它都能做,包括但不限于画 CAD、电路图仿真、发消息。
安装
dsh plugin --profile web add @momasiku/dsh-pilot
沙箱测试结果
| 阶段 | 结果 |
|---|---|
| 1 安装 | ✓ |
| 2 列装 | ✓ |
| 3 挂载 | ✓ |
| 4 启动 | — |
四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。
README
<img src="https://raw.githubusercontent.com/momasiku/dsh-pilot/main/assets/banner.webp" alt="dsh-pilot — desktop control for DeepSeek Harness: hands and eyes on the whole machine" width="100%">
dsh-pilot
让 DSH 看见并高效地操作你的电脑
Give DeepSeek Harness hands and eyes on your desktop.




[中文说明](#中文说明) · [English](#english)
中文说明
给 DeepSeek Harness 装上眼睛和手——装在整个桌面上。
范围:Windows 桌面操控——模型看到的是真实屏幕,驱动的是真实鼠标与键盘。
DSH 原本只会"说":它能推理、能写代码、能规划,但看不见你的屏幕,也动不了你的鼠标。于是看屏幕的是你、截图的是你、点按钮的是你、出错了汇报的也是你——你成了它的手、它的眼,还兼任它的报错信息。
dsh-pilot 把这个环闭上:模型直接看真实像素,然后自己动手。
实例演示
<!-- 图片走 raw.githubusercontent.com(本仓库所有资源都用这个域名)。若在你那边较慢,
jsDelivr 上有同样的镜像:
https://cdn.jsdelivr.net/gh/momasiku/dsh-pilot@main/assets/dsh-pilot-cad.gif
https://cdn.jsdelivr.net/gh/momasiku/dsh-pilot@main/assets/dsh-pilot-excel.gif
https://cdn.jsdelivr.net/gh/momasiku/dsh-pilot@main/assets/dsh-pilot-blender.gif -->
模型自己画出来的 CAD 图。 用的就是 AutoCAD 自己的命令行——REC → 0,0 → 240,150、内轮廓、五个圆孔、中心线、两道尺寸,AutoCAD 里什么都没装。
一次调用改完一张表。 desktop_sequence 聚焦工作簿、把鼠标移到 C1、点击、粘贴「Q3 收入」、回车、保存——整串动作只花一次往返。
从零建一个 3D 模型。 清空视口 → 加一个立方体 → Ctrl+1、Ctrl+3 两级细分,方盒子被磨成一个球。真机上的 Blender 4.2,跑在一台没有显卡的机器上——靠 Mesa 的软件 OpenGL,而那套环境也是模型自己配好的。
工具 · 作用
screen_view · 抓取当前屏幕,把 PNG 作为真正的图像块交给模型(不是 OCR、不是文字描述),连光标位置、前台窗口、各显示器范围一起给出
desktop_control · 移动鼠标、单击/双击/右键、拖拽、滚轮、打字、按键、聚焦与列出窗口;可以在同一次调用里顺手截一张,让效果立刻可见
desktop_sequence · 一次调用跑完一整串动作,最后只看一眼结果
它到底解决了什么
桌面自动化的瓶颈从来不是鼠标点得快不快,而是 "模型和电脑要来回说多少次话":
一个五步任务(聚焦窗口 → 点输入框 → 打字 → 回车 → 看结果) · 只用 DSH · DSH + dsh-pilot
谁在看屏幕 · 你 · 模型,看真实像素
谁在点击打字 · 你 · 模型
模型 ↔ 电脑往返次数 · 5 次(每步一次,外加你的) · 1 次
送给模型的截图 · 4–5 张 · 1 张
出错时 · 你发现、你描述 · 同一次结果里就写明哪一步、为什么
为什么坐标可信(这是"点得准"的关键)
视觉驱动点击最经典的翻车方式是"坐标差一点点",这里堵掉了三个来源:
1. 两端都是 per-monitor DPI 感知。非 DPI 感知的进程会被 Windows 骗——它把 2560×1600 的屏幕看成 1707×1067,于是按这种截图算出来的点击必然偏。传感器和执行器在做任何事之前都声明 PER_MONITOR_AWARE_V2,所以一个图像像素就是一个物理屏幕像素。
2. 每张图都带坐标刻度尺:上沿与左沿每 200px 一条刻度,标注的是屏幕坐标(不是图像偏移),还有 origin x,y step n 说明。模型直接读刻度,不用数像素;刻度是屏幕坐标,所以即使图片被压缩也依然有效。
3. 信封如实说明交付尺寸。如果宿主把图压小了,模型会收到比例与乘数;坐标契约也变成条件式——只有在"交付尺寸 == 采集尺寸"时才承诺"照用 x、y 即可",否则明确要求乘多少:
<delivered_scale>delivered 1974x873 = 0.873x capture; multiply image readings by 1.1454 to get screen pixels</delivered_scale>
为什么快
批处理是大头(省的是往返,不是点击);第二个大头是不再每次重启 PowerShell——一个常驻 worker 同时服务动作与截图:
请求 · 一次性脚本 · 常驻 worker
动作(移动/点击/打字…) · ~0.9–2.0 秒 · 6–12 毫秒
截图(主屏) · ~1.2–2.3 秒 · ~0.5 秒
(2560×1600、150% 缩放、DSH 界面还在动的情况下实测)。worker 在第一次调用时后台预热,它需要的约 1 秒与第一张截图重叠,不会拖慢第一个动作。
没变化的帧不重复发送:每次截图都带 frameHash,与同会话上一帧逐字节相同时就不重复附图(也不重复存储),结果里写 unchanged: true,模型手上那张图的坐标继续有效;想看就传 forceImage: true。
读控件树
截图是要靠猜的:模型在像素里找到按钮、估个中心、点一下,再截一张图看猜没猜对。
而 Windows 通过 UI Automation 直接把同一个控件交出来——角色、名字、矩形——于是点击
就变成「那个矩形的中心」,什么也不用看。
desktop_control({ action: 'controls', title: '记事本' })
// 4 [Button] '最小化' @ 887,1 45x39
// 14 [Button] '新建会话' @ 12,54 256x24
// 23 [Edit] '搜索会话名称' @ 204,238 4x20 offscreen
desktop_control({ action: 'click', target: 14, title: '记事本' })
控件树不是更快的截图,是另一种取舍。
· 截图 · 控件树
读一次 · ~150 ms,~1k token · ~130-300 ms,~850 token(过滤后)
点击位置 · 从像素里估 · 控件的精确矩形
状态 · 「看着像禁用」 · enabled、offscreen、HasKeyboardFocus、IsSelected、值
可用性 · 永远有 · 不一定有,见下
按单次调用看,树更慢或打平;按单个任务看,树快得多——一次读取能定位好几个目标,
既不用多截一张图,也不用多跑一轮推理。
它不是总存在。 canvas、绘图面、自绘列表、以及什么都不上报的 Electron 窗口,
给出的树要么是空的要么没意义。所以截图这条路还在,而且仍然是兜底:先读树,
树为空、或者你需要看「画出来什么」而不是「声明了什么」时,再截一张图。
三个要知道的点。
- 索引只针对「某一次列表」。点击时会重新读一遍再解析,而且暖 worker 记着它发出去的
那份列表,所以某一行换了身份会明确报错,而不是按位置点下去:
the control at index 4 is not the one that was listed: expected [Button] 'OK', found [Button] 'Cancel'。
meaningfulOnly(默认true)只返回人能操作的控件。在一个真实的 673 元素窗口上,
这是 77 个元素、约 850 token,而不是 9k——其余全是没名字、没状态、点了也没反应的
布局面板。要整棵树就传 false。
includeValues默认关闭:结构不是内容。即使打开,密码框也会被打码。
当你要找的东西本身没有树——聊天记录、画布、自绘面板——不要去找它。去找围着它的
东西再做减法:输入框是个带矩形的 Edit,窗口有矩形,那么聊天区就是它们之间剩下的那块。
或者干脆不用几何:在树里选中那一条,用 HasKeyboardFocus 确认键盘落点就是你要的地方,
打字,回车。最后这一步是截图做不到的——截图能给你一根光标,给不了保证。
为什么安全
给模型装上手,最该讲究的就是这一块:
- 风险先声明、后强制:默认
low可自由批量;声明medium/high的批次、或含risk: "high"步骤的批次,在碰桌面之前就被拒绝,除非调用方带confirm: true(而它只会在你同意之后带)。 dryRun: true只校验并列出计划,不执行。- 默认遇错即停:
focus失败绝不会有"接着往面前那个窗口里打字"的后续。 - 定向输入:步骤里指定了窗口(
hwnd)时,注入前会再次把该窗口置前,点击不会落进旁边的窗口。 - 结果不明就绝不静默重试:worker 在请求送达后死掉时,动作按失败上报而不是重放——它可能已经生效了;截图没有副作用,才会自动回退重试。
- 中断是真的能中断:按 Esc 会写取消令牌,动作循环在每一步之间轮询(拖拽中、等待中、截图前都查),拖拽在
finally里松开按键——中断的回合不会留下按住的鼠标,也不会把剩下的点击跑完。 - 不会假装成功:Windows 禁止向更高完整性级别(提权)的窗口注入输入,工具会如实报错。
- 批量有上限:
maxSequenceSteps(默认 24)。
安装
# 从 npm 装(推荐) dsh plugin --profile <你的profile> add @momasiku/dsh-pilot # 或从仓库装 dsh plugin --profile <你的profile> add github:momasiku/dsh-pilot # 或用本仓库 Releas …(truncated)
以上内容来自 npm 上的 README,我们只做格式化,不改内容。
版本
npm 上共发布:19,最后更新 2026-11-05