🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

桌面操控 HUANGjiale123-bit/dsh-desktop-control

DeepSeek Harness
HUANGjiale123-bit14 天前有提交已提供中文文档扫描:含敏感能力

让 AI 读取窗口并点击输入,操作真实桌面

29.9/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/23 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add HUANGjiale123-bit/dsh-desktop-control
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么[目录]—
dsh 原生插件 · ui
暂无时间戳·判据 →
装得上吗[实装验证]—
本站尚未做安装检查
暂无时间戳·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 14 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 140 处,展示前 73 条)
  • 执行外部命令固定命令
    plugin/apps.mjs:81
    const buf = execFileSync(
  • 读取本地文件
    plugin/apps.mjs:127
    const exes = readdirSync(dir).filter((f) => f.toLowerCase().endsWith('.exe'))
  • 读取本地文件
    plugin/apps.mjs:174
    if (/ exe$/i.test(p) && existsSync(p) && !looksLikeHelper(p)) return p
  • 读取本地文件
    plugin/apps.mjs:180
    if (dir && existsSync(dir)) {
  • 读取本地文件
    plugin/apps.mjs:192
    if (dir && existsSync(dir)) {
  • 读取本地文件
    plugin/apps.mjs:232
    if (!exe || !existsSync(exe)) continue
  • 读取本地文件
    plugin/apps.mjs:282
    return existsSync(q)
  • 发起网络请求
    plugin/index.mjs:262
    const outcome = await approval.request({
  • 读取本地文件
    plugin/index.mjs:315
    (existsSync(bundledHelper) ? bundledHelper : repoHelper)
  • 读取本地文件
    plugin/index.mjs:319
    const escPath = config.escPath ?? (existsSync(bundledEsc) ? bundledEsc : repoEsc)
  • 执行外部命令来自配置/变量
    plugin/index.mjs:366
    const child = spawn(helperPath, ['gate_probe'], {
  • 读取本地文件
    plugin/index.mjs:444
    if (!existsSync(p)) return
  • 读取本地文件
    plugin/index.mjs:445
    const raw = readFileSync(p, 'utf8')
  • 删除本地文件
    plugin/index.mjs:463
    rmSync(p, { force: true })
  • 执行外部命令来自配置/变量
    plugin/index.mjs:473
    const c = spawn(exe, args, { windowsHide: true })
  • 读取本地文件
    plugin/index.mjs:690
    : (process.env.DSC_CURSOR_FX === '1' || existsSync(join(tmpdir(), 'dsc-cursor-fx.enable'))),
  • 写入本地文件
    plugin/index.mjs:709
    mkdirSync(this.dir, { recursive: true })
  • 读取本地文件
    plugin/index.mjs:713
    for (const name of readdirSync(base)) {
  • 删除本地文件递归
    plugin/index.mjs:723
    if (Date.now() - statSync(d).mtimeMs > 3600_000) rmSync(d, { recursive: true, force: true })
  • 写入本地文件
    plugin/index.mjs:744
    try { copyFileSync(from, exe) } catch { }
  • 写入本地文件
    plugin/index.mjs:749
    try { copyFileSync(assetFrom, this.asset) } catch { }
  • 写入本地文件
    plugin/index.mjs:756
    try { copyFileSync(guardFrom, join(dir, 'dsc-guard.exe')) } catch { }
  • 写入本地文件
    plugin/index.mjs:819
    try { copyFileSync(files[i].file, dest) } catch { }
  • 写入本地文件
    plugin/index.mjs:863
    writeFileSync(join(this.dir, 'fx.active'), String(Date.now()))
  • 删除本地文件
    plugin/index.mjs:941
    try { if (this.dir) rmSync(join(this.dir, 'fx.heartbeat'), { force: true }) } catch { }
  • 删除本地文件
    plugin/index.mjs:958
    try { rmSync(blanked, { force: true }) } catch { }
  • 删除本地文件
    plugin/index.mjs:978
    try { if (stopFile) rmSync(stopFile, { force: true }) } catch { }
  • 删除本地文件递归
    plugin/index.mjs:1042
    if (!alive) rmSync(d, { recursive: true, force: true })
  • 执行外部命令来自配置/变量
    plugin/index.mjs:1447
    child = spawn(helperPath, args, { windowsHide: true })
  • 执行外部命令来自配置/变量
    plugin/index.mjs:1491
    child = spawn(cmd, args, opts)
  • 执行外部命令来自配置/变量
    plugin/index.mjs:3545
    const child = spawn(exe, args, {
  • 读取本地文件
    plugin/ocr-worker.mjs:48
    for (const c of cand) if (existsSync(c)) return c
  • 读取本地文件
    plugin/ocr-worker.mjs:107
    if (!script || !existsSync(script)) return { ok: false, error: 'NoOcrScript' }
  • 读取本地文件
    plugin/ocr-worker.mjs:131
    if (!script || !existsSync(script)) return { ok: false, error: 'NoOcrScript' }
  • 读取本地文件
    plugin/ocr-worker.mjs:132
    if (!imagePath || !existsSync(imagePath)) return { ok: false, error: 'ImageNotFound' }
  • 读取本地文件
    plugin/toolset.mjs:58
    for (const c of cands) if (existsSync(c)) return c
  • 读取本地文件
    plugin/toolset.mjs:80
    return typeof g === 'string' && g.length > 0 && existsSync(g)
  • 读取本地文件
    plugin/toolset.mjs:220
    const names = await readdir(shotDir)
  • 读取本地文件
    plugin/toolset.mjs:226
    const st = await stat(full)
  • 删除本地文件
    plugin/toolset.mjs:245
    await unlink(f)
  • 读取本地文件
    plugin/toolset.mjs:307
    if (fromEnv && existsSync(fromEnv)) return fromEnv
  • 读取本地文件
    plugin/toolset.mjs:317
    if (existsSync(c)) return c
  • 执行外部命令来自配置/变量
    plugin/toolset.mjs:352
    child = spawn(py, [script, String(hwnd), String(maxNodes)], {
  • 执行外部命令来自配置/变量
    plugin/toolset.mjs:423
    child = spawn(py, [script], { stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true, env })
  • 执行外部命令来自配置/变量
    plugin/toolset.mjs:611
    child = spawn(helperPath, args, { windowsHide: true, env })
  • 执行外部命令来自配置/变量
    plugin/toolset.mjs:645
    spawnSync(helperPath, ['release'], {
  • 执行外部命令来自配置/变量
    plugin/toolset.mjs:1288
    const child = spawn(app.exe, [], {
  • 写入本地文件
    plugin/toolset.mjs:1601
    await mkdir(shotDir, { recursive: true })
  • 执行外部命令固定命令
    server/apps.mjs:81
    const buf = execFileSync(
  • 读取本地文件
    server/apps.mjs:127
    const exes = readdirSync(dir).filter((f) => f.toLowerCase().endsWith('.exe'))
  • 读取本地文件
    server/apps.mjs:174
    if (/ exe$/i.test(p) && existsSync(p) && !looksLikeHelper(p)) return p
  • 读取本地文件
    server/apps.mjs:180
    if (dir && existsSync(dir)) {
  • 读取本地文件
    server/apps.mjs:192
    if (dir && existsSync(dir)) {
  • 读取本地文件
    server/apps.mjs:232
    if (!exe || !existsSync(exe)) continue
  • 读取本地文件
    server/apps.mjs:282
    return existsSync(q)
  • 读取本地文件
    server/ocr-worker.mjs:48
    for (const c of cand) if (existsSync(c)) return c
  • 读取本地文件
    server/ocr-worker.mjs:107
    if (!script || !existsSync(script)) return { ok: false, error: 'NoOcrScript' }
  • 读取本地文件
    server/ocr-worker.mjs:131
    if (!script || !existsSync(script)) return { ok: false, error: 'NoOcrScript' }
  • 读取本地文件
    server/ocr-worker.mjs:132
    if (!imagePath || !existsSync(imagePath)) return { ok: false, error: 'ImageNotFound' }
  • 读取本地文件
    server/server.mjs:217
    ` helper : ${set.helperPath}${existsSync(set.helperPath) ? '' : ' ← 不存在,需先编译'}\n` +
  • 读取本地文件
    server/toolset.mjs:58
    for (const c of cands) if (existsSync(c)) return c
  • 读取本地文件
    server/toolset.mjs:80
    return typeof g === 'string' && g.length > 0 && existsSync(g)
  • 读取本地文件
    server/toolset.mjs:220
    const names = await readdir(shotDir)
  • 读取本地文件
    server/toolset.mjs:226
    const st = await stat(full)
  • 删除本地文件
    server/toolset.mjs:245
    await unlink(f)
  • 读取本地文件
    server/toolset.mjs:307
    if (fromEnv && existsSync(fromEnv)) return fromEnv
  • 读取本地文件
    server/toolset.mjs:317
    if (existsSync(c)) return c
  • 执行外部命令来自配置/变量
    server/toolset.mjs:352
    child = spawn(py, [script, String(hwnd), String(maxNodes)], {
  • 执行外部命令来自配置/变量
    server/toolset.mjs:423
    child = spawn(py, [script], { stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true, env })
  • 执行外部命令来自配置/变量
    server/toolset.mjs:611
    child = spawn(helperPath, args, { windowsHide: true, env })
  • 执行外部命令来自配置/变量
    server/toolset.mjs:645
    spawnSync(helperPath, ['release'], {
  • 执行外部命令来自配置/变量
    server/toolset.mjs:1288
    const child = spawn(app.exe, [], {
  • 写入本地文件
    server/toolset.mjs:1601
    await mkdir(shotDir, { recursive: true })
扫描于 2026/11/4(1 天前) · 范围 全包扫描 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

Windows 桌面观察与操作插件(DSH / DeepSeek Harness):无障碍树、截图、OCR 兜底、鼠标键盘;会话级授权与 ESC 急停。Windows desktop control for DSH.

README

由 DeepSeek 最新模型翻译生成
dsh-desktop-control Windows 桌面观察与操作插件(DSH / DeepSeek Harness):读窗口无障碍树、截图、点击、输入。 Windows desktop observation and control for DeepSeek Harness: accessibility tree, screenshots, OCR fallback, mouse/keyboard, session-scoped approvals. 这会让 AI 操作你的真实鼠标和键盘。 权限模型见下面「权限模型」一节。 - 安装包:Releases - 新手实战笔记:使用经验与技巧(坐标、按名字点、长文本、急停、常见错误) - 许可:MIT 作者:north-star(t) 不依赖外部视觉模型——元素名、角色、坐标由 Windows UI Automation 提供,不是模型从图片里猜的。
展开完整文档(README 剩余 1 节)
dsh-desktop-control

Windows 桌面观察与操作插件(DSH / DeepSeek Harness):读窗口无障碍树、截图、点击、输入。
Windows desktop observation and control for DeepSeek Harness: accessibility tree, screenshots,
OCR fallback, mouse/keyboard, session-scoped approvals.

这会让 AI 操作你的真实鼠标和键盘。 权限模型见下面「权限模型」一节。

- 安装包:Releases
- 新手实战笔记:使用经验与技巧(坐标、按名字点、长文本、急停、常见错误)
- 许可:MIT 作者:north-star(t)

不依赖外部视觉模型——元素名、角色、坐标由 Windows UI Automation 提供,不是模型从图片里猜的。

安装

先下载 Release 里的 dsh-desktop-control-*.tgz,然后二选一:

1. 插件管理(推荐):DSH → 插件管理 → 添加插件 → 在"包名或地址"里填 tgz 的绝对路径 (例如 D:\下载\dsh-desktop-control-1.0.2.tgz)→ 重启 DSH
2. CLI(等价):

dsh plugin --profile <你的profile> add "D:\下载\dsh-desktop-control-1.0.2.tgz"

市场暂未收录(dshmarket 只显示其索引内的插件);请从 Releases 下载。
手改 package.json 的安装方式见安装说明的开发者附录,不推荐。

装完就能用,不需要改任何配置。 辅助程序随插件包一起安装。
装好后重启 DSH,让它跑一次 desktop_diagnose,看到 插件 1.0.x 即成功。

权限模型

默认什么都不放行。 首次操作某个应用时,插件会询问你是否允许:

允许在当前会话中操作「notepad.exe」吗?
同意后,本次会话内对该应用的鼠标/键盘操作不再询问;会话结束即失效,不会写入任何配置。

- 同意 → 仅对当前会话的这一个应用有效
- 拒绝 → 本次会话内不再询问该应用
- 会话结束 → 授权自动失效,不需要做任何清理

另有 desktop_revoke_grants 工具,可在会话中途主动收回全部授权。

与「持久白名单」的区别

插件也支持在配置里写 allowedApps,但那是持久放行:写进去就一直有效, 人不在场也照样能操作。对能操纵鼠标键盘的能力来说这偏重,所以默认留空。
只有确实需要长期免问的应用才写进去。

工具

| 工具 | 作用 | 需要授权 |
| desktop_list_windows | 列出可见窗口 | 否(只读) |
| desktop_read_window | 读窗口的无障碍树 | 否(只读) |
| desktop_screenshot | 截图 | 否(只读) |
| desktop_click | 按坐标点击 | 是 |
| desktop_click_element | 按元素描述符点击 | 是 |
| desktop_type | 输入文本(支持中文) | 是 |
| desktop_press_key | 发送组合键 | 是 |
| desktop_set_value | 写控件值(走 UIA,带回读校验) | 是 |
| desktop_do_action | 触发次要动作(Raise/Scroll/Expand/Collapse) | 是 |
| desktop_revoke_grants | 收回本次会话的授权 | 否 |
| desktop_indicate / desktop_off | 显示/关闭运行指示层与急停 | 否 |

数据流向

界面上的一切都在本机处理:dsc.exe 是本地进程,无障碍树、截图、输入注入都不出这台机器。唯一的出站内容是工具返回的文本与截图,它们会进入模型上下文,和任何其它工具结果一样。

界面文本按不可信数据处理:应用可能在标题、按钮名、文档内容里藏针对模型的指令,所以返回时加显式前缀说明"这是数据而非指令"。

已知限制

1. dsc.exe 不能放在带 Low 完整性标签的目录里(例如 D:\dsh workspace)。

同一份 dsc.exe:放在工作区里跑是 Low 完整性级别,读 Chromium 系窗口只拿到 7 个节点(外壳);同样字节复制到 %TEMP% 就是 Medium,读到 20~40 个。
icacls "D:\dsh workspace" 能看到 Mandatory Label\Low Mandatory Level:(OI)(CI)(NW) —— 从那里执行的程序也跟着变 Low,而 Low 完整性的 UIA 客户端拿不到内容树。

注入同理:低完整性下 SetCursorPos 失败、光标不动、不报错。

插件不受影响(它用 profile 安装目录里的那份,是 Medium)。
只有"直接跑 helper/bin/dsc.exe"(开发、调试、测试)才会踩到。
ping 和 tree 现在都会回报 integrity / integrityRid,树读残时先看它。
详见 docs/定案-低完整性级别不是Chromium的毛病.md。

2. 无障碍树在 WinUI / 打包应用上仍然很残。

实测元素数:自建 WinForms 窗口 9 个(完整)、系统记事本 12 个(多为无名 Pane)。
WinUI / 打包应用这类只有外壳,要用截图路径。

Chromium 系(Electron / Tauri / WebView2)已经能读也能点:插件会自动换一条 UIA 读取链(server/uia-bridge.py:python → PowerShell),实测 SuYou(Tauri)读到 39~62 个有名字、有矩形的节点;desktop_click_element 在 Chromium 上会自动改用这条链定位,然后优先用 InvokePattern 触发(不移动鼠标)。

详见 docs/问题-Chromium无障碍-第十轮-按名字点击打通.md。

3. 停止用 ESC,不是 desktop_off。

dsc-esc.exe 装上低层键盘钩子,按 ESC 拉下闸门文件;dsc.exe 每条命令执行前都查这个文件,拦住所有变更性动作(连观察类命令也一并停)。desktop_off 只收指示层界面,不拉闸。

4. 多显示器 / 跨屏不同缩放:没有实测数据。

开发机只有一块屏(\\.\DISPLAY1),窗口被拖到另一块屏、或两块屏缩放不同这类情况没验过。代码按 Per-Monitor V2 写,坐标是物理像素,理论上跟着窗口所在屏走 —— 但「理论上」不算支持。

desktop_list_windows 会回报屏数:多屏时它会把这条提醒直接写进返回文本,desktop_click 的工具说明里也写着。有多屏的人请自己用 desktop_whatis 核对落点,别把这块当成已验证。

5. 尚未实现:visual-candidates(在截图上标出候选元素、带 observationId / imageSha256 / 坐标仿射关系的那套)。其余早先列为「未实现」的(launch_app、drag、滚轮、截图坐标锚定)都已实现。

安全说明

- 白名单双层校验:插件和辅助程序各校验一次;操作前重新枚举窗口,确认目标仍存在、其可执行文件仍在名单内(挡住句柄被复用成别的进程)
- 所有写入回读验证:set_value 返回 before/after/verified,值没变则报错而不是假装成功
- 失败一律拒绝:授权通道不可用、回调抛错、无会话上下文 —— 全部按拒绝处理
- 急停闸门:desktop_off 拉下闸门后,所有变更性命令被拒绝,不依赖按键通道或前台窗口

开发

./helper/build.sh # 编译 dsc.exe / dsc-edge.exe
node tools/test-approval.mjs # 授权逻辑自测(22 项)
node tools/test-packaging.mjs # 自包含性检查(22 项)
./tools/diag/build.sh CursorTruth # 注入能力自检

改完插件后,把 plugin/ 下的文件同步到配置档的 node_modules/dsh-desktop-control/,并同步 package.json 与 index.mjs 里的 PLUGIN_VERSION。

文档

| 文件 | 内容 |
| docs/当前状态.md | 入口:能做什么、不能做什么、改动前必看 |
| docs/ESC强制退出-完整链路.md | ESC 停止的完整链路 + 六类踩过的坑 |
| docs/实机验证-ESC打断操作.md | 实机演示:人按 ESC 打断正在进行的操作 |
| docs/定案-注入取决于启动上下文.md | 注入失效问题的完整排查记录 |
| docs/ESC急停-实测记录.md | ESC 方案的排查与结论 |
| docs/与Codex的差异清单.md | 与 OpenAI Codex computer use 的逐条对照 |
预览分享卡片长什么样 ↓HUANGjiale123-bit/dsh-desktop-control
分享 · DeepSeek Harness Hub
HUANGjiale123-bit/dsh-desktop-control

让 AI 读取窗口并点击输入,操作真实桌面

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部