dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
Codex-style Computer Use for DeepSeek Harness: the official window2 13-method desktop surface plus Chromium automation, a visible overlay with Esc interrupt, per-app approvals and bundled skills. Windows, MIT, no Codex required.
让 DeepSeek Harness 直接操作 Windows 桌面应用与 Chromium 标签页。
参考Codex 的 window2 工具面,在DSH上体验Codex版的Computer Use
English | 中文
截止到此插件发布前,官方已经在实验性版本更新Computer Use。总体设计思路与本插件有差异。目前本插件已做兼容性处理,可以同时安装两个插件,但不建议同时启用。
| 完整的官方工具面 | Codex官方 window2 的全部 13 个方法 —— list_windows、get_window、list_apps、launch_app、get_window_state、click、press_key、type_text、scroll、set_value、drag、perform_secondary_action、activate_window —— 名称、参数、默认值、返回体与错误串都与Codex一致。 |
| 真实输入与真实截图 | 输入走 SendInput,无障碍树走 UI Automation,截图走 Windows.Graphics.Capture(窗口被遮挡也能拍)。截图以视觉 image part 送达模型,JSON 里不含 base64。 |
| 可见、可中断的覆盖层 | 状态药丸 + 带弹簧动画的合成光标。药丸只在“截图那一瞬”被隐藏:模型永远读不到自己的状态药丸,而操作者始终看得到它。任何时候按 Esc 都能中断当前回合。 |
| 对照真机验证 | 行为对着官方插件与其 helper 做门禁:AX 树语法、覆盖层像素、光标运动、截图新鲜度、传输预算、批准文案、回合生命周期。 |
| Harness 原生,不是 MCP 套壳 | DSH 工具 + 随包技能,而不是一个 JavaScript REPL。插件本身是一个 DSH bundle:package.json + cordis.patch.yml + 包根目录下的入口模块。 |
| 双平面、单 sidecar | 桌面是进程级资源:指针、覆盖层、截图与批准流放在 HOST 平面;模型可见的工具放在 agent preset,普通编码会话不会拿到鼠标。 |
| 经验层 | 任务结束后写入本机笔记,下一次任务执行前作为参考回放 —— 见经验层。 |
| 操作系统 | Windows 10 1809+ 或 Windows 11,x64 |
| Harness | DeepSeek Harness(源码 checkout 或已安装的 dsh CLI) |
| Node | 20 或更高 |
| Python | 3.10+ —— 仅浏览器目录需要;13 个桌面工具是 Rust + Node |
| Rust | 仅在你重新编译 helper 时需要(helper-rs/bin/win32-x64/ 已随包提供 release 二进制) |
# 从 GitHub 安装(无构建步骤、无安装期脚本)
dsh plugin --profile web add github:wushi2333/dsh-computer-use_codex-style
# 从本地 checkout 安装
dsh plugin --profile web add /path/to/dsh-computer-use_codex-style
# 从打包好的 tarball 安装
dsh plugin --profile web add ./dsh-computer-use-0.1.0.tgz
包内声明了 dsh.bundle.patch,所以 dsh plugin 会把 HOST 平面的行加进 profile 并链接该包。插件是纯 ESM JavaScript 加一个预编译 helper,没有 prepare / postinstall 脚本,pnpm 不会要求你额外允许构建。
桌面工具故意放在 agent preset 里,而不是 host 组合里。挑一个你愿意交出鼠标的 preset,在它的 agent.cordis.yml 里加一行(preset 位于 $DSH_HOME/.agent-presets/<name>/):
# Computer Use 工具消费 HOST 的 dshComputerUse sidecar,本身不发布任何服务,
# 因此像 tool-bash 一样松散放置。请先在 profile 里安装 dsh-computer-use
# bundle,否则这一行会一直等待服务。
- id: tool-computer-use
name: dsh-computer-use/tool
config:
surfaces:
- computer
browserSkill: computer-use-browser
建议给 Computer Use 单独留一个 preset:用 standard 启动的会话保留原有工具集,永远不会碰到你的鼠标。
两个技能随包提供,需要复制到 harness 读取的技能根目录:
# 在 profile 目录下执行
node node_modules/dsh-computer-use/scripts/sync-skills.mjs --write --defaults
# 之后随时核对副本(只报告漂移,不写文件)
node node_modules/dsh-computer-use/scripts/sync-skills.mjs --check --defaults
--defaults 指向 $DSH_HOME/.agent-presets/computer-use/skills 与 $DSH_HOME/skills;其他根目录用 --target <dir>。
重启对应 profile(插件面改动在启动时读取),用你的 Computer Use preset 新建会话,然后给它一个具体任务:
打开记事本,把这几条要点整理成一份干净的草稿。
第一次工具调用会拉起 helper,药丸出现,模型开始它的「观察 → 动作 → 刷新」循环。
dsh plugin --profile web remove dsh-computer-use
如果你手工加过 preset 行和技能副本,一并删除。
flowchart TB
subgraph DSH["DSH profile"]
direction TB
subgraph HOST["HOST 平面 — 进程级"]
S["dsh-computer-use<br/>服务 `dshComputerUse`<br/>指针 · 覆盖层 · 截图 · 批准<br/>回合生命周期 · 经验层"]
end
subgraph PRESET["PRESET 平面 — 每个 agent preset"]
T["dsh-computer-use/tool<br/>13 个 window2 工具<br/>+ harness 扩展"]
K["skills<br/>computer-use · computer-use-browser"]
end
end
S <-->|"stdio 上的 JSON-RPC,一行一个 JSON"| H["dsh-computer-use.exe<br/>Rust helper"]
H -->|SendInput| APP["目标 Windows 应用"]
H -->|UI Automation| APP
H -->|Windows.Graphics.Capture| APP
T --> S
P["Python 引擎(可选)<br/>CDP · Playwright · 浏览器目录"] <--> S
一个进程一个 helper,同一时刻一个回合。 sidecar 惰性拉起 dsh-computer-use.exe 并常驻;每个请求都带会话 + 回合身份,回合作用域变化时发送 end_turn —— 它会冲刷观察租约、隐藏覆盖层并恢复系统光标。这与官方一致:官方的 Stop / Interrupt / SubagentStop 钩子都调用 turn_ended。
新鲜度靠身份,不靠时间。 没有 TTL:窗口身份、包围盒与人机输入监视器一致时观察才有效。只要有人碰了被观察的窗口,下一次输入就会以 user input was detected in this window; call get_window_state before continuing 被拒绝。
没有任何动作会被静默批准。 launch_app 与音频录制会暂停等待 harness 批准 UI,批准按应用记忆,被拒绝时按官方文案报错而不是重试。唯一的例外是权限预设已经替你回答了问题:完全访问会话(或批准策略为「从不询问」的会话)会直接放行应用门禁,computer_use_health 里会记录原因。
window2 方法| 工具 | 用途 |
|---|---|
list_windows | 当前可定位的窗口 |
get_window | 重新水合一个你已持有的窗口绑定 |
list_apps | 已安装应用及其打开的可定位窗口 |
launch_app | 启动应用(可能暂停等待批准) |
get_window_state | 某个窗口的截图 + 完整无障碍树 |
click | 按元素索引或截图坐标点击 |
press_key | 按键与组合键(X keysym 风格名称) |
type_text | 向当前焦点输入字面文本 |
scroll | 从窗口相对坐标滚动 |
set_value | 直接设置可访问元素的值 |
drag | 从一个点拖拽/绘制到另一个点 |
perform_secondary_action | 触发元素的次要动作 |
activate_window | 把窗口带到前台 |
| 工具 | 默认 | 用途 |
|---|---|---|
batch_actions | 开启 | 一次调用执行一串确定性动作,然后做一次 get_window_state |
computer_use_health | 始终 | 后端、允许列表、文档门禁、环境审计、经验层状态 |
computer_use_experience | 始终 | 读取、记录与更新本机经验笔记 |
click_element、scroll_element | 需显式开启 | 旧版 window-v1 别名 |
session_note、session_state、diagnostic_state、end_turn | 诊断 | 会话草稿、状态转储与回合控制 |
想确认到底挂上了什么,最快的办法是 computer_use_health:后端、暴露的工具目录、批准策略、注入了哪些环境变量、文档门禁,经验层状态,以及覆盖层诊断(当前用哪条药丸渲染路径、推了多少帧、系统光标是否被压制、当前用哪种防捕获模式、此刻是否正处于截图遮蔽中)。
截图、元素索引与坐标都属于同一次观察。模型遵循的契约是:
sequenceDiagram
participant M as 模型
participant C as Computer Use
participant A as 目标应用
M->>C: get_window_state(window, include_text: true)
C->>A: UI Automation 树
C-->>M: 树 + 元素索引(+ 截图)
Note over M: 索引只对这一次观察有效
M->>C: click(window, element_index: 12)
C->>A: SendInput
M->>C: get_window_state(window)
C-->>M: 新的树 + 新的截图
两条读会话记录时有用的结论:
originX/originY 是屏幕坐标 —— 两者永远不要混用。插件随包提供官方确认策略与一份硬拒绝清单,常驻提示词也会重复这些不可协商项:
allowedApps)从根上限制哪些 app id 可以被观察或驱动。扩展工具面之前,先读随包的策略文档:skills/computer-use/references/confirmations.md 与 skills/computer-use-browser/references/confirmations.md。
每次 Computer Use 运行都会留下两类记录,下一次运行开始前会读到它们:
| 经验条目(模型写) | 观测记录(机器写) | |
|---|---|---|
| 内容 | 症状、上下文、原因推测、绕法、结果、标签、日期 | 方法、成功/错误、应用、无障碍树是否存在、窗口几何、耗时 |
| 谁写 | 模型,在任务结束时 | 插件,每次调用都写 |
| 可信度 | 含推断的叙述 —— 仅供参考 | 事实,不做解读 |
存放位置(在插件目录内,已 gitignore,永不发布):
.experience/
lessons.jsonl 一行一条经验(规范存储)
lessons.md 同一批笔记的人类可读视图,按应用分组
observations.jsonl 机器写的事实
pending.jsonl 还没被写下来的问题
manual.jsonl 可选,手写,插件永不改写
如何到达模型。 一个回合内对某应用的首次观察会额外带一条参考文本块:
Experience notes for blender.exe - machine-local notes from earlier tasks here.
ADVISORY ONLY: not rules and not a gate. An upgrade, a DPI or configuration change can
invalidate them, and the current observation always wins over a stored note.
- 2026-09-14 [partial] accessibility was null in 11 of 13 observations -> prefer the app scripting interface
它以独立文本块的形式送达,官方 payload 的键集保持不变(window、screenshots、accessibility、cacheDiagnostics)。
「仅供参考」是靠机制而不是靠措辞。 任何条目都不能阻塞、替换或门禁一次调用;超过 staleAfterDays 的条目标记为可能过期;再次被验证有效的条目会刷新 verified;被更好解法取代的条目用 supersededBy 退役;并且明确告知模型:当前观察永远优先。
隐私。 输入文本、控件名、控件值与截图字节永不落盘。错误文本会脱敏(C:/Users/name/... 变成 %USERPROFILE%)并截断。用 experience.enabled: false 或 DSH_CU_EXPERIENCE=off 可以整体关闭。
cordis.patch.yml 的 computer-use 行)| 键 | 默认 | 含义 |
|---|---|---|
backend | windows | windows(原生 helper)或 fake(脚本化桌面,用于测试) |
surface | computer | 向 helper 请求的工具目录 |
stealFocus | true | 输入方法会自动激活目标窗口 |
maxImageEdge | 0 | DSH 扩展:0 保持官方行为(不缩放);设为 1280 可用画质换 token |
approveLaunch | true | launch_app 前询问 |
timeoutMs / launchAppTimeoutMs / listAppsTimeoutMs | 10000 / 15000 / 20000 | 请求预算;超时会拒绝在途请求(官方传输语义下还会杀掉 helper)。list_apps 是唯一在作答前要构建「已安装应用目录」的方法,所以它有自己的 DSH 预算,而这条预算必须低于 harness 的 25 秒工具调用预算:否则先被 harness 中止,而中止会以「取消」的形式到达 helper(旧版本会把这一回合latch成「用户已停止」)。list_apps 超时不再杀 helper(keepAlive),热目录缓存得以保留 |
startupTimeoutMs | 15000 | helper 启动预算 |
preserveHelperOnTimeout | false | 超时后保留 helper 以便排查 |
allowedApps | [] | 非空时只有这些 app id 可被观察或驱动 |
envAllowlist | [] | 在随包允许列表之外额外转发给 helper 的环境变量名 |
overlayCaptureExclusion | mask | 状态药丸如何避开模型看到的截图:mask(默认)在单次捕获期间用合成器隐藏药丸,操作者始终能看到;wda 改用 SetWindowDisplayAffinity(WDA_EXCLUDEFROMCAPTURE);off 不排除,药丸会出现在截图里 |
experience.*)| 键 | 默认 | 含义 |
|---|---|---|
enabled | true | 读写笔记的总开关 |
store | "" | 空表示 <pluginRoot>/.experience |
captureObservations | true | 是否写机器观测事实 |
injectDigest | true | 是否把参考块附在匹配应用的首次观察上 |
maxEntries / maxChars | 3 / 900 | 注入预算 |
staleAfterDays | 90 | 超过这个天数的条目标记为可能过期 |
includeStale | true | 设为 false 时过期条目完全不注入 |
retainEntries / retainObservationDays | 200 / 30 | 保留策略 |
redactPaths | true | 对记录下来的错误文本做本地路径脱敏 |
dsh-computer-use/tool 行)| 键 | 默认 | 含义 |
|---|---|---|
surfaces | [computer] | 暴露哪些目录(computer、browser、mac、all) |
browserSkill | computer-use-browser | 解锁浏览器目录的技能名 |
approvalDefault | prompt | helper 因批准而拒绝时的行为:prompt、allow、deny。完全访问会话(或批准策略为「从不询问」的会话)直接放行且不询问;显式 deny 仍然失败关闭 |
approvalTools | {} | 按工具覆盖上面的策略 |
enabledTools | [batch_actions] | 哪些 harness 扩展进入模型可见目录 |
同一个 sidecar 还提供 Chromium 面:标签页、CDP 调用与事件、DOM 与无障碍快照、Playwright 风格交互、下载,以及通过随包 Chrome 扩展认领已登录标签页,共 95 个工具。
它是技能门控的:模型加载 computer-use-browser 技能前这些工具不会注册,普通会话的目录不会被淹没。浏览器路径是 Python 3.10+(computer_use/),通过 CDP 连接浏览器,不经过桌面 helper。
一切都能在本仓库复现。插件面门禁完全不需要桌面:
# 在 DeepSeek Harness checkout 下运行,以便解析 peer 依赖
node --import tsx/esm --test tests/contracts.test.mjs tests/experience.test.mjs
# helper(Rust)
cargo test --release --manifest-path helper-rs/Cargo.toml
# 引擎(Python)
python -m pytest -q
# fake 后端冒烟:不需要桌面,也不会碰鼠标
node src/smoke.mjs
当前状态(Windows 11 x64):插件门禁 38/38(25 条契约 + 13 条经验层)、Rust 202 通过、Python 289 通过 / 1 跳过、fake 后端冒烟通过。
parity 套件会操作真实桌面,把本插件与官方实现逐项对比 —— 覆盖层像素、光标运动、截图新鲜度、window-state 用例、传输预算、AX 树字节、插件生命周期:
pwsh -File parity/verify-all.ps1
它需要一个准备好的桌面(一个 Parity Target 窗口,AX 对比还需要 Word 与资源管理器),缺少夹具时会报 SKIP 而不是给出虚假的 PASS。开发证据 —— 逆向报告、差距登记册与验证日志 —— 刻意不放进公开源码树。
# JavaScript 插件:无需构建,纯 ESM
node src/exports-check.mjs
# Rust helper:构建、测试,并发布插件随包的二进制
pwsh -File scripts/ship-helper.ps1
# Python 引擎(可选浏览器面)
python -m pip install -e .
scripts/ship-helper.ps1 会跑 cargo build --release、helper 测试套件,把 dsh-computer-use.exe 复制到 helper-rs/bin/<platform>-<arch>/ 并打印 SHA-256。因为该二进制已被跟踪,全新 checkout 无需 Rust 工具链也能直接运行。
想在开发时直接指向 checkout 而不是安装副本:
dsh plugin --profile web add /path/to/dsh-computer-use_codex-style
package.json DSH bundle 清单(dsh.bundle.patch + dsh.skills)
cordis.patch.yml 本 bundle 插入的 HOST 平面层
dsh-plugin.json Codex 风格的插件清单(身份、界面、工具列表)
src/
index.js HOST 服务:sidecar 生命周期、回合生命周期、health
tool.js PRESET 行:工具注册、批准、文档门禁
sidecar.js helper 传输:启动、JSON-RPC、预算、路由
experience.js 经验层:存储、digest、观测、待补记
prompt.js 常驻提示词段 + 按需参考文档清单
paths.js helper / python 发现逻辑
skills/
computer-use/ 桌面技能及其参考文档
computer-use-browser/ 浏览器技能及其参考文档
helper-rs/ Rust helper(输入、UIA、截图、覆盖层、光标)
bin/<platform>-<arch>/ 随包发布的 release 二进制
helper-swift/ macOS helper 源码(尚未提供二进制)
computer_use/ Python 引擎(CDP、Playwright、浏览器目录)
parity/ 验证套件与夹具
tests/ 插件与引擎测试
docs/ 插件说明与图片资源
| 现象 | 含义 |
|---|---|
| 函数列表里没有 Computer Use 工具 | 会话没有用挂载 dsh-computer-use/tool 的 preset,或者安装 bundle 后没有重启 profile。 |
The Windows Computer Use helper may have failed | helper 没在 startupTimeoutMs 内启动。检查允许列表与环境允许列表后重试;computer_use_health 会报告实际注入了什么。 |
coordinate input target is unavailable | 观察已过期或窗口已变化。重新 get_window_state 并对新结果操作。 |
user input was detected in this window | 有人用过这个窗口。下一次输入前必须重新观察。 |
| 运行过程中焦点跳动 | stealFocus: true 的预期行为:输入方法会激活目标窗口。 |
| 桌面被锁定 | Computer Use 会停下并要求你解锁,它绝不操作 LockApp.exe。 |
| 屏幕上出现两个光标 | 覆盖层会画一个合成光标并把系统光标置空。真出现两个时,读 diagnostic_state → overlayState.systemCursorFailures:计数非零说明压制失败,那是设计上唯一会通向「双指针」的路径。 |
| 状态药丸一直不出现 | 读 computer_use_health → overlay.captureExclusion。默认的 mask 永远让药丸留在屏幕上。官方风格的 wda 亲和性会在某些 Windows/DWM/GPU 组合下让 DWM 连屏幕上都不再合成药丸的 DirectComposition 内容(操作者只看到合成光标、看不到药丸,而所有覆盖层 API 仍然报 visible=true),所以它是可选项。遮蔽卡住会表现为 overlay.captureMasked = true,而 helper 会在五秒后自行解除。 |
list_apps 超时 | 已安装应用目录是唯一在作答前真的要做重活的方法。两份能留下来的记录:computer_use_health → overlay/appCatalog 计时,以及 helper 自己写的 %LOCALAPPDATA%\computer-use-app-catalog\slow-requests.log(记录超过 DSH_CU_SLOW_REQUEST_MS(默认 1 秒)的每个请求,含目录与重建阶段耗时)。传输层超时会杀掉 helper,所以进程内诊断在你来得及问之前就已经消失;如果这台机器上目录确实慢,调大 listAppsTimeoutMs |
| 没按 Esc 却报 “Computer Use was stopped by the user with the physical Escape key” | 工具调用被 harness 自己的预算中止,旧版本的 helper 会把该回合 latch 成「已停止」。现在中止只发 cancel(仅隐藏覆盖层);若仍出现,说明 helper 是旧版本(下一回合会拉起新的 helper) |
launch_app 与音频录制会暂停等待 harness 批准 UI;没有任何动作会被静默批准,被拒绝的请求也绝不重试。完全访问(或批准策略为「从不询问」)的会话除外:那是用户自己的选择,插件按 allow 放行并留下审计记录。本插件对标的基线是 Codex Computer Use 插件 26.903.61454:相同的 13 个方法、相同的参数名与默认值、相同的返回体、相同的错误串、相同的 AX 树语法、相同的预算、相同的覆盖层语义。
DSH官方的Computer Use采用设计思路不大一致。如果希望使用Codex风格的功能,可以使用本插件。
MIT —— 见 LICENSE。
这是面向 DeepSeek Harness 的独立重实现,与 OpenAI 没有隶属、背书或赞助关系。Codex 是 OpenAI 的商标,此处提及仅用于描述行为兼容性。
仓库中包含逐字复制的第三方材料,它们保留各自的条款:
helper-rs/assets/prompts/ 与各技能的 references/ 目录包含官方 Computer Use 的 guidance、API 参考与确认策略文档,复制它们是为了让模型读到与官方插件相同的文字。parity/golden-ax/ 与 parity/ax-rich/ 包含官方 helper 产出的无障碍树样本,作为 parity 门禁的对比基线。如果你要再分发本项目,请按你获取这些文件时所依据的条款复核它们。