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

桌面操控 wushi2333/dsh-computer-use_codex-style

DeepSeek Harnessv0.3.1
wushi233349 天前有提交已提供中文文档扫描:含敏感能力

在 DeepSeek Harness 里操作 Windows 桌面应用和 Chromium 标签页。 基于 Codex…

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

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

自动兼容检查有告警:npm 同名包「dsh-computer-use」归属 988hj7tczd-oss/dsh-computer-use,装到的可能不是本插件。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add wushi2333/dsh-computer-use_codex-style
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · security
装得上吗
本站已真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 49 天前
档位由哪些信号合成

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意

npm 同名包「dsh-computer-use」归属 988hj7tczd-oss/dsh-computer-use,装到的可能不是本插件

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-computer-use @ 0.3.1
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/11/1 16:37:29

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

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

可执行外部命令发起外部网络请求
查看扫描证据(共 78 处,展示前 77 条)
  • 发起网络请求
    src/index.js:306
    const payload = await this.sidecar.request('health')
  • 发起网络请求
    src/index.js:339
    return this.sidecar.request('tools', { surface: surface || this.config.surface })
  • 发起网络请求
    src/index.js:346
    return this.sidecar.request('prompt')
  • 发起网络请求
    src/index.js:362
    return this.sidecar.request('call', { name, arguments: arguments_ || {}, meta: meta || {} }, signal)
  • 发起网络请求
    src/index.js:369
    return this.sidecar.request('interrupt')
  • 发起网络请求
    src/index.js:403
    return this.sidecar.request('cancel', {})
  • 发起网络请求
    src/tool.js:785
    const outcome = await service.request(request)
  • 执行外部命令来自配置/变量
    src/sidecar.js:509
    const child = spawn(exe, args, {
  • 执行外部命令来自配置/变量
    src/sidecar.js:549
    const child = spawn(command, args, {
  • 发起网络请求
    src/sidecar.js:702
    return this.request(method, params, signal)
  • 发起网络请求
    computer_use/chrome_extension/background.js:23
    const res = await fetch(url);
  • 发起网络请求
    computer_use/chrome_extension/background.js:73
    const res = await fetch(targetUrl, { credentials: "include" });
  • 发起网络请求
    computer_use/chrome_extension/background.js:98
    await fetch(`${base}/ingest`, {
  • 发起网络请求
    computer_use/chrome_extension/background.js:108
    const pending = await fetch(`${base}/pending`).then((r) => r.json());
  • 发起网络请求
    computer_use/chrome_extension/background.js:116
    await fetch(`${base}/ingest`, {
  • 执行外部命令来自配置/变量
    parity/atomic-cursor-check.mjs:13
    const c = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令固定命令
    parity/atomic-cursor-check.mjs:22
    const probe = () => { try { return execFileSync('pwsh', ['-NoProfile', '-File', repoRoot + '\\parity\\probe-cursor-z.ps1', String(myPid)], { encoding:
  • 执行外部命令来自配置/变量
    parity/ax-rich-parity.mjs:64
    this.c = spawn(exe, ['--parent-pid', String(process.pid)], { stdio: ['pipe', 'pipe', 'pipe'], env })
  • 执行外部命令固定命令
    parity/ax-rich-parity.mjs:92
    execFileSync('pwsh', args, { stdio: 'ignore', timeout: 15000 })
  • 执行外部命令来自配置/变量
    parity/check-fix1.mjs:19
    this.c = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令来自配置/变量
    parity/cursor-test.mjs:21
    this.c = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令来自配置/变量
    parity/cursor-trace.mjs:18
    this.c = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令固定命令
    parity/cursor-trace.mjs:37
    const out = execSync('powershell -NoProfile -Command "Add-Type -AssemblyName System.Windows.Forms; $p=[System.Windows.Forms.Cursor]::Position; \"$($p.
  • 执行外部命令固定命令
    parity/cursor-trace.mjs:70
    const out = execSync('pwsh -NoProfile -ExecutionPolicy Bypass -File repoRoot + "/parity/screen-shot.ps1" repoRoot + "/parity/full-screen.png"', { enco
  • 执行外部命令来自配置/变量
    parity/dcomp-selftest.mjs:14
    const c = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'], env: { ...process.env, DSH_CU_OVERLAY_SELFTEST: '1' } })
  • 执行外部命令固定命令
    parity/dcomp-selftest.mjs:36
    console.log(execSync('pwsh -NoProfile -ExecutionPolicy Bypass -File repoRoot + "/parity/pill-probe.ps1"', { encoding: 'utf8' }).trim())
  • 执行外部命令来自配置/变量
    parity/diag-affinity.mjs:13
    const c = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令来自配置/变量
    parity/diag-coords.mjs:13
    const c = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令来自配置/变量
    parity/diag2.mjs:13
    const c = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令来自配置/变量
    parity/fresh-test.mjs:18
    this.c = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令来自配置/变量
    parity/golden-ax.mjs:33
    this.c = spawn(exe, ['--parent-pid', String(process.pid)], { stdio: ['pipe', 'pipe', 'pipe'], env })
  • 执行外部命令来自配置/变量
    parity/hold-overlay.mjs:13
    const c = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令固定命令
    parity/interactive-physical.mjs:27
    return execSync(
  • 发起网络请求
    parity/interactive-physical.mjs:82
    sidecar.request('call', { name, arguments: args || {}, meta: meta || {} })
  • 发起网络请求
    parity/interactive-physical.mjs:121
    const diag = await sidecar.request('diagnostic_state', {})
  • 执行外部命令固定命令
    parity/interactive-physical.mjs:136
    execSync('pwsh -NoProfile -ExecutionPolicy Bypass -File repoRoot + "/parity/inject-key.ps1"', {
  • 发起网络请求
    parity/interactive-physical.mjs:218
    const diag0 = await sidecar.request('diagnostic_state', {})
  • 执行外部命令固定命令
    parity/interactive-physical.mjs:232
    const out = execSync(
  • 发起网络请求
    parity/interactive-physical.mjs:252
    diag = await sidecar.request('diagnostic_state', {})
  • 执行外部命令固定命令
    parity/interactive-physical.mjs:349
    try { execSync('taskkill /IM notepad.exe /F', { stdio: 'ignore' }) } catch {}
  • 执行外部命令来自配置/变量
    parity/interrupt-marker.mjs:29
    this.c = spawn(EXE, ['--parent-pid', String(process.pid)], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令来自配置/变量
    parity/motion-curve.mjs:43
    this.c = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令固定命令
    parity/overlay-lifecycle.mjs:30
    const psfile = (f, args) => execSync('pwsh -NoProfile -ExecutionPolicy Bypass -File "' + f + '" ' + (args || ''), { encoding: 'utf8' })
  • 执行外部命令来自配置/变量
    parity/overlay-lifecycle.mjs:31
    const targetProc = spawn(TARGET, [], { stdio: 'ignore' })
  • 执行外部命令来自配置/变量
    parity/overlay-lifecycle.mjs:35
    this.c = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令固定命令
    parity/pill-capture-mask.mjs:58
    const [count, width] = String(execFileSync('pwsh', ['-NoProfile', '-Command', SCREEN_ACCENT], { encoding: 'utf8' })).trim().split(/ +/)
  • 执行外部命令固定命令
    parity/pill-capture-mask.mjs:71
    return Number(String(execFileSync('pwsh', ['-NoProfile', '-Command', ps], { encoding: 'utf8' })).trim())
  • 执行外部命令来自配置/变量
    parity/pill-capture-mask.mjs:76
    this.child = spawn(exe, ['--parent-pid', '0'], {
  • 执行外部命令固定命令
    parity/pill-capture-mask.mjs:113
    const bounds = String(execFileSync('pwsh', ['-NoProfile', '-Command',
  • 执行外部命令固定命令
    parity/pill-capture-mask.mjs:119
    return String(execFileSync('pwsh', ['-NoProfile', '-File', path.join(pluginRoot, 'parity', 'move-target.ps1'),
  • 执行外部命令来自配置/变量
    parity/pill-probe.mjs:18
    this.c = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令固定命令
    parity/pill-probe.mjs:53
    const out = execSync('pwsh -NoProfile -ExecutionPolicy Bypass -File repoRoot + "/parity/pill-probe.ps1"', { encoding: 'utf8' })
  • 执行外部命令固定命令
    parity/pill-reshow.mjs:53
    const [count, width] = String(execFileSync('pwsh', ['-NoProfile', '-Command', COUNT], { encoding: 'utf8' })).trim().split(/ +/)
  • 执行外部命令来自配置/变量
    parity/pill-reshow.mjs:59
    this.child = spawn(exe, ['--parent-pid', '0'], {
  • 执行外部命令来自配置/变量
    parity/probe.mjs:13
    const child = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令固定命令
    parity/sidecar-observe-act.mjs:43
    try { execFileSync('pwsh', ['-NoProfile', '-Command', 'Get-Process dsh-computer-use -ErrorAction SilentlyContinue | Stop-Process -Force'], { stdio: 'i
  • 执行外部命令固定命令
    parity/sidecar-observe-act.mjs:48
    running = execFileSync('pwsh', ['-NoProfile', '-Command', "if (Get-Process ParityTarget -ErrorAction SilentlyContinue) { 'yes' } else { 'no' }"], { en
  • 执行外部命令来自配置/变量
    parity/sidecar-observe-act.mjs:51
    const proc = spawn(repoRoot + '/parity/ParityTarget.exe', [], { stdio: 'ignore', detached: true })
  • 执行外部命令固定命令
    parity/sidecar-observe-act.mjs:55
    try { execFileSync('pwsh', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', repoRoot + '/parity/raise-target.ps1'], { stdio: 'ignore' }) } catch
  • 发起网络请求
    parity/sidecar-wire.mjs:30
    await sidecar.request('health')
  • 发起网络请求
    parity/sidecar-wire.mjs:34
    await sidecar.request('tools', { surface: 'computer' })
  • 发起网络请求
    parity/sidecar-wire.mjs:35
    await sidecar.request('cancel', {})
  • 执行外部命令来自配置/变量
    parity/smoke-axdiff.mjs:17
    const child = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令来自配置/变量
    parity/smoke-diff-seq.mjs:15
    const child = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令来自配置/变量
    parity/smoke-twocell.mjs:19
    this.child = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令来自配置/变量
    parity/tmp-activate-diag.mjs:14
    const c = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令来自配置/变量
    parity/tmp-click-diag.mjs:14
    const c = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令来自配置/变量
    parity/tmp-fg-diag.mjs:14
    const c = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令来自配置/变量
    parity/tmp-first-click.mjs:14
    const c = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令来自配置/变量
    parity/window-states.mjs:21
    this.c = spawn(EXE, ['--parent-pid', '0'], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 执行外部命令固定命令
    parity/window-states.mjs:38
    const ps = (script, args) => execSync('pwsh -NoProfile -ExecutionPolicy Bypass -File repoRoot + "/parity/' + script + '" ' + (args || ''), { encoding:
  • 执行外部命令固定命令
    parity/window-states.mjs:92
    execSync(
  • 执行外部命令固定命令
    parity/window-states.mjs:97
    try { execSync('taskkill /IM notepad.exe /F', { stdio: 'ignore' }) } catch {}
  • 发起网络请求
    src/smoke.mjs:14
    const health = await sidecar.request('health')
  • 发起网络请求
    src/smoke.mjs:16
    const listed = await sidecar.request('tools', { surface: 'computer' })
  • 发起网络请求
    src/smoke.mjs:22
    const browser = await sidecar.request('tools', { surface: 'browser' })
  • 发起网络请求
    src/smoke.mjs:27
    const shot = await sidecar.request('call', {
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-tools@deepseek-ai/dsh-system-prompt@deepseek-ai/dsh-user-approval@deepseek-ai/dsh-attachment@deepseek-ai/schemastery
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • Esc中断与按应用审批
展开完整介绍(122 字)↓

DeepSeek Harness 的 Codex 风格 Computer Use:官方 window2 13 方法桌面接口加 Chromium 自动化,可见浮层支持 Esc 中断、按应用审批和内置技能。Windows,MIT,无需 Codex。

README

由 DeepSeek 最新模型翻译生成
Computer Use for DeepSeek Harness 在 DeepSeek Harness 里操作 Windows 桌面应用和 Chromium 标签页。 基于 Codex 的 window2 工具面 —— DeepSeek Harness 上的 Codex 风格 Computer Use 体验。 截至本插件发布时,官方 harness 已在实验版本中推出 Computer Use,设计上有明显差异。本插件可安全共存:两者能并排安装,但不建议同时运行两个驱动。 目录 - 你能得到什么 - 快速开始 - 工作原理 - 工具面 - 操作与刷新循环 - 安全模型 - 体验层 - 配置 - 浏览器自动化 - 验证 - 从源码构建 - 仓库结构 - 故障排查 - 安全与隐私 - 兼容性与已知缺口 - 许可与署名 你能得到什么
展开完整文档(README 剩余 1 节)
Computer Use for DeepSeek Harness

在 DeepSeek Harness 里操作 Windows 桌面应用和 Chromium 标签页。 基于 Codex 的 window2 工具面 —— DeepSeek Harness 上的 Codex 风格 Computer Use 体验。

截至本插件发布时,官方 harness 已在实验版本中推出 Computer Use,设计上有明显差异。本插件可安全共存:两者能并排安装,但不建议同时运行两个驱动。

目录

- 你能得到什么
- 快速开始
- 工作原理
- 工具面
- 操作与刷新循环
- 安全模型
- 体验层
- 配置
- 浏览器自动化
- 验证
- 从源码构建
- 仓库结构
- 故障排查
- 安全与隐私
- 兼容性与已知缺口
- 许可与署名

你能得到什么

| 完整的 Codex 工具面 | 官方 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,窗口被遮挡也能截到。截图以视觉图像块的形式送达,绝不以 base64 塞进 JSON。 |
| 可见、可取消的浮层 | 一个状态胶囊,加一个带动画的合成光标。每次截图期间胶囊都会隐藏,这样模型不会把自己状态胶囊读回去,而你始终能看到它。Esc 随时打断当前轮次。 |
| 对照真实实现验证过 | 行为以官方插件及其 helper 为基准:AX 树语法、浮层像素、光标运动、截图新鲜度、传输预算、审批字符串、轮次生命周期。 |
| Harness 原生,而非 MCP 形态 | DSH 工具自带技能,不是 JavaScript REPL。插件是 DSH bundle:package.json + cordis.patch.yml + 包根目录下的入口模块。 |
| 两个平面,一个 sidecar | 桌面是进程级的,所以指针、覆盖层、捕获和审批都放在 HOST 平面;面向模型的工具放在智能体预设里,因此普通编码会话永远碰不到鼠标。 |
| 经验层 | 任务结束后写下本机专属笔记,下一个任务开始前作为参考上下文回放——见经验层。 |

快速开始

环境要求

| 操作系统 | Windows 10 1809+ 或 Windows 11,x64 |
| Harness | DeepSeek Harness(源码检出或已安装的 dsh 命令行) |
| Node | 20 或更高 |
| Python | 3.10+ —— 仅用于可选的浏览器目录;13 个桌面工具是 Rust + Node |
| Rust | 仅在你重新构建 helper 时需要(helper-rs/bin/win32-x64/ 里已附带 release 二进制) |

1. 安装 bundle

from GitHub (no build step, no install-time script)
dsh plugin --profile web add github:wushi2333/dsh-computer-use_codex-style

from a local checkout
dsh plugin --profile web add /path/to/dsh-computer-use_codex-style

from a packed tarball
dsh plugin --profile web add ./dsh-computer-use-0.1.0.tgz

bundle 声明了 dsh.bundle.patch,所以 dsh plugin 会把 HOST 平面那一行加进配置档,并链接该包。插件是纯 ESM JavaScript 加一个预构建 helper,因此不带 prepare 或 postinstall 脚本——pnpm 永远不会让你允许构建。

2. 把工具行加进智能体预设

桌面工具刻意放在智能体预设里,而不是 host 组合里。挑一个你想交出鼠标的预设,往它的 agent.cordis.yml 加一行(预设位于 $DSH_HOME/.agent-presets/<name>/):

Computer Use tools consume the HOST dshComputerUse sidecar. They publish
nothing, so they sit loose like tool-bash. Install the dsh-computer-use
bundle in the profile first; otherwise this row waits for the service.
- id: tool-computer-use
name: dsh-computer-use/tool
config:
surfaces:
- computer
browserSkill: computer-use-browser

如果你愿意,也可以给 Computer Use 单独留一个预设:用 standard 预设启动的会话就保持正常工具集,永远不碰你的鼠标。

3. 交付技能

两个技能随包发布,会被复制到 harness 读取的技能根目录:

from the profile directory
node node_modules/dsh-computer-use/scripts/sync-skills.mjs --write --defaults

verify the copies later (reports drift, writes nothing)
node node_modules/dsh-computer-use/scripts/sync-skills.mjs --check --defaults

4. 重启并运行重启配置档(插件平面的改动在启动时读取),用你的 Computer Use 预设启动会话,然后提一个具体的需求:

打开 Notepad,把这些要点整理成一份干净的草稿。

第一次工具调用会启动 helper,胶囊出现,模型开始它的 observe → act → refresh 循环。

卸载 sh
dsh plugin --profile web remove dsh-computer-use

如果你手动添加过预设行和复制过来的技能,也一并删掉。

工作原理 mermaid
flowchart TB
subgraph DSH["DSH profile"]
direction TB
subgraph HOST["HOST plane — process-wide"]
S["dsh-computer-useService dshComputerUsepointer · overlay · capture · approvalsturn lifecycle · experience store"]
end
subgraph PRESET["PRESET plane — one agent preset"]
T["dsh-computer-use/tool13 window2 tools+ harness extensions"]
K["skillscomputer-use · computer-use-browser"]
end
end
S <-->|"JSON-RPC over stdio, one JSON object per line"| H["dsh-computer-use.exeRust helper"]
H -->|SendInput| APP["target Windows app"]
H -->|UI Automation| APP
H -->|Windows.Graphics.Capture| APP
T --> S
P["Python engine (optional)CDP · Playwright · browser catalog"] <--> 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 的批准界面,批准按应用粒度进行,拒绝会按官方措辞上报,而不是重试。唯一的例外是权限预设已经回答过这个问题:完全访问会话(或批准策略从不弹窗的会话)会直接放行应用门禁,无需询问,computer_use_health 会记录原因。

工具面

13 个官方 Codex 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 | 把窗口带到前台 |

Harness 扩展

| 工具 | 默认 | 用途 |
| 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 是查看实际挂载内容最快的方式:后端、暴露的目录、审批策略、注入的环境变量名、文档门禁、经验层状态,以及叠加层诊断(当前生效的是哪个 pill 渲染器、它推送了多少帧、系统光标是否被抑制、当前强制的是哪种捕获排除,以及捕获是否正在遮挡 pill)。

动作与刷新循环

截图、元素索引和坐标都属于同一次观察。模型遵循的约定是: mermaid
sequenceDiagram
participant M as Model
participant C as Computer Use
participant A as Target app
M->>C: get_window_state(window, include_text: true)
C->>A: UI Automation tree
C-->>M: tree + element indexes (+ screenshot)
Note over M: indexes are valid for THIS observation only
M->>C: click(window, element_index: 12)
C->>A: SendInput
M->>C: get_window_state(window)
C-->>M: fresh tree + fresh screenshot

读日志之前,有两点值得先知道:

- 一次观察只做一个动作。 想交错执行动作,或者失败后重试,都得先重新观察一次。
- 坐标是窗口相对的逻辑像素。 截图的 originX/originY 是屏幕坐标——两者绝不能混用。

安全模型

插件自带官方确认策略和硬性拒绝列表,常驻的提示词段落反复强调几条不可妥协的规则:

- 绝不碰 Windows 键——单独按不行,组合键也不行。
- 不做终端自动化(Windows Terminal、Command Prompt、PowerShell),不碰运行对话框,不在文件资源管理器里嵌入 shell 脚本。
- 不碰密码管理器,不碰安全或反恶意软件工具,不碰身份验证或年龄验证对话框。
- 不可信内容(页面、邮件、文档、截图)可以提供信息,但不能授予权限,也不能证明意图。
- 可选允许列表(allowedApps)限制哪些应用 id 可以被观察或驱动。
扩展工具面之前,先读随附的策略:skills/computer-use/references/confirmations.md 和 skills/computer-use-browser/references/confirmations.md。

经验层

每次 Computer Use 运行都会留下两类记录,下一次运行在动手之前会先读它们:

| | Lessons(模型写的) | Observations(机器写的) |
| 内容 | 症状、上下文、疑似原因、绕过办法、结果、标签、日期 | 方法、ok/error、应用、无障碍是否存在、窗口几何、耗时 |
| 谁来写 | 模型,在任务结束时 | 插件,每次调用都写 |
| 可信度 | 带推断的叙述——仅供参考 | 事实,不做解读 |

存放位置(在插件文件夹内,已 gitignore,从不发布): text .experience/ lessons.jsonl 每条笔记一条 JSON 记录(权威存储) lessons.md 同样的笔记,给人看的渲染版,按应用分组 observations.jsonl 机器写的事实 pending.jsonl 还没人写下来的问题 manual.jsonl 可选,手写,插件从不改写

怎么送到模型手里。 一轮里某个应用的第一次观察会多带一个参考文本块: text 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

笔记作为独立块传输,所以官方载荷的键集保持原样(window、screenshots、accessibility、cacheDiagnostics)。

从结构上就是参考,不是靠措辞。 笔记永远不能阻塞、替换或拦截调用;超过 staleAfterDays 的笔记会被标记;再次被证明正确的笔记会用 verified 刷新;被更好笔记取代的会用 supersededBy 退役;并且会告诉模型:当前观察永远优先。

隐私。 输入的文本、元素名、元素值、截图字节永远不会进入这些文件。错误字符串会做路径脱敏(C:/Users/name/... 变成 %USERPROFILE%)并截断。用 experience.enabled: false 或 DSH_CU_EXPERIENCE=off 可以关掉整个层。

配置

HOST 平面(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 | 请求预算;超时会拒绝正在进行的请求(官方 transport 会杀掉 helper)。list_apps 是唯一一个在应答前先构建已安装应用目录的方法,所以它有独立的 DSH 预算,而且这个预算必须低于 harness 的 25 秒工具调用预算:如果 harness 先中止调用,中止会以取消的形式到达 helper,而中止曾经会把该轮锁死为「被用户停止」。list_apps 超时后 helper 仍然存活(keepAlive),这样热目录就能保留下来 |
| startupTimeoutMs | 15000 | Helper 启动预算 |
| preserveHelperOnTimeout | false | 超时后保留 helper 存活,便于调试 |
| allowedApps | [] | 非空表示只允许观察或驱动这些 app id |
| envAllowlist | [] | 在随附的允许列表之外,额外转发给 helper 的环境变量名 |
| overlayCaptureExclusion | mask | 状态胶囊如何避开模型的截图:mask 在一次截图期间于合成器里隐藏它(你自己仍然看得见),wda 改为应用 SetWindowDisplayAffinity(WDA_EXCLUDEFROMCAPTURE),off 则让胶囊留在画面里 |

体验层(同一行的 experience.)

| Key | Default | Meaning |
| enabled | true | 读写笔记的总开关 |
| store | "" | 空表示 <pluginRoot>/.experience |
| captureObservations | true | 写入机器观察到的事实 |
| injectDigest | true | 把建议块附加到匹配 app 的第一条观察记录上 |
| maxEntries / maxChars | 3 / 900 | 注入预算 |
| staleAfterDays | 90 | 早于这个天数的笔记会被标记为可能过时 |
| includeStale | true | 设为 false 会把过时笔记从摘要里彻底剔除 |
| retainEntries / retainObservationDays | 200 / 30 | 保留策略 |
| redactPaths | true | 在记录的错误文本里隐去本地配置档路径 |

PRESET 平面(dsh-computer-use/tool 行)

| Key | Default | Meaning |
| surfaces | [computer] | 暴露哪些目录(computer、browser、mac、all) |
| browserSkill | computer-use-browser | 解锁浏览器目录的技能 |
| approvalDefault | prompt | helper 因审批而拒绝时怎么办:prompt、allow、deny。完全访问会话(或审批策略从不提示的会话)无需询问即可放行,显式 deny 仍然按失败关闭处理 |
| approvalTools | {} | 按工具覆盖上面的设置 |
| enabledTools | [batch_actions] | 哪些 harness 扩展进入面向模型的目录 |

浏览器自动化

同一个 sidecar 还提供 Chromium 界面:95 个工具,覆盖标签页、CDP 调用与事件、DOM 与无障碍快照、Playwright 风格的交互、下载,以及通过随附的 Chrome 扩展认领已登录的标签页。
它采用技能门控:模型加载 computer-use-browser 技能之前,工具不会注册,所以普通会话不会被工具目录淹没。浏览器路径需要 Python 3.10+(computer_use/),通过 CDP 连接浏览器,桌面辅助程序不参与其中。

验证

一切都能从这个仓库复现。插件层面的门控完全不需要桌面: sh

from a DeepSeek Harness checkout, so the peer dependencies resolve

node --import tsx/esm --test tests/contracts.test.mjs tests/experience.test.mjs

helper (Rust)

cargo test --release --manifest-path helper-rs/Cargo.toml

engines (Python)

python -m pytest -q

fake-backend smoke: no desktop, no mouse

node src/smoke.mjs

Windows 11 x64 上的当前状态:插件门控 38/38(25 项契约 + 13 项体验),Rust 202 项通过,Python 289 项通过 / 1 项跳过,fake-backend 冒烟测试通过。

对等测试套件会驱动真实桌面,把这个插件和官方插件做对比——覆盖层像素、光标移动、截图新鲜度、窗口状态用例、传输预算、AX 树字节数、插件生命周期: powershell pwsh -File parity/verify-all.ps1

它要求桌面已准备好(一个 Parity Target 窗口,以及用于 AX 对比的 Word 和 Explorer),缺少测试夹具时报告 SKIP,而不是给出错误的 PASS。开发证据——逆向工程报告、差距登记表和验证日志——有意不放进公开源码树。

从源码构建 sh

JavaScript plugin: nothing to build, it is plain ESM

node src/exports-check.mjs

Rust helper: build, test, and publish the binary the plugin ships

pwsh -File scripts/ship-helper.ps1

Python engine (optional browser surface)

python -m pip install -e .

scripts/ship-helper.ps1 会运行 cargo build --release 和辅助程序测试套件,把 dsh-computer-use.exe 复制到 helper-rs/bin/<platform>-<arch>/,并打印它的 SHA-256。全新检出的仓库没有 Rust 工具链也能运行,因为这个二进制文件已被跟踪。

想基于检出的仓库而不是已安装的副本做开发: sh
dsh plugin --profile web add /path/to/dsh-computer-use_codex-style

仓库结构 text package.json the DSH bundle manifest (dsh.bundle.patch + dsh.skills) cordis.patch.yml the HOST-plane layer this bundle inserts dsh-plugin.json the Codex-style plugin manifest (identity, interface, tool lists) src/ index.js HOST service: sidecar lifetime, turn lifecycle, health tool.js PRESET row: tool registration, approvals, documentation gate sidecar.js helper transport: spawn, JSON-RPC, budgets, routing experience.js the experience layer: store, digest, observations, pending prompt.js always-on prompt section + on-demand reference inventory paths.js helper/python discovery skills/ computer-use/ the desktop skill + its reference documents computer-use-browser/ 浏览器技能及其参考文档 helper-rs/ Rust 助手(输入、UIA、捕获、覆盖层、光标) bin/<platform>-<arch>/ 随发布附带的二进制文件 helper-swift/ macOS 助手源码(不作为二进制文件发布) computer_use/ Python 引擎(CDP、Playwright、浏览器目录) parity/ 验证套件及其测试夹具 tests/ 插件与引擎测试 docs/ 插件 readme 与资源

故障排查

| 现象 | 含义 |
| Computer Use 工具不在函数列表中 | 会话没有使用挂载 dsh-computer-use/tool 的预设,或者安装 bundle 后没有重启配置档。 |
| The Windows Computer Use helper may have failed | 助手没有在 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 亲和性会让 DWM 在某些 Windows/DWM/GPU 组合下不把胶囊的合成内容呈现在屏幕上*(此时操作者只看到合成光标、看不到胶囊,而所有覆盖层 API 仍报告 visible=true);这就是它需要显式开启的原因。卡住的 mask 会表现为 overlay.captureMasked = true,助手会在五秒后自行解除。 |
| list_apps 超时 | 已安装应用目录是唯一一个在应答前要做实际工作的方法。computer_use_health → overlay/appCatalog 的耗时,以及助手自己的 %LOCALAPPDATA%\computer-use-app-catalog\slow-requests.log(记录每个超过 DSH_CU_SLOW_REQUEST_MS 的请求,默认 1 s,含目录与重建阶段耗时)是仅存的两份记录:传输超时会杀掉助手,等你能查询时它进程内的诊断信息已经没了。如果这台机器上目录确实很慢,调大 listAppsTimeoutMs |
| 未按 Esc 却出现 Computer Use was stopped by the user with the physical Escape key | 工具调用被 harness 中止(自身预算耗尽),helper 就把这一轮标记为已停止。现在中止会发送 cancel,它只负责移除覆盖层;如果你仍然看到这条提示,说明 helper 来自旧版本(下一轮会启动新的 helper) |
| 某个应用的无障碍树不可用 | 自绘 UI 常见这种情况。改用截图路径,或者优先使用应用自带的脚本接口,然后用 computer_use_experience 记录你得到的结论。 |

安全与隐私

- 智能体操控真实的鼠标、键盘和屏幕。 请在可以接受这一点的会话里运行 Computer Use,并保持拒绝列表完整。
- 审批是显式的。 launch_app 和录音可能暂停,等待 harness 的审批界面;不会有任何操作被静默批准,被拒绝的操作也绝不会重试。
- 经验存储是本地且有界的。 它位于插件文件夹内,被 gitignore 忽略,从不打包,也从不记录输入的文本、元素名称或截图字节。
- 截图是视觉部分。 它们以图片附件的形式传给模型;JSON 工具结果里不携带 base64。
- 不可信内容始终不可信。 页面、文档和邮件可以给模型提供信息,但不能授权任何操作。

兼容性与已知缺口

插件对标 Codex Computer Use 插件的基线 26.903.61454:同样的 13 个方法、同样的参数名与默认值、同样的返回结构、同样的错误字符串、同样的 AX 树语法、同样的预算、同样的覆盖层语义。

官方 DSH Computer Use 的设计明显不同。想要 Codex 风格的行为时,就用这个插件。

许可证与署名

MIT —— 见 LICENSE。

这是为 DeepSeek Harness 做的独立重实现。它不隶属于 OpenAI,也未获得 OpenAI 的认可或赞助。Codex 是 OpenAI 的商标;这里提到它只是为了描述行为兼容性。

本仓库包含逐字复制的第三方材料,这些材料保留各自的条款:

- helper-rs/assets/prompts/ 和技能 references/ 目录收录了官方 Computer Use 指南、API 参考和确认策略文档,原样复制是为了让模型读到的文字与官方插件一致。
- parity/golden-ax/ 和 parity/ax-rich/ 收录了官方 helper 生成的无障碍树样本,作为一致性门禁的对比基线。

如果你要再分发这个项目,请对照你获取这些文件时适用的条款逐一审查。
预览分享卡片长什么样 ↓wushi2333/dsh-computer-use_codex-style
分享 · DeepSeek Harness Hub
wushi2333/dsh-computer-use_codex-style

在 DeepSeek Harness 里操作 Windows 桌面应用和 Chromium 标签页。 基于 Codex…

这是你的仓库?认领条目

回到顶部