让模型操作真实鼠标键盘并安全管理本机文件
30.6/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/11/2 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add Zero20230619/desktop-hand该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
是什么
dsh 原生插件 · desktop
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 3 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🟢 扫描:未发现敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。
扫描于 2026/11/2(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
Desktop Hand:为 DeepSeek Harness 提供真实桌面鼠标键盘输入,以及受策略保护的文件工具
README
由 DeepSeek 最新模型翻译生成桌面操控手(Desktop Hand)
让 DeepSeek Harness 里的模型直接操作真实的桌面鼠标和键盘,并提供一套带禁区、回收站删除与会话级授权的文件工具。
⚠️ 高风险提醒 —— 请先读这一段
桌面操控手会让模型操作你的真实桌面:移动真实鼠标、点击、拖拽、输入文本、按快捷键、截屏,以及在本机写入、移动、删除和恢复真实文件。
- 真实输入和文件改动默认全部关闭,必须由人批准一份有期限、有动作次数上限的会话级授权后才能进行(默认 approval.authorize: "ask";若你的 DSH 审批策略会自动批准,这层保障会被削弱——详见 docs/CONFIG.md)。
- 它不是沙箱:不是虚拟机,不是独立账户,也不是操作系统权限边界。桌面操控手以 DeepSeek Harness 进程的权限运行,除了被策略保护的路径外,凡是该进程能碰的东西它都能碰。
- 文件策略只约束桌面操控手自己的工具(除非你开启 policy.enforceOnDshFsTools)。bash、pwsh 等 shell 工具不受约束,可以绕过它。
- 删除默认走回收站(隔离区)模式,可恢复;但 direct(直接删除)一旦由用户解锁就是永久销毁。
- 请先用 fake 输入后端或一次性测试账户,按 docs/ACCEPTANCE.md 走完验收,并把手放在紧急停止热键上。
展开完整文档(README 剩余 1 节)
桌面操控手(Desktop Hand)
让 DeepSeek Harness 里的模型直接操作真实的桌面鼠标和键盘,并提供一套带禁区、回收站删除与会话级授权的文件工具。
⚠️ 高风险提醒 —— 请先读这一段
桌面操控手会让模型操作你的真实桌面:移动真实鼠标、点击、拖拽、输入文本、按快捷键、截屏,以及在本机写入、移动、删除和恢复真实文件。
- 真实输入和文件改动默认全部关闭,必须由人批准一份有期限、有动作次数上限的会话级授权后才能进行(默认 approval.authorize: "ask";若你的 DSH 审批策略会自动批准,这层保障会被削弱——详见 docs/CONFIG.md)。
- 它不是沙箱:不是虚拟机,不是独立账户,也不是操作系统权限边界。桌面操控手以 DeepSeek Harness 进程的权限运行,除了被策略保护的路径外,凡是该进程能碰的东西它都能碰。
- 文件策略只约束桌面操控手自己的工具(除非你开启 policy.enforceOnDshFsTools)。bash、pwsh 等 shell 工具不受约束,可以绕过它。
- 删除默认走回收站(隔离区)模式,可恢复;但 direct(直接删除)一旦由用户解锁就是永久销毁。
- 请先用 fake 输入后端或一次性测试账户,按 docs/ACCEPTANCE.md 走完验收,并把手放在紧急停止热键上。 默认热键是 Pause(刻意不用 F9:Blender 的「调整上一步操作」占用了 F9,建模时会误触)。
- 开发阶段没有对 Blender 等真实应用做过端到端 GUI 实操验证,自动化测试只使用 fake 输入后端和单元测试。
真实应用的验收属于手工步骤。
目录
- 这是什么
- 架构
- 环境要求与平台支持
- 安装
- 快速上手
- 工具列表
- 斜杠命令
- 配置
- 文件策略、删除模式与回收站
- 安全模型与威胁模型
- 常见问题排查
- 开发与测试
- 许可证
这是什么
桌面操控手是一个 DeepSeek Harness(DSH)插件,为模型提供两类被严格隔开的能力:
1. 真实桌面输入:观察屏幕(get_pointer、foreground_window、screenshot),并操作真实桌面(move_mouse、click、drag、scroll、press_key、type_text)。模型按「看 → 做 → 再看」的循环工作:截图 → 用 DSH 的 read_image 查看 → 只做一个动作 → 再截图确认。
2. 受策略保护的文件操作:read_file、list_dir、write_file、move_path、delete_path、 restore_path、list_trash。读取不需要授权,但仍受禁区约束;写入、移动、删除需要单独的一份 files(文件)授权。删除默认进入可恢复的「回收站」隔离区,带元数据、只增日志和一次调用即可恢复的能力。
所有这些能力同时受以下机制约束:互相独立的 input(输入) 与 files(文件) 会话级授权、每次调用的 审批策略、动作与坐标上限、文件禁区/系统关键区/敏感屏幕区域、全系统紧急停止,以及 JSONL 审计日志。
它不是:远程桌面协议、沙箱、后台常驻服务,也不能替代 DSH 自带的 read/write/edit 工具(日常工作区的文件编辑请继续使用那些工具)。
架构
DSH 宿主进程 │ │ profile patch 行(cordis.patch.yml / install.ps1 写入的托管块) ▼ index.js —— 插件入口 │ • Config schema(部署级覆盖:enabled/configPath/provider/trashDir/…)
│ • 注册 21 个工具、/desktop-hand 命令、系统提示词指引 │ • tools/pre-execute:授权 + 审批 + 紧急停止拦截 │ • 启动紧急停止热键监听 ▼ lib/runtime.js —— 每次插件激活只创建一次 │ ├── lib/config.js 默认值 · 配置发现 · 深合并 · 校验 · 路径展开 │ │ │ ├── lib/tools/ │ │ input-tools.js 观察 + 鼠标/键盘/文本/截图(需要 input 授权) │ │ fs-tools.js 读/列目录/写/移动/删除/恢复/回收站(写操作需要 files 授权) │ │ control-tools.js 授权 · 撤销 · 状态 · 策略收紧 · 紧急停止 │ │ │ ├── lib/security/ │ │ authorization.js 会话授权、动作预算、敏感区/直接删除解锁、会话收紧 │ │ limits.js 坐标/时长/次数上限、敏感屏幕区域、窗口标题模式 │ │ emergency.js 暂停/恢复、AbortSignal、监听器 │ │ │ ├── lib/fs/ │ │ policy.js 禁区 + 受保护根目录 → 允许/拒绝;删除模式 │ │ trash.js <trash>/items/<id>/payload + meta.json + index.jsonl │ │ audit.js audit-<session>.jsonl、轮转、输入文本脱敏 │ │ │ └── lib/input/ │ index.js 输入后端工厂(auto | windows | linux | macos | fake | disabled) │ windows.js 常驻 PowerShell JSON-lines 代理(scripts/input-agent.ps1) │ linux.js xdotool 逐条命令 │ macos.js cliclick + osascript + screencapture │ fake.js 确定性的内存假后端(测试 / 演练) │ hotkey.js 隐藏的 scripts/hotkey-monitor.ps1 轮询器(仅 Windows) │ └── 审计文件、回收站、截图(工作区 .desktop-hand/screenshots)
环境要求与平台支持
| 平台 | 真实输入 | 截图 | 紧急停止热键 | 说明 |
| Windows 10/11 | ✅ 完整 | ✅ 完整 | ✅ 默认 Pause | 主目标平台。使用 Windows PowerShell 5.1(powershell.exe,回退 pwsh.exe)、常驻输入代理和隐藏的热键监听进程,无需额外安装组件。 |
| Linux | ⚠️ 尽力而为 | ⚠️ 尽力而为 | ❌ 无 | 需要 PATH 中有 xdotool;截图依赖 ImageMagick import、scrot 或 gnome-screenshot。多显示器只上报为一块显示区域。紧急停止仍可用 /desktop-hand stop 或 desktop_hand_emergency_stop;输入后端每次操作前也会检查停止标志文件。 |
| macOS | ⚠️ 尽力而为 | ⚠️ 尽力而为 | ❌ 无 | 需要 cliclick;使用 osascript、pbcopy+Cmd+V 输入文本(会改动剪贴板)和 screencapture。不支持滚轮和中键点击,拖拽仅左键;需要手动授予辅助功能/自动化权限。无热键监听。 |
| fake | —(模拟) | ✅ 生成真实 PNG | ❌ 无 | 确定性的内存假后端,用于测试/演练(input.provider: "fake"),完全不碰真实桌面。 |
| disabled | ❌ | ❌ | ❌ | input.provider: "disabled",输入工具直接失败关闭。 |
运行要求:Node.js ≥ 22(插件为 ESM,见 package.json 的 engines)、带 profile 的 DSH; Windows 上需要 PowerShell 5.1 或 PowerShell 7。本仓库测试在 Windows + Node v26.13.0 上运行通过。
安装
插件包目录是 desktop-hand/(本仓库/本文件夹),包含 index.js、lib/、scripts/、locale/、 cordis.patch.yml、desktop-hand.config.json、install.ps1、uninstall.ps1 以及本文档。
推荐方式:install.ps1
DSH 运行时已设置 DSH_PROFILE_DIR;若没有则显式传入。
pwsh -File .\install.ps1 -ProfileDir "$env:DSH_PROFILE_DIR"
参数:
| 参数 | 默认值 | 含义 |
| -ProfileDir | $env:DSH_PROFILE_DIR | 目标 DSH profile(必须已存在 node_modules/ 和 cordis.patch.yml)。 |
| -SourceDir | 脚本所在目录 | 要安装的插件包目录。 |
| -DshHome | $env:DSH_HOME 或 $HOME\.dsh | 播种 desktop-hand.config.json 的位置。 |
| -SkipConfig | 关闭 | 不播种配置文件。 |
| -Force | 关闭 | 覆盖已安装副本(例如应用可能正在运行)。 |
脚本会做这些事:
1. 校验源包(package.json、index.js、包名必须是 desktop-hand)。
2. 把 cordis.patch.yml 备份为 cordis.patch.yml.bak-<时间戳>。
3. 如果 profile patch 里在托管标记之外已有一行手写的 desktop-hand 配置,脚本会拒绝执行,需先移除。
4. 把插件包复制到 <profile>/node_modules/desktop-hand(跳过 node_modules、.git、.desktop-hand、 test、coverage)。
5. 仅在文件不存在时播种 <DSH_HOME>/desktop-hand.config.json(让你的策略在升级后保留)。
6. 在 profile 的 cordis.patch.yml 末尾写入幂等的托管块:
desktop-hand managed block (install.ps1) >>>
- insert:
- id: desktop-hand
name: desktop-hand
config: {}
<<< desktop-hand managed block <<<
手工修改 profile patch
不想运行脚本时:
1. 把插件包目录复制到 <profile>/node_modules/desktop-hand。
2. 把上面的 - insert: 行(不加托管标记也可以)加到 profile 的 cordis.patch.yml 末尾——它是 bundle 层之后应用的用户 patch 层。
3. 重启 DSH(或重新加载 profile)。
开发用补丁叠加层(--patch)
DSH 启动器支持通过 --patch <文件> 追加补丁层(启动器参数必须位于应用参数之前)。补丁文件是与 cordis.patch.yml 相同的 YAML 列表;各层按顺序叠加:bundle 层 → profile patch → --patch 叠加层。
开发时先让插件包安装进 profile(执行一次 install.ps1,之后每次改动用 -Force 覆盖),再用叠加层按次启用/禁用或改配置,而不必反复编辑 profile patch:
dev.patch.yml
- insert:
- id: desktop-hand
name: desktop-hand
config:
enabled: true
provider: windows
示例:带叠加层启动另一个 DSH 实例。请使用你所装 DSH 版本的启动器命令/参数;启动器参数必须位于应用参数之前。
dsh --patch .\dev.patch.yml
叠加层是启动器能力,不是包管理器,不会替你复制任何文件。叠加层里的行可以指向本地 index.js 路径(在部分环境可用于行本身),但插件里裸写的 @deepseek-ai/ import 仍然需要 profile 里已安装的副本才能解析。所以请先安装(install.ps1 会复制插件包),再用 --patch 只覆盖行/配置。
重启 / 热更新
install.ps1 结束时会提示:「重启 DeepSeek Harness(或等待 profile HMR 拾取新包)」。正式部署请 重启 DSH。配置文件只在插件激活时读取一次(没有文件监听),因此改配置后也需要重启/重载。
卸载
pwsh -File .\uninstall.ps1 -ProfileDir "$env:DSH_PROFILE_DIR"
会移除托管块(先备份 patch)和已安装的包。用户数据会保留:desktop-hand.config.json、审计目录和回收站目录都保留,以便之后审计或恢复历史删除。
目录结构
desktop-hand/
├── index.js 插件入口:Config、工具注册、审批拦截、系统提示词 ├── lib/ 运行时、配置、工具、安全、文件策略、输入层 ├── scripts/ │ ├── input-agent.ps1 常驻 Windows JSON-lines 输入代理 │ ├── hotkey-monitor.ps1 隐藏的 GetAsyncKeyState 轮询器(紧急热键) │ └── live-smoke.mjs 安全、只读的后端实机自检(不注入输入) ├── locale/{en,zh}.json 插件市场元数据 ├── cordis.patch.yml 随包发布的 bundle 层 patch ├── desktop-hand.config.json 示例/用户可编辑配置(install.ps1 会播种) ├── install.ps1 / uninstall.ps1 ├── docs/{CONFIG.md,ACCEPTANCE.md} └── test/ node:test 单元测试(fake 后端)
快速上手
1. 安装并重启 DSH,在一个一次性工作区里打开会话。
2. 查看状态(用户专用命令,任何时候都允许): /desktop-hand status
确认 provider、config、hotkey: Pause、delete mode: trash,以及 input/files 两份授权都是 none。
3. 授予有时限、有次数上限的输入授权: /desktop-hand authorize input 10 200
(需要点击任务栏/屏幕角落时加 sensitive:/desktop-hand authorize input 10 200 sensitive。)
请只给短预算:授权会过期,也受动作次数限制。
4. 先看屏幕,再一步一步做:
- 模型先用 desktop_hand_get_pointer 和 desktop_hand_foreground_window 获取坐标、确认目标窗口;
- desktop_hand_screenshot 把 PNG 存到 <会话工作目录>/.desktop-hand/screenshots/;
- 模型必须再用 DSH 的 read_image 读取该路径才真正「看见」画面;
- 每次工具调用只做一个 click / press_key / type_text,然后再次截图确认。
5. 文件改动需要另一份授权: /desktop-hand authorize files 5 50
默认 approval.fileMutations: "ask",每次写入/移动/删除/恢复还需要实时审批。如果 DSH 关闭了审批(策略为 never),这些调用会失败关闭;如何改成 "grant" 见 docs/CONFIG.md。
拖拽和组合键(approval.drag/approval.combo)默认也走审批——Blender 的 shift+a 这一步需要有可用的审批提示,或把这两个类别改成 "grant"。
6. 随时按 Pause 紧急停止,或输入 /desktop-hand stop。只有人才能执行 /desktop-hand resume。
不想碰真实桌面时:把配置改为 "input": { "provider": "fake" } 并重启,就能用同一套流程在确定性的假桌面上演练。
工具列表
共 21 个模型可见工具(input 授权 = 会话级输入授权;files 授权 = 会话级文件操作授权;标为 只读的工具不需要授权,但仍受文件禁区约束;紧急停止期间除 status、revoke、emergency_stop 外全部被拦截)。
| # | 工具 | 作用 | 授权 / 审批 | 限制与说明 |
| 1 | desktop_hand_get_pointer | 返回当前指针坐标、各显示器边界、虚拟桌面边界、前台窗口标题与句柄。 | 只读,无需授权 | 点击前用来确认坐标。 |
| 2 | desktop_hand_foreground_window | 返回前台窗口标题、原生句柄、进程号,并报告标题是否命中敏感窗口模式。 | 只读,无需授权 | 输入文本/快捷键前用来确认目标应用。 |
| 3 | desktop_hand_move_mouse | 把真实指针移动到虚拟桌面绝对坐标。 | input 授权 | 必填 x、y;duration_ms 默认 0(瞬移),上限 limits.maxMoveDurationMs(5000)。消耗 1 次输入动作。 |
| 4 | desktop_hand_click | 在坐标处(或省略 x/y 时的当前指针处)点击真实鼠标键。 | input 授权 | button 取 left/right/middle(默认 left);count 默认 1,上限 limits.maxClicksPerCall(3);interval_ms 默认 80。命中敏感屏幕区域会被拒绝,除非授权解锁了敏感区。消耗 1 次动作。 |
| 5 | desktop_hand_drag | 按下鼠标、按时长移动到终点、松开。 | input 授权;审批 drag(默认 ask) | 必填 from_、to_;duration_ms 默认 500,上限 limits.maxDragDurationMs(10000);起点受敏感区域检查。消耗 1 次动作。 |
| 6 | desktop_hand_scroll | 在指针处或指定 x/y 处滚轮滚动。 | input 授权 | 必填 direction;amount 默认 3,上限 limits.maxScrollAmount(50)。消耗 1 次动作。 |
| 7 | desktop_hand_press_key | 在真实键盘上按单键或组合键,如 shift+a、ctrl+z、f12、win+r。 | input 授权;含 + 的组合键受审批 combo(默认 ask) | 必填 keys;hold_ms 默认 40;组合键段数上限 limits.maxComboKeys(4)。消耗 1 次动作。 |
| 8 | desktop_hand_type_text | 把 Unicode 文本作为真实键盘输入送进前台应用。 | input 授权;审批 text(默认 grant);命中敏感窗口标题时额外审批 | 必填 text(不能为空),上限 limits.maxTextChars(2000 个 UTF-16 码元);interval_ms 默认 input.textIntervalMs(8)。审计默认脱敏,除非 audit.logTypedText 为 true。消耗 1 次动作。 |
| 9 | desktop_hand_screenshot | 截取全部显示器或指定区域,保存为会话工作区内的 PNG。 | input 授权(屏幕内容属于隐私) | 可选 region_x/y/width/height;PNG 不得超过 screenshots.maxBytes(8 MiB);不消耗动作预算。需再用 DSH 的 read_image 读取返回路径才能看到。 |
| 10 | desktop_hand_read_file | 读取 UTF-8 文本文件,附带大小/修改时间。 | 只读,无需授权 | file_path;max_bytes 默认/上限 1 MiB;offset 按字节;超过 64 MiB 与二进制文件会被拒绝;只读禁区会带明确原因拒绝。不消耗动作。 |
| 11 | desktop_hand_list_dir | 列出目录的直接子项(类型/大小/修改时间,含隐藏项)。 | 只读,无需授权 | dir_path;max_entries 默认/上限 500;只读禁区拒绝。 |
| 12 | desktop_hand_write_file | 创建或修改 UTF-8 文本文件。 | files 授权;审批 fileMutations(默认 ask) | file_path、content;mode 为 overwrite(默认)/append;create_dirs 默认 false;受禁区、系统关键位置与插件数据保护约束。消耗 1 次文件动作。 |
| 13 | desktop_hand_move_path | 移动或重命名文件/目录。 | files 授权;审批 fileMutations(默认 ask) | source_path、dest_path;overwrite 默认 false;源与目标两端都做禁区检查。消耗 1 次动作。 |
| 14 | desktop_hand_delete_path | 按当前删除模式删除文件/目录。 | files 授权;直接删除依次受 directDelete、fileMutations 审批,回收站模式受 fileMutations 审批 | path;recursive;confirm_direct(永久删除必填);reason(写入审计与回收站元数据)。回收站模式移动到隔离区并返回 trashId/trashPath;forbid 直接拒绝;direct 需要解锁 + confirm_direct=true(目录还需 recursive=true)。消耗 1 次动作。 |
| 15 | desktop_hand_restore_path | 按 id 恢复一条隔离区删除。 | files 授权;审批 fileMutations(默认 ask) | trash_id;destination(默认原路径);overwrite 默认 false;目标路径会重新做禁区检查。消耗 1 次动作。 |
| 16 | desktop_hand_list_trash | 列出最近的隔离区条目(id、原路径、删除时间、大小、原因)。 | 只读,无需授权 | limit 默认 50,上限 200;不读取 payload 内容。 |
| 17 | desktop_hand_authorize | 由模型侧发起会话授权请求。 | 审批 authorize(默认 ask) | mode 取 input/files;minutes/max_actions 会被夹到会话上限;allow_sensitive_zones;allow_direct_delete;note。建议优先走人手动 /desktop-hand authorize。 |
| 18 | desktop_hand_revoke | 立即撤销本会话的输入和/或文件授权。 | 无需授权,始终允许 | mode 取 input/files/all(默认 all)。紧急停止期间也可用。 |
| 19 | desktop_hand_status | 报告授权、紧急停止状态、输入后端、策略摘要、目录与审批模式。 | 只读,始终允许 | 仅读取状态;自身标为高风险工具。 |
| 20 | desktop_hand_policy_override | 仅收紧本会话的文件策略。 | 审批 policyOverride(默认 ask) | add_readonly[]、add_write_protected[]、force_delete_mode: "forbid"、reason。无法删除禁区,也无法放宽删除模式。 |
| 21 | desktop_hand_emergency_stop | 立即中止所有桌面操控手操作并杀掉输入后端。 | 无需授权,始终允许 | reason(写审计)。除 status/revoke/emergency_stop 外全部被拦截,直到人执行 /desktop-hand resume。 |
说明:
- 每次调用只做一个原子动作。 系统提示词要求模型每次只做一个点击/组合键/文本/拖拽,并用截图验证后再做下一步。授权次数在动作成功之后扣减(截图和只读工具不扣次数)。
- 两类授权互相独立。 input 授权绝不允许文件改动,反之亦然。
- 工具动作与策略拒绝都会审计。 多数调用会追加一条审计记录,拒绝(input-denied、fs-denied)会连同命中的规则/原因一起记录。当授权/审批/紧急停止判定不允许时,tools/pre-execute 会在工具主体执行之前直接拒绝。
斜杠命令
/desktop-hand 是用户专用斜杠命令,不会进入模型对话,因此它是权威的「人工同意」路径。
| 命令 | 作用 |
| /desktop-hand 或 /desktop-hand status | 显示停止状态、input/files 授权(到期时间、已用/上限动作数)、输入后端、配置路径、审计/回收站目录、删除模式、热键、策略摘要。 |
| /desktop-hand authorize input [分钟] [次数] [sensitive] | 授予本会话真实鼠标/键盘/文本/截图权限。默认取 session.inputDefaultMinutes(10 分钟)与 inputDefaultActions(200 次),并夹到配置上限。加 sensitive 会在本次授权中解锁敏感屏幕区域。 |
| /desktop-hand authorize files [分钟] [次数] [direct-delete] | 授予文件写入/移动/删除/恢复权限。默认 5 分钟 / 50 次。direct-delete 解锁永久删除(每次调用仍需 confirm_direct=true,按配置可能还要逐次审批)。 |
| /desktop-hand revoke [input\|files\|all] | 立即撤销(默认 all)。 |
| /desktop-hand tighten readonly <模式> | 为本次会话追加只读禁区(语法同配置:路径、通配符或 /正则/)。 |
| /desktop-hand tighten write <模式> | 为本次会话追加写保护禁区。 |
| /desktop-hand tighten delete=forbid | 本会话强制删除模式为 forbid。 |
| /desktop-hand resume(别名 reset) | 解除紧急停止。只有人能执行。 |
| /desktop-hand stop(别名 halt) | 立即紧急停止。 |
| /desktop-hand policy | 打印当前生效的文件策略(配置禁区、删除覆盖规则)。 |
| /desktop-hand help | 显示命令语法。 |
会话收紧是只增不减的:只能追加禁区、只能强制 forbid,不能删除禁区或放宽删除模式。它只存在于内存,会随会话/重启消失。
配置
完整的逐字段注释参考见 docs/CONFIG.md。要点:
- JSON 配置的发现顺序:插件 Config.configPath(必须存在)→ <DSH_HOME>/desktop-hand.config.json (推荐,安装脚本会播种)→ <插件目录>/desktop-hand.config.json → <DSH_HOME>/desktop-hand/config.json → 内置默认值(并打印警告)。DSH_HOME 默认是 ~/.dsh。
- 配置文件在默认值之上深合并;数组整体替换。路径字段支持 ~、$VAR、${VAR}、${env:VAR} 和 %VAR% 展开。非法配置会让插件激活失败并报错,绝不会悄悄降级为默认值。
- profile patch 行可以覆盖少量部署级参数(enabled、configPath、provider、trashDir、auditDir、 screenshotsDir、hotkey、emergencyStop);策略、上限和审批模式都在 JSON 文件里。
- 配置只在插件激活时读取一次;修改后请重启/重载。
必须知道的关键默认值:
| 配置项 | 默认值 | 为什么重要 |
| policy.delete.mode | trash | 删除是可恢复的隔离区移动,而不是直接 unlink。随包配置把回收站放在 D:\DSH_Trash。 |
| approval.fileMutations | ask | 每次写入/移动/删除/恢复都需要实时审批。 |
| approval.directDelete | ask | 永久删除需要用户逐次明确确认。 |
| approval.drag / approval.combo | ask | 拖拽和组合键(例如 Blender 的 shift+a)属于高风险动作,默认逐次审批。 |
| approval.text | grant | 文本输入以 input 会话授权作为同意依据;但当前台窗口标题命中 limits.sensitiveZones.foregroundTitlePatterns 时仍会额外审批。 |
| emergency.hotkey | Pause | 全系统停止热键。刻意避开 F9,因为 Blender 用它做「调整上一步操作」。 |
| session. | 10 分钟/200 次输入,5 分钟/50 次文件;上限 30 分钟/1000 次 | 授权同时受时间和动作预算约束。 |
| input.provider | auto | Windows → windows,Linux → linux,macOS → macos;演练用 fake。 |
"ask" 不等于一定成功。 如果 DSH 会话审批策略是 never(或审批通道不可用),所有 "ask" 类别都会失败关闭——调用在进入工具主体前就被拒绝,什么也不会发生。Blender 验收流程里的 shift+a 属于 combo:要么把 DSH 审批策略切回 ask(推荐,能看到提示),要么把相关类别(combo、drag,文件操作则是 fileMutations/directDelete)改成 "grant",依赖 /desktop-hand authorize 的时间/次数受限会话授权。
文件策略、删除模式与回收站
禁区与优先级
桌面操控手的每个文件工具都会先规范化调用方给的路径(相对路径按会话工作目录解析;展开 ~/环境变量;剥离 Win32 命名空间前缀;解析符号链接/junction),然后同时用字面路径和真实路径匹配禁区,防止用链接绕过。
优先级刻意按「安全优先」排列:
1. 命中只读禁区 → 拒绝读、列目录、写、移动(源和目标)、删除。这一步先于任何删除模式判断,所以 direct 钉死规则也无法绕过只读禁区。
2. 命中写保护禁区 → 拒绝创建/覆盖/追加、移动和删除;读取与列目录仍允许。
3. 操作系统关键位置(protectSystemRoots,默认 true)→ 拒绝写入和删除;允许读取。
4. 插件数据(protectPluginData,默认 true):插件目录、审计目录和回收站目录不能被工具修改。
5. 受保护的删除根目录(delete.protectRoots,默认 true):盘符根、用户主目录、回收站目录、插件目录,以及会话工作目录根及其上级都不能被删除(也不能被移走)。只做等值判断——子项通常可以删。
6. 删除模式判定:会话强制 forbid > 按路径的 delete.pathOverrides > 全局 delete.mode。
direct 模式下,除非 directDeleteRequiresUnlock 为 false,否则需要带 allowDirectDelete 的 files 授权;非空目录还需要 recursive=true。trash 模式需要配置 trashDir。
7. 另外,desktop_hand_delete_path 会拒绝删除会话工作目录根或其上级目录。
删除模式
| 模式 | 行为 | 取证 / 恢复 |
| forbid | 所有删除都被拒绝(delete-forbidden)。 | 审计 fs-denied。 |
| trash(默认) | 文件/目录被移动到 <trashDir>/items/<id>/payload,并写 meta.json 与 index.jsonl;工具返回回收站 id 与恢复提示。 | desktop_hand_list_trash、desktop_hand_restore_path。跨卷移动退化为先复制再删除源。 |
| direct | 永久 rm。需要已解锁的 files 授权(allowDirectDelete)、confirm_direct=true、非空目录还需要 recursive=true,并按默认需要 directDelete 逐次审批(还会参考 approval.fileMutations)。 | 审计 fs/delete_direct;无法恢复。 |
回收站布局与恢复
D:\DSH_Trash\ # policy.delete.trashDir(随包配置) ├── index.jsonl # 只增日志:quarantine 与 restore 记录
└── items\
└── 20261031T162738-1a2b3c4d\ # id = UTC 时间戳 + 随机 hex ├── meta.json # id、originalPath、displayPath、payloadPath、size、type、 │ # mtime、deletedAt、sessionId、callId、tool、reason、 │ # policyRule、mode、moveKind、restoredAt、restoredTo └── payload # 被移动的文件或目录(符号链接仍按链接移动)
- desktop_hand_delete_path 返回 mode: "trash"、trashId、trashPath 和形如
desktop_hand_restore_path({ trash_id: "..." }) 的恢复提示。
- desktop_hand_restore_path 把 payload 移回记录的原始路径(或显式 destination),恢复前会重新对目标做禁区检查;除非 overwrite=true,否则不覆盖已存在路径。恢复后 meta.json 会更新 restoredAt、restoredTo、restoreCount、lastRestoreKind,index 追加 restore 记录。
- meta.json 在 payload 移动之前写入,因此即使崩溃也不会出现「有数据没元数据」的情况。
- 回收站 payload 不会自动清理,保留与清理由你负责。
会话收紧
/desktop-hand tighten readonly|write <模式> 和 /desktop-hand tighten delete=forbid (以及 desktop_hand_policy_override)只能让会话更严格。没有任何工具或命令能放宽配置禁区或重新允许删除。
安全模型与威胁模型
控制措施
- 两类互相独立的会话级授权。 input 与 files 分开管理,只存在内存中,按分钟到期,并受动作次数预算限制。撤销立即生效(/desktop-hand revoke、desktop_hand_revoke)。重启 DSH 会清空所有授权。
- 人工同意路径。 /desktop-hand authorize … 是用户专用斜杠命令;模型侧的 desktop_hand_authorize 还额外受 approval.authorize(默认 ask)约束,因此在默认审批模式下模型无法静默给自己授权。若部署把审批改成自动批准,这层保障会被削弱——高风险/无人值守环境请保持 approval.authorize 为 ask/deny。
- 审批拦截(tools/pre-execute)。 高风险调用在工具主体执行前返回 ask/deny:授权类工具、策略收紧、文件改动、直接删除、拖拽、组合键和文本输入。默认:fileMutations、directDelete、 drag、combo 为 ask;text 为 grant(以 input 会话授权作为同意),但命中敏感窗口标题时仍会额外审批。若 DSH 审批策略是 never,所有 ask 类别都会失败关闭——需要显式把类别改成 grant,或有意开启审批。
- 紧急停止。 默认 Pause 热键由隐藏的 PowerShell 监听进程轮询,触发后写入 <DSH_HOME>/desktop-hand/emergency-stop.json;运行时随即停止、通过 AbortSignal 中止进行中的输入、杀掉输入后端并通知模型。停止期间,除 status、revoke、emergency_stop 外的全部桌面操控手工具都被拒绝,只有人能执行 /desktop-hand resume。刻意不选 F9,因为 Blender 把它绑定到「调整上一步操作」。
- 硬性限制。 坐标校验(必须是整数、落在真实显示器内、不在显示器之间的虚拟空隙)、次数/时长/文本长度上限、敏感屏幕矩形(任务栏条、屏幕角落;点击与拖拽起点默认拒绝,除非授权解锁敏感区)。
敏感前台窗口标题模式可在输入文本前强制走审批。
- 文件策略。 如上文的禁区、删除模式、受保护根目录和「真实路径」检查;拒绝都会返回带代码与原因的明确错误,绝不静默跳过。
- 审计。 每会话一个只增 JSONL 文件,支持轮转,默认对输入文本脱敏。工具级别的拒绝(input-denied、fs-denied)会连同命中的规则/原因记录,授权变更和紧急停止也会记录。由 tools/pre-execute 在工具主体执行前做出的授权/审批拒绝不会进入桌面操控手审计日志——请查看调用方收到的拒绝原因、/desktop-hand status 和 DSH 日志。
威胁模型与坦白的局限
桌面操控手假设人类用户是主体,而模型可能犯错、被提示注入操纵,或只是理解错了:
- 一旦出问题,限制损失靠的是授权的时限/次数预算、紧急停止热键、回收站的可恢复性以及审计日志, 而不是操作系统沙箱。
- 策略范围: policy. 只约束桌面操控手自己的工具。除非开启 policy.enforceOnDshFsTools: true(此时也会保护 DSH 自带的 read/read_image/list_dir/ write/edit/write_file),shell 命令(bash、pwsh 等)可以读写同样的文件——包括只读禁区里的文件——并完全绕过删除模式。forbid 不是文件系统权限。
- 不是操作系统沙箱。 插件以 DSH 进程的用户权限运行,无法防御同用户的恶意进程,也无法阻止模型被诱导去申请一份过大的授权。
- 屏幕隐私: 截图会拍下所有显示器上的可见内容(或指定区域);type_text 可能输入敏感信息。
审计默认脱敏(audit.logTypedText: false),但这些内容仍会作为真实输入发送。
- 破坏性路径依然存在: 人若解锁 direct-delete、提供 confirm_direct 并批准,就能永久删除文件; trashDir 不会自动清理,但可以在插件之外被手工删掉——如果把它配到不受保护/不可信的卷上,插件也保护不了它。
- 审批依赖: 使用 approval.: "ask" 的类别(默认包括 fileMutations、directDelete、drag、 combo)在没有实时审批通道的部署(例如 DSH 审批策略 never、无头运行)中会失败关闭。这是刻意的失败关闭行为,不是 bug。
- 平台缺口: 紧急停止热键监听仅 Windows 有;Linux/macOS 上紧急路径是 /desktop-hand stop 命令和停止标志文件检查。Linux/macOS 输入后端属于尽力而为,且 macOS 输入文本会改动剪贴板。
- 真实应用验证: 自动化测试使用 fake 后端;开发阶段没有对 Blender、Office、浏览器等真实 GUI 做过端到端实操验证。请按 docs/ACCEPTANCE.md 走验收,并在用于重要工作前自行小心试点。
- 文件护栏不是备份: 重要数据请始终保留独立备份。
常见问题排查
| 现象 | 可能原因 / 处理 |
| 输入后端不可用 / INPUT_MISSING_BINARY | Windows:确认 PowerShell 可用(powershell.exe 或 pwsh.exe)。Linux:安装 xdotool(或设置 input.linux.xdotoolPath)。macOS:安装 cliclick 并授予辅助功能/自动化权限。演练可设 input.provider: "fake"。 |
| 输入工具被拒,提示授权未开启/过期 | 执行 /desktop-hand authorize input <分钟> <次数>(需要时加 sensitive)。授权会过期且受次数限制——用 /desktop-hand status 查看。 |
| 文件写入/删除被审批拒绝 | 默认 approval.fileMutations: "ask" 需要实时审批;DSH 审批策略为 never 时会失败关闭。若希望「会话授权即可」,把 desktop-hand.config.json 改成 "grant" 并重启。 |
| 拖拽或组合键(如 shift+a)被审批拒绝 | approval.drag 与 approval.combo 默认 ask;DSH 审批策略为 never 时会失败关闭。把审批策略切到 ask(看到提示)或把类别改成 "grant",依赖 input 会话授权。 |
| 想在不注入输入的情况下做安全自检 | 在包目录执行 node scripts/live-smoke.mjs:它会启动 Windows 后端、读取屏幕/指针/前台窗口、把 PNG 存到 %TEMP%\dh-live-home\live-shot.png,并验证停止标志守卫;绝不会移动鼠标、点击或输入。 |
| file operation denied by policy: ... read-only zone ... | 路径命中了 policy.readonly(或会话收紧的禁区)。这是预期行为;改配置移除该禁区或换路径。不要用 shell 命令绕过——那会让策略失去意义。 |
| delete-forbidden | 删除模式是 forbid(全局、按路径覆盖或本会话 tighten delete=forbid)。改配置并重载;注意会话收紧在该会话内不会解除。 |
| direct-delete-locked / 要求 confirm_direct | 授权 files 时加 direct-delete,调用时传 confirm_direct=true,非空目录还要 recursive=true;按配置可能仍需逐次审批。 |
| 授权过期 / 动作次数用尽 | 重新执行 /desktop-hand authorize …;重新授权会替换旧授权并重置预算(不叠加)。desktop_hand_screenshot 不消耗次数。 |
| 截图已保存但「看不到」 | 模型必须用 DSH 的 read_image 读取返回路径;截图位于 <会话工作目录>/.desktop-hand/screenshots/。 |
| 紧急热键没反应 | 仅 Windows 实现。查看 DSH 日志中的 emergency-stop hotkey 警告(无效按键、缺少 PowerShell/脚本、平台不支持)。可改用 /desktop-hand stop。停止后只有人能 /desktop-hand resume。 |
| 停止后所有工具都被拦截 | 这是设计:只允许 status、revoke、emergency_stop。执行 /desktop-hand resume。 |
| 改配置后插件激活失败 | 配置校验很严格;看报错(非法模式/上限/正则/版本、文件不可读)。坏配置绝不会静默回退默认值。 |
| 恢复被拒 | desktop_hand_restore_path 默认不覆盖;传 overwrite=true(会重新做禁区检查)或改用其他 destination。 |
开发与测试
在 desktop-hand 包目录下
npm test # node --test test/
npm run test:watch # node --test --watch test/
node --test test/
- Node.js ≥ 22(ESM、node:test)。当前测试套件共 167 个通过用例,不需要 DSH 运行时: defineTool 由外部注入,输入后端使用假实现,配置/策略/授权/限制/紧急停止/审计/回收站模块均直接做单元测试。
- 测试布局(test/):config.test.js(默认值、发现顺序、合并、校验)、policy.test.js(禁区、优先级、删除模式、受保护根、符号链接、会话收紧)、auth.test.js(授权、过期、预算、撤销、敏感区/ 直接删除解锁、收紧)、limits.test.js(几何、敏感区、各类上限)、emergency.test.js (停止/重置/中止)、audit.test.js(JSONL、轮转、脱敏)、trash.test.js(隔离/恢复/EXDEV 回退)、 input.test.js 与 keys.test.js(输入后端契约/后端实现与按键解析)、tools-fs.test.js 与 tools-input.test.js(用假运行时测工具处理逻辑)、integration.test.js(运行时装配、端到端流程与 /desktop-hand 命令处理)。
- scripts/live-smoke.mjs 是安全、只读的 Windows 后端实机自检(node scripts/live-smoke.mjs):读取屏幕/指针/前台窗口、把 PNG 存到 %TEMP%\dh-live-home\live-shot.png、验证停止标志守卫会拒绝动作;绝不会移动鼠标、点击或输入。
- 真实桌面的 GUI 自动化属于手工验收:docs/ACCEPTANCE.md。开发演练可把 input.provider 设为 "fake"。
开发阶段已核实的证据(可作为依据,但不是普遍保证):
- 自动化测试全量通过:167/167。
- 一个临时 DSH profile(headless 模板)成功把包装进 node_modules 并启动插件,没有激活告警。
- 本机安全实机自检成功:报告 2560×1600 屏幕、读取指针/前台窗口、写出 2560×1600 PNG 截图、停止标志守卫拒绝了一次动作、Pause 热键监听进程启停正常。
- 没有对真实 Blender/GUI 输入做验证——见 docs/ACCEPTANCE.md。
贡献建议:保持代码风格;新增工具/策略行为要补测试;新增配置字段时同步更新 docs/CONFIG.md。
许可证
MIT——见 package.json 的 license 字段。(本包目前没有单独的 LICENSE 文件,包元数据声明为 MIT。)
相关文档:配置参考(docs/CONFIG.md) ·手工验收(docs/ACCEPTANCE.md) · English README预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
Zero20230619/desktop-hand
让模型操作真实鼠标键盘并安全管理本机文件
相关插件 · 桌面端
Codex 任务面板chuspeeism/dashi-taskboard
现代化可灵活嵌入的任务面板,支持 Codex、DeepSeek Harness
★ 3,409已汉化DSH
71.7
多智能体自进化开发平台Prism-Shadow/penguin-harness
统一、稳定的 Agent 自进化框架全自动优化:任意模型 · 任意算法 · 任意 Benchmark
★ 3,111已汉化DSH
71.1
桌面宠物PC2005-cloud/dsh-pet
DSH 桌面宠物:一行命令装好即用的透明动画小桌宠,支持多开、大小位置随心配置;还内置 DIY 素材链,能用 AI…
★ 5,341已汉化DSH
71
多端 Agent 工作台GCWing/OpenBitFun
OpenBitFun 是一个高度可定制的开源 Agent 工作台,让任务按你的方式持续推进。
★ 3,449已汉化DSH
70.8
DSH Desktopanywhere-labs/dsh-desktop
为 DeepSeek Harness DSH 插件生态打造的现代化桌面端解决方案。万物皆「插件」,桌面本身也是「插件」。
★ 34,532已汉化DSH
70.7
桌面宠物伴侣OpenPetsHQ/openpets
桌面伴侣平台,带宠物、插件,还能选配本地智能体集成。
★ 1,353已汉化DSH
70.2
这是你的仓库?认领条目