Bundle
dsh-desktop-operator
DSH Desktop Operator: safe Windows Computer Use, desktop automation, UI Automation, and MCP tools for DeepSeek Harness
- Source
- zjh02249
- stars
- 1 stars
- License
- MIT
- Updated
- Updated 13 days ago
Readme
# DSH Desktop Operator
> 🌐 **语言切换 / Language:** **简体中文** | [English](README.en.md)
[](https://github.com/zjh02249/dsh-desktop-operator/releases/latest)
[](#系统兼容性)
[](LICENSE)
`dsh-desktop-operator` 是一个面向 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) / DSH 的 Windows Computer Use、桌面自动化和 MCP 插件。它把经过适配的 Open Computer Use 原生运行时、DSH 桥接层、许可证和 Windows x64/arm64 二进制打进**一个插件包**,安装后不再依赖第二个项目或相邻源码目录。
项目目标不是简单模拟鼠标键盘,而是逐步复刻 Codex Computer Use 的关键工程能力:精确选择窗口、观察界面、优先使用无障碍元素、执行动作、验证结果、处理模态窗口、在敏感动作前确认,并让用户清楚看到电脑正在被控制。
核心插件不包含面向某个具体桌面程序的操作分支、控件 ID 或联系人。真实应用名称只作为可替换的质量矩阵数据和兼容性证据;消息流程验收器由调用方显式传入应用、窗口与控件选择器。
> 当前开发版本:`0.12.1`;公开发布状态以 [Releases](https://github.com/zjh02249/dsh-desktop-operator/releases) 为准。项目 Windows-first,可供开发者试用。已在 Windows 10 x64 与 DeepSeek Harness `0.3.5` / DSH `0.1.0-rc.6` 上完成真实桌面验证;尚不应视为跨系统、跨应用都达到生产级稳定性的最终版本。
### 项目关系与归属
这是 [valkia/dsh-plugin-computer-use](https://github.com/valkia/dsh-plugin-computer-use) 的**独立维护增强衍生版**。原插件实现来自 DeepSeek Harness 相关工作;本仓库保留原始 MIT 许可证与 `Copyright (c) 2026 DeepSeek` 声明,并正式合并、持续改造了来自 [iFurySt/open-codex-computer-use](https://github.com/iFurySt/open-codex-computer-use) 的 Windows runtime。本仓库不是 DeepSeek 官方发行版。
当前产品使用独立的软件包 ID `dsh-desktop-operator`,不再使用原仓库的 `@valkia/dsh-plugin-computer-use` 标识。旧 ID 只会出现在来源说明和迁移命令中,不表示本仓库拥有或代表 GitHub 用户 `valkia`。
## 快速安装
### 1. 下载插件包
从本仓库的 [Releases](https://github.com/zjh02249/dsh-desktop-operator/releases) 下载最新的:
```text
dsh-desktop-operator-<版本号>.tgz
```
例如 `0.12.1` 对应:
```text
dsh-desktop-operator-0.12.1.tgz
```
如果你刚从源码构建,安装包位于:
```text
artifacts/package/dsh-desktop-operator-0.12.1.tgz
```
### 2. 安装到 DSH Web Profile
```powershell
dsh plugin --profile web add "D:\Downloads\dsh-desktop-operator-0.12.1.tgz"
```
如果终端找不到 `dsh`,使用 DeepSeek Harness 自带的 DSH CLI:
```powershell
$DshCli = "$env:USERPROFILE\.dsh\profiles\node_modules\@deepseek-ai\dsh\lib\bin.js"
node $DshCli plugin --profile web add "D:\Downloads\dsh-desktop-operator-0.12.1.tgz"
```
### 3. 挂载到 Agent Preset
**只安装插件包不会自动把 Computer Use 工具暴露给模型。** 还必须在需要桌面控制能力的 Agent Preset 中加入:
```yaml
- id: computer-use
name: 'dsh-desktop-operator'
config:
accessPolicy: allow
highRiskActionPolicy: confirm
interactionMode: foreground-verified
allowAppLaunch: false
visualIndicator: true
toolCallTimeoutMs: 120000
```
本机 Agent Preset 通常位于:
```text
%USERPROFILE%\.dsh\.agent-presets\<preset-name>\agent.cordis.yml
```
推荐以上配置的原因:当前部分 DeepSeek Harness 环境的全局 approval policy 是 `never`,此时 `accessPolicy: per-call` 会被直接拒绝;`accessPolicy: allow` 允许普通桌面动作运行,而 `highRiskActionPolicy: confirm` 仍会在发送、删除、购买、上传、安装等最终动作前调用 DSH 原生确认界面。
### 4. 重启并新建会话
重启 DeepSeek Harness/对应 Profile,然后使用刚才配置的 Agent Preset **新建会话**。旧会话不会自动获得新挂载的工具。
可先让模型执行一个无副作用检查:
```text
列出当前 Windows 桌面上的窗口,不要点击或输入。
```
### 5. 核验安装版本
```powershell
$PluginRoot = "$env:USERPROFILE\.dsh\profiles\web\node_modules\dsh-desktop-operator"
(Get-Content -Raw "$PluginRoot\package.json" | ConvertFrom-Json).version
& "$PluginRoot\runtime\bin\win32-x64\open-computer-use.exe" --version
```
两处版本都应与 Release 版本一致。
### 从旧软件包迁移
如果此前安装过 `@valkia/dsh-plugin-computer-use`,先移除旧 ID,再安装新的独立软件包,并把 Agent Preset 中的 `name` 改成 `dsh-desktop-operator`:
```powershell
dsh plugin --profile web remove '@valkia/dsh-plugin-computer-use'
dsh plugin --profile web add "D:\Downloads\dsh-desktop-operator-0.12.1.tgz"
```
### 升级已有 `dsh-desktop-operator` 安装
DSH/pnpm 可能复用同名本地包缓存。升级时建议先移除旧包,再安装新的 `.tgz`:
```powershell
dsh plugin --profile web remove 'dsh-desktop-operator'
dsh plugin --profile web add "D:\Downloads\dsh-desktop-operator-0.12.1.tgz"
```
随后重启 DeepSeek Harness,并使用新会话重新验证版本。
## 系统兼容性
| 环境 | 状态 | 说明 |
|---|---|---|
| Windows 10 x64 | **已验证** | 当前开发机为 Windows 10 22H2 / Build 19045;WPF、WinForms、Qt 钉钉只读语义矩阵以及 Electron DeepSeek Harness/ZCode 矩阵已测试。 |
| Windows 11 x64 | **工作流已就绪,待合格实机** | 提供要求 `windows-11` 与 `interactive` 标签的自托管验收工作流;当前主机不是 Windows 11,不能宣称实机通过。 |
| Windows arm64 | **已构建,未实机验证** | Release 包含 `win32-arm64` 二进制,当前只完成交叉编译和包完整性检查。 |
| macOS | **未实现** | 当前没有 macOS runtime、权限适配或安装产物。 |
| Linux | **未实现** | 当前没有 X11/Wayland runtime 或安装产物。 |
| 锁屏、UAC 安全桌面 | **不支持** | Windows 安全边界内的桌面无法由普通用户进程控制。 |
| 远程桌面断开状态 | **不保证** | 依赖有效的交互式桌面 Session。 |
### DeepSeek Harness 与开发环境
| 项目 | 要求/验证范围 |
|---|---|
| DeepSeek Harness | 已验证 `0.3.5` |
| DSH | 已验证 `0.1.0-rc.6`;DSH 仍是预发布 API,后续升级可能需要适配 |
| Node.js | `^22.19.0` 或 `>=24.0.0` |
| pnpm | `11.7.0` |
| Go | 构建 runtime 需要 `1.22+` |
| Windows SDK | 当前构建验证使用 `10.0.26100.0` |
### 应用兼容性
| 应用/框架 | 当前状态 |
|---|---|
| 标准 WPF 控件 | **已验证**:窗口观察、焦点、`set_value`、点击、组合后置条件、WGC 截图 |
| 标准 WinForms 控件 | **已验证**:owner/modal 识别、切换阻断对话框、`window_closed` |
| 钉钉 Windows 客户端(Qt 验收样本) | **部分验证**:窗口解析、激活、WGC 截图、语义搜索框/消息框/发送控件查询可用;完整草稿准备/恢复与发送前确认仍待无副作用实机闭环 |
| Electron | **本机矩阵通过**:DeepSeek Harness 与 ZCode 的窗口观察、WGC 捕获和语义元素检索通过 |
| Office/WPS | **矩阵已定义,当前主机无可用应用**:不宣称实机通过 |
| WinUI / UWP / 自绘控件 | **未形成完整系统性矩阵** |
| 游戏、DirectX、自绘画布 | **不保证**:可能只能使用截图坐标,缺少可靠语义元素 |
| 浏览器网页 | 可控制浏览器窗口,但本项目不是浏览器专用 DOM 自动化工具 |
## 已实现功能
### 单包安装与运行时
- 一个 `.tgz` 同时包含 DSH 插件、运行时源码、Windows x64/arm64 二进制、许可证和第三方声明。
- 安装后不依赖独立的 `open-computer-use-dsh` 项目。
- 自动选择当前 Windows 架构对应的内置 runtime;支持使用绝对路径覆盖进行开发调试。
- 插件、原生 runtime 和 Release 使用同一版本号。
- MCP 子进程异常退出后支持有限重连;Agent/Session 释放时终止子进程和工具注册。
### 窗口与观察
- 枚举应用和顶层窗口,使用稳定 `WindowRef`、generation、进程和窗口身份减少误操作。
- 检测 stale/ambiguous 窗口引用,拒绝对已经变化或无法唯一确认的目标继续操作。
- 以 Windows Graphics Capture(WGC)为主要窗口截图路径;窗口被其他窗口遮挡时仍可独立捕获。
- 回传物理像素尺寸、窗口原点、DPI、虚拟桌面边界和截图降级诊断。
- 检测截图后窗口移动/缩放,拒绝继续使用过期坐标。
- 识别最小化窗口并要求先恢复、重新观察。
- 暴露 UI Automation 树、元素索引、focused element 和模态窗口关系。
- 提供只读 `find_elements`,在当前观察内按可访问名称、AutomationId、值、控件类型、类名和动作检索大型 Qt/Electron/Office UIA 树。
### 桌面动作
- 激活窗口、点击、拖动、滚动、按键/组合键、文本输入、UIA `set_value` 和辅助动作。
- 前台验证模式下使用真实 Windows `SendInput`,并在需要输入前核验目标窗口和焦点。
- `set_value` 优先使用 UIA `ValuePattern`,必要时使用已验证焦点的输入回退;读回不一致不会报告成功。
- 鼠标坐标从截图像素映射到物理窗口坐标,并拒绝越界点。
- 内置负坐标、混合缩放和越界拒绝自检;真实负坐标显示器存在时,可靠性 smoke 会自动增加物理动作验收。
- 动作后可验证 `target_focused`、`target_value_equals`、`text_contains`、`foreground_window`、`screenshot_changed` 和 `window_closed`。
- 支持最多 8 个非嵌套 `all`/`any` 后置条件组合。
- 只有结果得到验证时返回 `ActionStatus: applied`;无法判断时返回 `unknown`,避免假报成功。
- DSH 为每个有副作用调用注入 `action_id` 与 `idempotency_key`;运行时把两者的哈希和脱敏动作状态同步写入每用户 JSONL 日志,跨进程重启仍拒绝重复派发,并在实时结果中返回动作 ID 和耗时。
- 崩溃后启动的新 runtime 会检查悬挂动作的原进程;仅在确认其已退出时把状态恢复为 `unknown`,要求重新观察且绝不自动重放。
- `doctor`、`action-audit` 和 `action-journal-prune` 提供状态诊断、脱敏审计与保留策略压缩;日志不保存输入文本、设置值、动作摘要或原始幂等键。
### 用户可见控制状态
- 默认显示不抢焦点、可穿透点击的顶部控制提示条。
- 橙色光环跟随真实系统鼠标位置。
- 鼠标动作使用短距离平滑移动,让用户能看到自动化正在操作。
- 每轮实际使用结束后调用 `turn-ended` 清理提示条和临时视觉状态。
### 会话占用与恢复
- 首个通过策略的 Agent turn 获得运行时租约,避免两个会话同时复用同一套元素快照。
- turn 停止、Agent 销毁或 Session 销毁时自动释放;新会话无需重启 DSH 即可继续使用。
- 并发控制请求会明确失败,不会静默把输入发给错误会话。
- MCP 工具调用支持标准取消通知;轮次停止时会取消排队调用,并终止仍在执行的 PowerShell 动作进程。
- 同一 runtime 内的工具调用严格串行;多个 runtime 进程通过 Windows 命名互斥锁共享唯一前台输入通道。
- 检测被 owned modal 禁用的 owner window,并返回 `modal_window_required` 和候选窗口。
### 高风险动作确认
- 所有有副作用工具都要求准确的 `action_intent.kind` 与用户可读摘要。
- `send`、`submit`、`publish`、`delete`、`purchase`、`approve`、`upload`、`change_access`、`expose_sensitive_data` 和 `install` 被视为高风险最终动作。
- 默认 `highRiskActionPolicy: confirm` 会通过 DSH 原生问题界面在最终动作前确认。
- 可配置为全部拒绝或明确允许。
- 对语义明显的发送、删除、支付等控件进行基础反降级检查,避免把高风险动作伪装成普通点击。
## 部分实现、仍需增强
- 负坐标物理显示器和 100%/125%/150%/200% 混合 DPI 的完整组合矩阵;当前只完成负坐标确定性自检与 125%/200% 实机拓扑。
- Windows 11、Windows arm64 真实设备上的长期回归;Windows 11 自托管交互工作流已就绪但尚未执行。
- Office/WPS、WinUI、UWP 与复杂自绘控件的实机矩阵;当前 Qt 与 Electron 样本已通过,Office 类应用在本机不可用。
- 参数化消息类应用的真实联系人搜索、中文输入、消息内容复核和“发送前确认”完整端到端验收;默认不猜测搜索结果,也不执行发送。
- 截图作为模型图片附件依赖 DSH 挂载 `ctx.attachments`,并要求所选模型路由支持图片输入。
- 审计导出、按动作查询和受控诊断包仍需增强;当前提供脱敏 JSON CLI 查看,不持久化截图或文本正文。
- 风险动作分类目前主要依赖声明、控件标签和策略,尚不是完整的语义安全引擎。
## 尚未实现
- macOS 和 Linux runtime/安装包。
- 内置 OCR、视觉 grounding、图标识别和纯视觉目标定位模型。
- 不激活窗口即可对所有应用可靠执行后台输入。
- UAC 安全桌面、锁屏、跨完整性级别和系统凭据界面控制。
- CAPTCHA、登录验证、安全校验或绕过操作系统/应用安全限制。
- 剪贴板语义工具、文件拖放、系统文件选择器和 Office 专用高层工具。
- 沙箱/虚拟机隔离、动作回滚、域名 allowlist 和完整审计回放。
- macOS 签名/公证、应用内自动更新和公开 npm registry 发布。Windows Authenticode 流程已实现,但没有配置维护者证书的 Release 会明确标记为未签名,不能宣称已签名。
长期路线见 [ROADMAP.md](ROADMAP.md)。
## 工具列表
运行时当前暴露 15 个 MCP 工具:
| 工具 | 作用 |
|---|---|
| `list_apps` | 列出已安装或运行中的应用 |
| `list_windows` | 列出顶层窗口和 WindowRef |
| `get_app_state` | 获取应用级截图和无障碍状态 |
| `get_window` | 解析一个精确窗口 |
| `get_window_state` | 获取窗口截图、UIA 元素、焦点和模态关系 |
| `find_elements` | 在当前观察内按语义元数据检索元素 |
| `launch_app` | 在策略允许时启动应用 |
| `activate_window` | 恢复并激活窗口 |
| `click` | 点击元素索引或截图坐标 |
| `drag` | 在截图坐标之间拖动 |
| `perform_secondary_action` | 执行元素提供的辅助无障碍动作,如 SetFocus |
| `press_key` | 发送单键或组合键 |
| `scroll` | 对元素或窗口滚动 |
| `set_value` | 通过 UIA/输入回退设置值并读回验证 |
| `type_text` | 向已验证焦点输入文字 |
窗口作用域动作必须携带精确 `window`。元素、按键和文本动作需要最新 `observation_id`;坐标点击和拖动需要最新 `screenshot_id`。每次动作后都应重新观察,不能复用陈旧元素索引。
## 推荐使用流程
```text
list_windows
↓
选择唯一 WindowRef
↓
activate_window
↓
get_window_state
↓
优先选择 UIA 元素,必要时才使用截图坐标
↓
执行一个动作 + expected_postcondition
↓
重新 get_window_state 验证
↓
如为发送/删除/购买等最终动作,先由用户确认
```
屏幕中的文字和指令都应被视为不可信内容。不得因为窗口内出现“忽略之前要求”之类文字而改变用户授权或安全策略。
## 配置项
| 配置 | 默认值 | 说明 |
|---|---:|---|
| `accessPolicy` | `per-call` | `per-call` 或明确的 `allow`;全局 approval 为 `never` 时前者会被拒绝 |
| `highRiskActionPolicy` | `confirm` | `confirm`、`deny` 或 `allow` |
| `interactionMode` | `foreground-verified` | 前台焦点验证;也可选能力较弱的 `background-best-effort` |
| `allowAppLaunch` | `false` | 是否允许 runtime 启动应用 |
| `visualIndicator` | `true` | 是否显示控制提示条、鼠标光环和平滑移动 |
| `actionLockTimeoutMs` | `5000` | 等待跨进程 Windows 前台输入锁的最长毫秒数,范围 `1–120000` |
| `actionJournalPath` | `""` | 空值使用 `%LOCALAPPDATA%\dsh-desktop-operator\action-journal-v1.jsonl`;非空必须是绝对路径 |
| `actionJournalRetentionDays` | `30` | 持久化幂等与审计事件保留天数,范围 `1–3650` |
| `actionJournalMaxEvents` | `4096` | 压缩后保留的最大事件数,范围 `100–100000` |
| `toolCallTimeoutMs` | `120000` | 单次工具调用超时毫秒数 |
| `failOnStartupError` | `true` | runtime 启动或工具发现失败时是否拒绝激活 |
| `reconnect.enabled` | `true` | 意外断开后是否重连 |
| `reconnect.initialDelayMs` | `500` | 首次重连延迟 |
| `reconnect.maxDelayMs` | `30000` | 重连退避上限 |
| `reconnect.maxAttempts` | `10` | 连续重连上限 |
| `runtimeExecutable` | `""` | 空值使用包内 runtime;非空必须是开发用绝对路径 |
| `env` | `{}` | 显式传入 runtime 的环境变量 |
| `cwd` | `""` | runtime 工作目录 |
| `cleanupOnTurnEnd` | `true` | 轮次结束后清理视觉状态 |
| `cleanupTimeoutMs` | `5000` | 清理通知器超时 |
| `cleanupGraceMs` | `1000` | 终止通知器进程树的宽限时间 |
## 从源码构建
### 前置条件
- Windows PowerShell 5.1 或 PowerShell 7
- Node.js `^22.19.0` 或 `>=24`
- pnpm `11.7.0`
- Go `1.22+`
- Windows SDK 与可用的 C# 编译工具链
### 一键构建、测试和打包
```powershell
pnpm install --frozen-lockfile
pnpm package:plugin
```
`package:plugin` 会依次:
1. 测试 vendored runtime 并执行 `go vet`;
2. 构建 Windows x64 与 arm64 原生 runtime;
3. 使用配置的 Authenticode 证书签名并验证二进制;未配置证书时生成明确的未签名报告;
4. 生成 CycloneDX 1.6 SBOM;
5. 运行插件 Node 测试并生成 `.tgz`;
6. 解包检查 runtime、源码、许可证和必要工具;
7. 启动打包后的 MCP runtime,验证版本、工具列表与坐标自检。
若 Go 不在 PATH,可直接调用:
```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass `
-File .\scripts\package-plugin.ps1 `
-GoExecutable "C:\path\to\go.exe"
```
### Windows 签名与供应链配置
发布工作流支持两种 Authenticode 证书来源:`WINDOWS_SIGNING_PFX_BASE64` + `WINDOWS_SIGNING_PFX_PASSWORD`,或已安装证书的 `WINDOWS_SIGNING_CERT_THUMBPRINT`。把仓库变量 `WINDOWS_SIGNING_REQUIRED` 设为 `true` 后,缺少证书、签名失败、时间戳失败或验签失败都会阻断 Release。
未配置证书时,构建仍会生成开发者可测试的包,但 `windows-signing-report.json` 会明确记录 `unsigned`。这不等同于签名发布。SBOM、签名状态和升级/回滚报告位于 `artifacts/security/`;GitHub Release 还会附加官方 artifact attestation。
## 测试与验收范围
自动化测试覆盖插件配置、runtime 选择、环境变量清理、工具同步、审批策略、高风险确认、租约释放、断线重连、轮次清理和包完整性。Windows runtime 还提供真实窗口 smoke 脚本:
```text
runtime/windows/scripts/run-windows-window-smoke.ps1
runtime/windows/scripts/run-windows-capture-smoke.ps1
runtime/windows/scripts/run-windows-action-smoke.ps1
runtime/windows/scripts/run-windows-modal-smoke.ps1
runtime/windows/scripts/run-windows-reliability-smoke.ps1
```
完整可靠性入口会采集当前显示器数量、负坐标和 DPI,并顺序运行遮挡捕获、模态恢复和动作闭环;可用 `-DisplayOnly` 仅检查显示拓扑、用 `-ActionIterations 100` 做压力测试,也可通过 `-RealApp`/`-RealAppTitle` 加入只观察、不发送的真实应用窗口验收:
```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass `
-File .\runtime\windows\scripts\run-windows-reliability-smoke.ps1 `
-ActionIterations 1
```
Release 构建不会声称替代真实应用验收。涉及发送消息、删除数据、购买、上传或权限修改时,必须在隔离测试对象上执行,并保留最终用户确认。
## 发布版本
- 版本历史见 [CHANGELOG.md](CHANGELOG.md)。
- `main` 中的 `package.json` 首次出现新版本号时,GitHub Actions 会在 Windows runner 上重新测试和打包;全部通过后自动创建对应 `v*` 标签和 Release。
- 仍可手动推送 `v*` 标签触发同一套发布流程;标签版本必须与 `package.json` 一致。
- Release 自动附带 `.tgz`、两个架构的 runtime、manifest、CycloneDX SBOM、签名状态报告、升级/回滚报告和 SHA-256 校验文件。
- GitHub Actions 为发布制品生成 build provenance 和 SBOM attestation;每次发布还在隔离 `DSH_HOME` 中验证上一版 → 当前版 → 上一版。
- 主分支的 backfill job 会为历史标签补建缺失的 GitHub Release 页面。
维护者只需提交版本号、CHANGELOG 和文档后推送 `main`:
```powershell
git push origin main
```
## 目录结构
```text
lib/ DSH 插件运行时代码与类型
runtime/windows/ 合并维护的 Windows Computer Use runtime 源码
runtime/bin/ 构建生成的 x64/arm64 二进制和 manifest
runtime/LICENSE.* 上游许可证
runtime/THIRD_PARTY_* 第三方声明和溯源
scripts/build-runtime.ps1 runtime 构建入口
scripts/package-plugin.ps1 一键测试、构建、打包和校验
scripts/generate-sbom.ps1 CycloneDX 1.6 SBOM
scripts/sign-windows-artifacts.ps1 Authenticode 签名与验签
scripts/verify-dsh-upgrade-rollback.ps1 隔离升级/回滚验收
test/ 插件测试
.github/workflows/ CI 与 GitHub Releases 自动化
ROADMAP.md 长期 Codex 能力对齐路线
CHANGELOG.md 版本历史
```
## 安全边界
本插件控制的是用户真实桌面,不是沙箱。它不会绕过操作系统权限,也不能保证所有第三方应用的自绘控件都可观察。请默认保持:
- `allowAppLaunch: false`;
- `highRiskActionPolicy: confirm`;
- `visualIndicator: true`;
- 对最终发送、删除、购买、授权、上传和安装动作逐次确认;
- 对 `ActionStatus: unknown` 重新观察,绝不盲目重试有副作用的动作。
## 上游与许可证
本项目的 Windows runtime 基于 [iFurySt/open-codex-computer-use](https://github.com/iFurySt/open-codex-computer-use) 进行合并、适配和持续维护。上游代码许可证与第三方声明保留在 `runtime/` 中。
本仓库整体使用 [MIT License](LICENSE)。使用和再发布时必须保留相应版权、许可证与第三方声明。
Install
dsh plugin --profile web add github:zjh02249/dsh-desktop-operator
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-desktop-operator from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.