dsh-plugin-offline-updater 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +141 -3
- package/client.js +842 -0
- package/cordis.patch.yml +5 -0
- package/icon.svg +12 -0
- package/index.js +629 -0
- package/lib/install.js +274 -0
- package/lib/registry.js +167 -0
- package/lib/release-age.js +227 -0
- package/lib/settings.js +138 -0
- package/locale/en.json +10 -0
- package/locale/zh.json +10 -0
- package/package.json +50 -6
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-plugin-offline-updater contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,141 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# 插件离线更新器(dsh-plugin-offline-updater)
|
|
2
|
+
|
|
3
|
+
DeepSeek Harness(DSH)的 Cordis 插件,用于在 Web GUI 中管理当前 profile 已安装用户插件的版本更新。
|
|
4
|
+
|
|
5
|
+
它会在侧栏增加一个「插件离线更新」入口,列出所有已安装的用户插件,逐个向 npm 源查询最新版本并与本地版本比较;有新版本时可直接更新,并遵守「新版本 24 小时发布年龄」限制。
|
|
6
|
+
|
|
7
|
+
## 功能
|
|
8
|
+
|
|
9
|
+
- **插件列表**:读取当前 DSH profile 中已安装的用户插件(`availability === 'profile'`),展示图标、名称、版本与描述,自动排除本插件自身;读取 bundle 清单失败时回退到 profile `package.json` + `node_modules/<pkg>/package.json`。
|
|
10
|
+
- **检查更新**:按插件调用 npm registry(含 scoped 包与私有源),比较本地版本与 `dist-tags.latest`,显示「已是最新版本 / 发现新版本 / 检查失败」。
|
|
11
|
+
- **24 小时新版本限制**:按**目标版本自身的发布时间**判定,不足 24 小时(或发布时间未知)时弹窗确认;确认后该版本记入「已确认」,30 天内不再重复弹窗。
|
|
12
|
+
- **稳妥版本**:存在「已满 24 小时、高于当前版本且不高于 `latest`、非预发布」的版本时,确认弹窗额外提供「更新到稳妥版本」,一键安装该版本。
|
|
13
|
+
- **两种更新模式**:默认原位 `pnpm add` 升级;可在设置中开启「更新前先卸载旧插件」,改为 `pnpm remove` + `pnpm add`,与官方插件市场行为一致(安装失败会尽力回滚到原版本)。
|
|
14
|
+
- **发布年龄白名单维护**:以 `--config.minimumReleaseAge=0` 放行的过新版本,安装成功后会写入 profile `pnpm-workspace.yaml` 的 `minimumReleaseAgeExclude`,避免之后所有插件(含官方市场)安装被 `ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION` 拦下。
|
|
15
|
+
- **列表分页**:客户端分页,默认每页 10 条;刷新按钮会重新拉取列表并对当前页插件静默检查一次,不会自动更新。
|
|
16
|
+
- **跟随 DSH 的 registry 语义**:读 `pluginManager.registries()`(等价于 profile 的 `pnpm config get registry`),私有/未知源只问它自己,绝不回退到公网镜像;查询与安装都通过 profile 自带的 pnpm 执行,自动继承 `.npmrc` 的认证、代理与 CA。
|
|
17
|
+
|
|
18
|
+
## 环境要求
|
|
19
|
+
|
|
20
|
+
- DSH 运行环境(`dsh web` 或 Electron `ELECTRON_RUN_AS_NODE`),Node.js ≥ 20(仅用于 ESM 与内置模块;Host 端不再使用全局 `fetch`)。
|
|
21
|
+
- profile 内自带 pnpm(检查与更新都通过 profile 的 pnpm 执行;没有可用 pnpm 的环境无法检查或更新)。
|
|
22
|
+
- 仅适用于 **registry(npm)来源**的 profile 依赖;`link:`、`file:`、`portal:`、`workspace:`、`git:`、`https:`、tarball 来源的插件不支持自动更新。
|
|
23
|
+
- 纯 ESM,无构建步骤、无 TypeScript、无打包器、无第三方运行时依赖。
|
|
24
|
+
|
|
25
|
+
## 安装
|
|
26
|
+
|
|
27
|
+
推荐用 Harness 的 `plugin_manager` 工具安装本地目录(以 link 方式,改动立即生效,便于开发):
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
plugin_manager(action: "install_bundle", target: "<本目录绝对路径>")
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
> 本包**尚未发布到 npm**,因此 `pnpm add dsh-plugin-offline-updater` 目前无法安装。需要从 npm 安装时请先按文末「发布到 npm」首次发布。
|
|
34
|
+
|
|
35
|
+
安装后侧栏会出现「插件离线更新」入口(可在「设置 → 插件 → 插件离线更新器」中关闭)。更新任意插件后需要**重启 DSH** 才会加载新版本代码;只改本插件自身的前端代码时刷新页面即可。
|
|
36
|
+
|
|
37
|
+
## 使用
|
|
38
|
+
|
|
39
|
+
1. 打开侧栏「插件离线更新」,页面列出当前 profile 的已安装用户插件(每页 10 条)。
|
|
40
|
+
2. 点击某行的「检查更新」,插件会查询 npm 源并给出结果;也可点右上角刷新按钮重新拉列表并对当前页做一次静默检查(只展示状态,不会自动更新)。
|
|
41
|
+
3. 有新版本且发布时间已满 24 小时:直接更新。
|
|
42
|
+
4. 新版本不足 24 小时:弹窗提示,可选择
|
|
43
|
+
- 「继续更新」:忽略该版本的 24 小时限制(记入已确认);
|
|
44
|
+
- 「更新到稳妥版本」:安装最近一个已满 24 小时的版本(无需确认,且不会记为已确认);
|
|
45
|
+
- 「取消」:不做任何操作。
|
|
46
|
+
弹窗可用 `Esc` 或点击遮罩关闭。
|
|
47
|
+
5. 更新完成后提示「已下载 vX.Y.Z,重启 DSH 后生效」。
|
|
48
|
+
|
|
49
|
+
## 设置
|
|
50
|
+
|
|
51
|
+
设置入口位于「设置 → 插件 → 插件离线更新器」的 bundle 详情页,共三个开关:
|
|
52
|
+
|
|
53
|
+
| 设置 | 默认 | 说明 |
|
|
54
|
+
| --- | --- | --- |
|
|
55
|
+
| 侧栏入口 | 开 | 是否在侧栏显示「插件离线更新」入口,切换时实时挂载/卸载页面。 |
|
|
56
|
+
| 忽略新版本 24 小时限制 | 关 | 开启后过新版本直接更新、不再弹窗,对**所有插件**全局生效。 |
|
|
57
|
+
| 更新前先卸载旧插件 | 关 | 关闭为原位升级;开启后先 `pnpm remove` 再 `pnpm add`,模拟官方插件市场。`removable === false` 的插件在此模式下拒绝更新。 |
|
|
58
|
+
|
|
59
|
+
设置与「已确认版本」持久化在 `~/.dsh/plugin-offline-updater/settings.json`(`DSH_HOME` 存在时以其为准)。
|
|
60
|
+
|
|
61
|
+
## HTTP API
|
|
62
|
+
|
|
63
|
+
Host 半注册以下同源精确路由,前缀固定为 `/api/dsh-plugin-offline-updater`:
|
|
64
|
+
|
|
65
|
+
| 方法 | 路径 | 说明 |
|
|
66
|
+
| --- | --- | --- |
|
|
67
|
+
| `GET`/`HEAD` | `/settings` | 返回 `{ ok, sidebarEntry, ignoreReleaseAge, uninstallBeforeUpdate }` |
|
|
68
|
+
| `POST` | `/settings` | 接受 `{ sidebarEntry?, ignoreReleaseAge?, uninstallBeforeUpdate? }` 或 `{ key, value }` |
|
|
69
|
+
| `GET`/`HEAD` | `/plugins` | 返回 `{ ok, plugins }`,每项含 `name`、`version`、`title`、`description`、可选 `icon`(`data:image/...`)、`removable` |
|
|
70
|
+
| `POST` | `/check` | body `{ name }`,查询 npm 最新版本并计算是否需要确认 |
|
|
71
|
+
| `POST` | `/update` | body `{ name, version?, force? }`,执行更新 |
|
|
72
|
+
|
|
73
|
+
`/check` 返回 `ok`、`name`、`currentVersion`、`latestVersion`、`publishedAt`、`ageHours`、`tooFresh`、`releaseAgeHours`、`updateAvailable`、`safeVersion`、`safePublishedAt`、`safeAgeHours`、`ignoreReleaseAge`、`acknowledged`、`needsConfirm`、`registry`;拿不到 registry 数据时返回 `502 { ok: false, error }`。
|
|
74
|
+
|
|
75
|
+
`/update` 仅允许更新已安装且为 registry 来源的插件,且禁止更新自身;`version` 必须为合法 semver 且能在源中找到。门槛不满足且未 `force`、未确认时返回 `409 { needsConfirm: true, safeVersion, ... }`;已有更新在跑时也返回 `409`;未安装返回 `404`;pnpm 失败返回 `502`(错误经脱敏)。成功时返回 `{ ok, name, installedVersion, restartRequired: true, updateMode: 'in-place' | 'reinstall', registry, application: 'restart-required' }`。同一时间只允许一个更新正在执行。
|
|
76
|
+
|
|
77
|
+
写接口(`POST /settings`、`/check`、`/update`)仅放行本机回环请求:缺失 `Host`/`Origin` 时视为非页面请求而放行(Desktop 代理可能剥离它们),存在时必须为回环且同源,`sec-fetch-site: cross-site` 一律拒绝。
|
|
78
|
+
|
|
79
|
+
## 目录结构
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
.
|
|
83
|
+
├─ package.json # 包清单 + dsh.bundle / dsh.client 声明
|
|
84
|
+
├─ cordis.patch.yml # 插入的 Loader 行(id: plugin-offline-updater)
|
|
85
|
+
├─ index.js # Host 半:HTTP API、插件列表、检查/更新编排
|
|
86
|
+
├─ client.js # Client 半:侧栏图标、插件列表页、设置卡、确认弹窗
|
|
87
|
+
├─ lib/
|
|
88
|
+
│ ├─ settings.js # 设置与「已确认版本」持久化
|
|
89
|
+
│ ├─ registry.js # registry 选择(DSH registryPlan 语义)+ pnpm view 结果解析 + semver 比较
|
|
90
|
+
│ ├─ install.js # profile 目录 / pnpm 运行时解析、pnpm view 查询、pnpm add / remove+add
|
|
91
|
+
│ └─ release-age.js # minimumReleaseAgeExclude 白名单维护(guard 校验 + record 合并写盘)
|
|
92
|
+
├─ locale/
|
|
93
|
+
│ ├─ en.json # 插件元信息(meta.title / meta.description)
|
|
94
|
+
│ └─ zh.json
|
|
95
|
+
├─ icon.svg # 插件图标(package.json 导出 ./icon)
|
|
96
|
+
├─ LICENSE # MIT
|
|
97
|
+
└─ .gitignore
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## 开发与验证
|
|
101
|
+
|
|
102
|
+
改完代码后至少跑一遍语法检查:
|
|
103
|
+
|
|
104
|
+
```powershell
|
|
105
|
+
node --check index.js
|
|
106
|
+
node --check client.js
|
|
107
|
+
node --check lib/settings.js
|
|
108
|
+
node --check lib/registry.js
|
|
109
|
+
node --check lib/install.js
|
|
110
|
+
node --check lib/release-age.js
|
|
111
|
+
node -e "JSON.parse(require('fs').readFileSync('package.json','utf8'))"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
接口冒烟(端口以运行上下文给出的 GUI URL 为准):
|
|
115
|
+
|
|
116
|
+
```powershell
|
|
117
|
+
$b = 'http://127.0.0.1:<port>/api/dsh-plugin-offline-updater'
|
|
118
|
+
Invoke-RestMethod "$b/settings"
|
|
119
|
+
Invoke-RestMethod "$b/plugins"
|
|
120
|
+
Invoke-RestMethod "$b/check" -Method Post -ContentType 'application/json' -Body (@{ name = 'dshmarket' } | ConvertTo-Json)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
生效方式:Host 端(`index.js`、`lib/*.js`)改动需要**重启 DSH**;只改 `client.js`(含样式)时刷新页面即可。
|
|
124
|
+
|
|
125
|
+
## 发布到 npm
|
|
126
|
+
|
|
127
|
+
本仓库的 `publishConfig.registry` 固定为 `https://registry.npmjs.org`(避免被本机 npmmirror 镜像配置带偏)。发布步骤:
|
|
128
|
+
|
|
129
|
+
```powershell
|
|
130
|
+
npm login # 首次发布前登录 npmjs 账号
|
|
131
|
+
npm pack --dry-run # 检查将打进 tarball 的文件
|
|
132
|
+
npm publish # 发布(publishConfig 已声明 public)
|
|
133
|
+
npm view dsh-plugin-offline-updater version # 校验发布结果
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## 已知限制
|
|
137
|
+
|
|
138
|
+
- 只处理 registry(npm)来源的 profile 依赖。
|
|
139
|
+
- 更新已安装插件后必须重启 DSH 才加载新版本代码。
|
|
140
|
+
- 本插件不会把自己列进插件列表,也不能通过自身更新(`/update` 对自身返回 400);npm 上尚无同名包,对自身检查更新会得到「无法获取最新版本」。
|
|
141
|
+
- 检查与更新完全依赖 profile 的 pnpm;无法执行 pnpm 的环境无法使用本插件。
|