Skip to content
dsh.fish
Bundle

dsh-safe-install

装插件全流程自动化:四重安全检查(版本/patch/工具名/供应链)+ 自动安装 + 自动重启 DSH | Safe one-shot DSH plugin installs: four checks + auto install + auto restart

Source
goodaiaiai
License
MIT
Updated
Updated 7 days ago

Readme

# dsh-safe-install

> **DSH 插件安全安装全流程自动化**:四重安全检查 → 自动安装 → 自动重启。
> Safe, one-shot installation of DeepSeek Harness plugins: verify → install → restart.

> 🌐 **English docs**: [README.en.md](./README.en.md)

![version](https://img.shields.io/badge/version-0.1.0-blue) ![license](https://img.shields.io/badge/license-MIT-green) ![dsh](https://img.shields.io/badge/DSH-0.1.0--rc.8-orange) ![tests](https://img.shields.io/badge/tests-33%20unit%20%2B%204%20integration%20passing-brightgreen)

装插件有风险(dsh-mask 重复加载器崩溃、工具名冲突、版本不匹配),且装完要手动重启 DSH。本插件把「装插件」变成一句话:
**安检通过 → 打快照 → 安装 → 自动重启 → 新插件生效**,全程无需手动操作。

---

## 功能特性 (Features)

- 🔍 **四重安全检查**(安装前):版本兼容 / patch 冲突 / 工具名冲突 / 供应链
- ⛔ **阻断机制**:任一检查为 `block` 即拒绝安装并说明原因;`warn` 不阻断但提示风险
- 📸 **安装前自动打快照**(集成 dsh-undo-savepoint,可随时回退)
- 🔄 **安装后自动重启 DSH**(Node detached spawn,原进程释放端口后自动拉起)
- 📋 **状态追踪**:最近检查/安装/重启记录,重启后仍可查询
- 👁 **变更检测**:轮询 profile `package.json` bundles,感知外部安装/卸载

## 工作流程 (Flow)

```
用户说"装 XX 插件"
  │
  ├─ ① 四重安全检查
  │     ├─ 版本兼容   peer 要求的 @deepseek-ai/* (minor,patch,rc) ≤ 当前 DSH
  │     ├─ patch 冲突  cordis.patch.yml insert id 不与核心/已装插件重复
  │     ├─ 工具名冲突  注册工具名不与已装插件/内置工具重复
  │     └─ 供应链     npm 已发布 + 维护活跃(<30天) + license 清晰
  │        └─ 有 block? → 拒绝安装,返回报告
  │
  ├─ ② 打快照(undo CLI,失败不阻断)
  ├─ ③ dsh plugin --profile web add <pkg>
  │     └─ 失败 → 返回错误
  ├─ ④ 验证入列(读 profile package.json bundles)
  ├─ ⑤ 自动重启(restart=true 时)
  │     ├─ spawn 独立辅助进程(detached + unref)
  │     ├─ 原进程延迟退出(留时间 flush 工具结果)
  │     └─ 辅助进程等端口释放后拉起新 DSH
  └─ ⑥ 返回报告:检查结果 + 安装结果 + 重启状态
```

## 注册工具 (Tools)

| 工具名 | 功能 | 参数 |
|---|---|---|
| `safe_install_check` | 只做四重安全检查,返回通过/警告/阻断报告 | `{ pkg, source? }` |
| `safe_install` | 检查 → 通过则安装 → (可选)自动重启 | `{ pkg, source?, restart? }` |
| `safe_install_status` | 查询上次检查/安装/重启状态与历史 | `{}` |

- `pkg` — npm 包名,如 `dsh-startup-guard`
- `source` — GitHub 源(推荐,提供后 patch/工具名检查才完整),如 `github:lire1131/dsh-undo-savepoint#master`

## 四重安全检查 (Four Checks)

| # | 检查 | 数据源 | 判定 |
|---|---|---|---|
| ① | **版本兼容**:插件 `peerDependencies` 中 `@deepseek-ai/*` 的要求 `(minor, patch, rc)` 必须 ≤ 当前 DSH(本机 `0.1.0-rc.8`) | npm registry / GitHub raw `package.json` | 超则 **block** |
| ② | **patch 冲突**:`cordis.patch.yml` 的 insert id 不得与核心保留 id(`storage` / `storage-json` / `storage-domain` 等)或已装插件重复 —— 防 `duplicate loader entry id` 崩溃 | GitHub raw `cordis.patch.yml` + 本地扫描 | 重复则 **block** |
| ③ | **工具名冲突**:注册的工具名不得与已装插件/内置工具重复 —— 防工具名冲突崩溃 | GitHub raw `lib/index.js` + 本地扫描 | 冲突则 **block** |
| ④ | **供应链**:npm 有正式发布 + 维护活跃(`pushed_at` < 30 天) + license 清晰(MIT/Apache/BSD/ISC 等) | npm registry + GitHub API | 不满足则 **warn** |

> ⚠️ 未提供 `source` 时 ②③ 无法检查,返回 **warn**(不阻断)。**建议总是提供 GitHub 源**以获得完整检查。

## 架构 (Architecture)

```
dsh-safe-install/
├── package.json          # 插件声明(dsh.bundle.patch)
├── cordis.patch.yml      # 挂载条目(insert id: safe-install,唯一)
├── lib/
│   ├── index.js          # 入口:注册 3 工具 + 事件监听 + 轮询
│   ├── env.js            # 环境事实(profile 路径 / rc 探测 / 已知工具名清单)
│   ├── net.js            # 网络封装(Node https + TLS 绕过 + 自动重试)
│   ├── check.js          # 四重检查汇总(并行执行)
│   ├── checkVersion.js   # ① 版本兼容
│   ├── checkPatch.js     # ② patch 冲突
│   ├── checkTools.js     # ③ 工具名冲突
│   ├── checkSupply.js    # ④ 供应链
│   ├── install.js        # 安装执行(快照 + dsh plugin add + 验证入列)
│   ├── restart.js        # 自动重启(Node detached spawn)
│   ├── detect.js         # 轮询 profile package.json bundles
│   └── state.js          # 状态记录(内存 + 磁盘)
└── tests/
    ├── run-tests.mjs     # 离线单元测试(纯函数,无需网络)
    └── integration.mjs   # 真机集成测试(真实 npm/GitHub 数据)
```

## 快速开始 (Quick Start)

### 安装

```powershell
# 从 GitHub 安装
dsh plugin --profile web add github:goodaiaiai/dsh-safe-install#master

# 或本地源码安装
dsh plugin --profile web add <本目录路径>

# 安装后重启 DSH 生效(或让 AI 用 safe_install 装,它自己会重启)
```

### 在对话中使用

```
safe_install_check { pkg: "dsh-startup-guard" }                          # 只检查
safe_install { pkg: "dsh-better-sidebar", source: "github:omdsh-dev/DSH-better-sidebar" }  # 检查+安装(默认自动重启)
safe_install_status                                                       # 查状态
```

> ⚠️ `safe_install` 默认 `restart: true`,会重启 DSH 进程(响应返回后约 2.5s 退出,辅助进程 3s 后拉起新进程)。测试完整流程前确保有恢复手段。

## 开发与测试 (Development)

```powershell
# 单元测试(离线,无需网络):覆盖 rc 判定 / patch 提取 / 工具名 / license
node tests\run-tests.mjs

# 集成测试(需要网络):对真实插件执行四重检查,验证判定
node tests\integration.mjs
```

当前测试状态:
- 单元测试 **33/33 通过**(含 rc.6/rc.8/rc.9、跨 patch `0.1.1-rc.1`、跨 minor `0.2.0-rc.3`、storage 冲突 patch、undo_* 工具名冲突、license 判定)
- 集成测试 **4/4 通过**(dsh-startup-guard 放行 / 已装插件防重复安装阻断 / dsh-better-sidebar 0.16.1 版本兼容 / dsh-plugin-notify 放行)
- 安全用例:未知供应链包 → warn 不阻断

## 兼容性 (Compatibility)

| 项 | 值 |
|---|---|
| DSH | **0.1.0-rc.8**(peer 要求 ≤ 当前 rc;跨 minor/patch 系列会被拦截) |
| profile | `web`(GUI http://127.0.0.1:3080) |
| Node | ≥ 18(使用 `node:https`、`node:child_process`) |
| 依赖 | 仅 `@deepseek-ai/cordis`、`@deepseek-ai/dsh-tools`(peer) |

> 其他 rc 版本可通过环境变量 `DSH_VERSION` / `DSH_RC` 覆盖探测结果(调试用)。

## 已知限制 (Limitations)

- ②③ 检查依赖 GitHub 源;npm 包在未下载时无法读取其 patch/源码内容
- 工具名清单为内置快照 + 启动时扫描已装插件,新装插件后需重启刷新
- `dsh plugin add` 在 workspace-write 沙箱下可能 EPERM(临时文件权限),需 danger-full-access
- 版本检查覆盖 `(minor, patch, rc)` 三元组;核心模块缺失(如 `dsh-client-ui-slots`)属运行时依赖完整性,不在本插件检查范围(建议配合 dsh-startup-guard)

## 安全说明 (Security)

- 插件运行在你的 DSH 进程中,只安装通过四重检查的插件
- 安装前自动打快照,改错了随时可回退(dsh-undo-savepoint)
- Node 访问网络内置 `NODE_TLS_REJECT_UNAUTHORIZED=0`(本机 CA 链不完整);网络请求带重试(2 次)+ 20s 超时

## 贡献 (Contributing)

1. Fork 本仓库
2. 新增/修改后运行 `node tests\run-tests.mjs` 与 `node tests\integration.mjs`
3. 提交 PR,说明改动与测试结果

## License

[MIT](./LICENSE)

Install

dsh plugin --profile web add github:goodaiaiai/dsh-safe-install#e1531fe91fdb7e43180571fa8ecf342b7cf476e4

Profile: web

Source