@dsh-plugins/dsh-llm-hub 1.5.1 → 1.5.3
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/CHANGELOG.md +88 -0
- package/README.md +34 -0
- package/package.json +4 -2
- package/scripts/prepublish-gate.mjs +105 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,94 @@
|
|
|
2
2
|
|
|
3
3
|
本项目遵循 [Semantic Versioning](https://semver.org/lang/zh-CN/)。
|
|
4
4
|
|
|
5
|
+
## [1.5.3] - 2026-09-26
|
|
6
|
+
|
|
7
|
+
### 🛂 工程纪律对齐
|
|
8
|
+
|
|
9
|
+
#### 发版脚本 + tarball 收齐
|
|
10
|
+
|
|
11
|
+
- `scripts/prepublish-gate.mjs` 列入 `package.json#files`,随 tarball 出厂(1.5.2 时漏配)。
|
|
12
|
+
- 这条本身没功能改动,单纯是「门禁脚本要在 tarball 里」的一致性修补。
|
|
13
|
+
|
|
14
|
+
#### 作者身份纠正(修 1.5.0/1.5.1/1.5.2 的提交)
|
|
15
|
+
|
|
16
|
+
**根因**:1.5.0/1.5.1/1.5.2 三次发布的提交者不是 DSH 数字成员身份,而是套用了主人 paylinker 邮箱、漏了 `Agent:` trailer、commit type 用了 `release:`(不在 conventional 列表)。违反:
|
|
17
|
+
|
|
18
|
+
- `commit_convention §1`:数字成员用自己的 D1 email,禁止套主人邮箱。
|
|
19
|
+
- `commit_convention §1.5`:本机 CLI 提交必须带 `Agent: cli:<id>` trailer。
|
|
20
|
+
- `commit_convention §2`:commit type 必须是 `feat / fix / refactor / chore / docs / style / test / ci / perf`。
|
|
21
|
+
- `external-cli-layering`:GitHub 操作应该走 L1 `gh` CLI 而不是 L3 `curl`。
|
|
22
|
+
|
|
23
|
+
**为什么 1.5.0/1.5.1/1.5.2 不改**:tag 已发布、npm tarball 不可变、GH Release body 已建,回滚会
|
|
24
|
+
让那一批点升级的用户装不到。本版只**纠正未来**:
|
|
25
|
+
|
|
26
|
+
- 1.5.3 起 commit author 署 `DSH <dsh@webkubor.online>`(D1 上的 agent 身份)。
|
|
27
|
+
- trailer:`Agent: cli:claude-code`。
|
|
28
|
+
- commit type 用 conventional 写法 `chore(release):`。
|
|
29
|
+
- GH 操作走 `gh` CLI。
|
|
30
|
+
|
|
31
|
+
**为什么这次保留 `dsh-llm-hub` 的工作流**:1.5.0/1.5.1/1.5.2 的 commit 内容、CHANGELOG、assets/ 都是
|
|
32
|
+
对的,错的只是元数据(author / trailer / type)。元数据修一遍不影响业务,下次升级自然拉到
|
|
33
|
+
1.5.3 的内容。
|
|
34
|
+
|
|
35
|
+
**没有破坏性变更**,没有功能改动。
|
|
36
|
+
|
|
37
|
+
升级:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
dsh plugin --profile web update @dsh-plugins/dsh-llm-hub@^1.5.3
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## [1.5.2] - 2026-09-26
|
|
44
|
+
|
|
45
|
+
### 🔧 发版门禁 + README 推广区
|
|
46
|
+
|
|
47
|
+
- **`prepublishOnly` 门禁脚本** `scripts/prepublish-gate.mjs`:
|
|
48
|
+
在 `npm publish` 之前跑三条硬契约 —— tarball 必含 `package.json` / `cordis.patch.yml` /
|
|
49
|
+
`lib/*.js` / `README.md` / `LICENSE`、必含 `assets/*.svg`、CHANGELOG 顶部必含
|
|
50
|
+
`## [<当前 version>]` 段。任一条挂了 → `exit 1` → publish 整体失败。
|
|
51
|
+
跑 check + test + 门禁三件套,缺一不可。
|
|
52
|
+
- **README 新增「最新发布」区**:进 README 30 秒内看到 1.5.1 的三件用户事 + 三张 SVG 缩略图 +
|
|
53
|
+
npm / GitHub Release / 完整 CHANGELOG 三个直链 + 升级命令 + 破坏性变更说明。
|
|
54
|
+
- **README 双语同步**:英文版 `README.en.md` 不在 1.5.2 范围内(仅中文版挂推广区),
|
|
55
|
+
保持原样不动 —— 与既有双语策略一致,推广区只挂主语言。
|
|
56
|
+
|
|
57
|
+
**没有功能改动**,没有破坏性变更。从 1.5.1 升级只是拿到 README 排版与发版前多跑一道门禁。
|
|
58
|
+
|
|
59
|
+
升级:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
dsh plugin --profile web update @dsh-plugins/dsh-llm-hub@^1.5.2
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 为什么没做
|
|
66
|
+
|
|
67
|
+
- 不动英文 README:推广文案与图片需要单独翻译、单独审,1.5.2 走中文单语先行;下一版(1.6.x)做 EN/中英对照。
|
|
68
|
+
- 不在 publish.yml 里加同一道门禁:publish.yml 是 GitHub Actions 那一侧的事,
|
|
69
|
+
本机 `npm publish` 不走它。门禁必须双侧都加才完整;本版只加了本机侧,Actions 侧的 `tag 与版本一致性 + npm view 探测` 已经在 publish.yml 里。
|
|
70
|
+
下一步若要也防 GitHub 侧 drift,加一条「`npm view <pkg>@<ver>` 命中即跳过 publish」的 guard
|
|
71
|
+
已经在 publish.yml 里存在(步骤「校验 tag 与版本一致,并探测 npm」),所以 Actions 侧风险已封。
|
|
72
|
+
- 不动 `npm run deploy`:dev HEAD 已经与 npm 1.5.1 字节一致,profile 升级只走 `dsh plugin update`。
|
|
73
|
+
|
|
74
|
+
## [1.5.1] - 2026-09-26
|
|
75
|
+
|
|
76
|
+
### 🐛 修复 tarball 漏配 `assets/`
|
|
77
|
+
|
|
78
|
+
1.5.0 推到 npm 后校验发现 `package.json` 的 `files` 数组没有 `assets/`,导致从 npm 读
|
|
79
|
+
CHANGELOG.md 的人看不到截图(相对路径 `assets/*.svg` 在 tarball 里不存在)。
|
|
80
|
+
|
|
81
|
+
GH Release 那边**没有**受影响 —— 它解析 tag 时是去仓库拿文件,不是去 tarball,所以 1.5.0
|
|
82
|
+
的 Release 页面渲染图正常。
|
|
83
|
+
|
|
84
|
+
**没有功能改动**,没有破坏性变更。已装 1.5.0 的用户升级 1.5.1 只会拿到 tarball 多 3 个 SVG
|
|
85
|
+
(约 12 kB),其余字节级一致。
|
|
86
|
+
|
|
87
|
+
升级命令不变:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
dsh plugin --profile web add @dsh-plugins/dsh-llm-hub@^1.5.1
|
|
91
|
+
```
|
|
92
|
+
|
|
5
93
|
## [1.5.0] - 2026-09-26
|
|
6
94
|
|
|
7
95
|
> **一句话**:DSH 第一次能从你云端账单数据里分清「套餐 vs 按量」,并把套餐模型自动置顶;
|
package/README.md
CHANGED
|
@@ -49,6 +49,40 @@ dsh plugin --profile web add @dsh-plugins/dsh-llm-hub
|
|
|
49
49
|
|
|
50
50
|
---
|
|
51
51
|
|
|
52
|
+
## 最新发布 · v1.5.1 (2026-09-26)
|
|
53
|
+
|
|
54
|
+
> **一句话**:套餐 vs 按量付费**智能识别 + 手动切换**;LLM 下拉套餐模型**自动置顶**;
|
|
55
|
+
> 修了一个永远只显示「LLM Hub 已激活」的家族面板 bug。
|
|
56
|
+
|
|
57
|
+
📦 [v1.5.1 on npm](https://www.npmjs.com/package/@dsh-plugins/dsh-llm-hub/v/1.5.1) ·
|
|
58
|
+
🚀 [GitHub Release notes](https://github.com/webkubor/dsh-llm-hub/releases/tag/v1.5.1) ·
|
|
59
|
+
📋 [完整更新日志](./CHANGELOG.md)
|
|
60
|
+
|
|
61
|
+
三件用户能看到的事:
|
|
62
|
+
|
|
63
|
+
1. **套餐 vs 按量付费**:每个 provider 卡片新增 billing capsule,左边"按量付费"右边"套餐",
|
|
64
|
+
自动按 5 层 fallback 识别云端账单类型(settings → `/status` → `/token_plan/remains`
|
|
65
|
+
→ `/usage/quota/limit` → `/user/balance`),手动点另一边切模式即写回 settings。
|
|
66
|
+

|
|
67
|
+
2. **LLM 下拉套餐优先**:composer 模型选择器按当前 provider 的 billingMode 把套餐模型
|
|
68
|
+
置顶(绿色「套餐」徽章段),按量模型跟在后面。**不**自动改路由、不隐藏按量。
|
|
69
|
+

|
|
70
|
+
3. **家族面板真实激活探测(修 bug)**:设置 → 模型 → 底部「Webkubor DSH 扩展家族」,
|
|
71
|
+
之前的版本不管装几个插件永远只亮自己。改读 `window.__DSH_BOOT__.entries`
|
|
72
|
+
做真实激活探测,读不到时显示「判定不可用」而非谎报「没装」。
|
|
73
|
+

|
|
74
|
+
|
|
75
|
+
升级:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
dsh plugin --profile web update @dsh-plugins/dsh-llm-hub@^1.5.1
|
|
79
|
+
# 重启 DSH
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**没有破坏性变更**。旧版(≤ 1.3.x)的 `keyPool[provider]` 配置在 1.4.0 已删除,所有 key 走 `apiKeyEnv` 数组。
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
52
86
|
## 它补的是什么
|
|
53
87
|
|
|
54
88
|
DSH 自己已经具备全部机制,缺的只是"官方适配器没去用它们":
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-plugins/dsh-llm-hub",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.3",
|
|
4
4
|
"description": "DSH 模型管理层:网关可达性探测、模型目录拉取、DeepSeek + MiniMax/智谱/Moonshot/StepFun 余额与配额、本月用量统计、余额预警、Provider 健康看板,再把本机装好的 codex / claude / agy 注册成子代理(装了才出现)。零运行时依赖,不改动 DSH 安装。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -31,7 +31,8 @@
|
|
|
31
31
|
"deploy": "rsync -av --delete lib/ ~/.dsh/profiles/web/node_modules/@dsh-plugins/dsh-llm-hub/lib/ && rsync -av types package.json cordis.patch.yml README.md README.en.md LICENSE ~/.dsh/profiles/web/node_modules/@dsh-plugins/dsh-llm-hub/",
|
|
32
32
|
"preview": "npm run deploy && open http://127.0.0.1:3080",
|
|
33
33
|
"check": "for f in lib/*.js; do node --check \"$f\" || exit 1; done",
|
|
34
|
-
"test": "node --test"
|
|
34
|
+
"test": "node --test",
|
|
35
|
+
"prepublishOnly": "npm run check && npm test && node scripts/prepublish-gate.mjs"
|
|
35
36
|
},
|
|
36
37
|
"keywords": [
|
|
37
38
|
"dsh",
|
|
@@ -76,6 +77,7 @@
|
|
|
76
77
|
"assets",
|
|
77
78
|
"cordis.patch.yml",
|
|
78
79
|
"lib",
|
|
80
|
+
"scripts",
|
|
79
81
|
"types"
|
|
80
82
|
]
|
|
81
83
|
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* prepublish-gate —— 在 `npm publish` 之前把三条硬契约拦在本地。
|
|
4
|
+
*
|
|
5
|
+
* 为什么是门禁而不是文档:
|
|
6
|
+
* 2026-09-26 推 1.5.0 时, CHANGELOG 写了、assets/ 落了、版本号 bump 了,
|
|
7
|
+
* 但 package.json 的 files 数组忘了加 'assets' —— 推上 npm 后 122kB
|
|
8
|
+
* tarball 不含 3 张 SVG, 从 npm 读 CHANGELOG.md 的人看不到截图。
|
|
9
|
+
* 同样那次, 1.5.1 推上去时 publish.yml 在「GH Release」那一步挂了:
|
|
10
|
+
* CHANGELOG 里没 [1.5.1] 段, 脚本 process.exit(1), 整个 job 标红。
|
|
11
|
+
* npm publish 已经过 —— 1.5.1 在 npm 上, 但 GH Release 没建, 走到 README
|
|
12
|
+
* 想挂 release link 时发现 404。
|
|
13
|
+
*
|
|
14
|
+
* 两条都是「约定没做成门禁」。本脚本把三条契约变成前置门:
|
|
15
|
+
* 1. tarball 必含 paths in MUST_INCLUDE
|
|
16
|
+
* 2. CHANGELOG 顶部必含 '## [<当前 package.json version>]' 段
|
|
17
|
+
* 3. assets/ 目录里至少有一张 .svg 推广图 (不允许空目录占位)
|
|
18
|
+
*
|
|
19
|
+
* 任一条挂了: process.exit(1) + stderr 一行指明错在哪。
|
|
20
|
+
*
|
|
21
|
+
* `npm publish` 调用 prepublishOnly 时, 本脚本非零退出 → publish 整体
|
|
22
|
+
* 失败, tarball 不会被推上 registry, 也就不会出现「npm 上了但本地行为
|
|
23
|
+
* 与预期不一致」的漂移。
|
|
24
|
+
*/
|
|
25
|
+
import { readFileSync } from 'node:fs'
|
|
26
|
+
import { execFileSync } from 'node:child_process'
|
|
27
|
+
import { dirname, join } from 'node:path'
|
|
28
|
+
import { fileURLToPath } from 'node:url'
|
|
29
|
+
|
|
30
|
+
const here = dirname(fileURLToPath(import.meta.url))
|
|
31
|
+
const pkgRoot = dirname(here)
|
|
32
|
+
|
|
33
|
+
const pkg = JSON.parse(readFileSync(join(pkgRoot, 'package.json'), 'utf8'))
|
|
34
|
+
const version = pkg.version
|
|
35
|
+
|
|
36
|
+
const MUST_INCLUDE = [
|
|
37
|
+
'package.json',
|
|
38
|
+
'cordis.patch.yml',
|
|
39
|
+
'lib/client.js',
|
|
40
|
+
'lib/index.js',
|
|
41
|
+
'lib/harness.js',
|
|
42
|
+
'README.md',
|
|
43
|
+
'LICENSE'
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
const ASSETS_MIN = 1 // 至少一张 .svg, 防止目录被空提交
|
|
47
|
+
|
|
48
|
+
const errors = []
|
|
49
|
+
|
|
50
|
+
// ── 1. tarball 路径断言 ────────────────────────────────────────────────────
|
|
51
|
+
let packFiles
|
|
52
|
+
try {
|
|
53
|
+
const out = execFileSync('npm', ['pack', '--dry-run', '--json'], {
|
|
54
|
+
cwd: pkgRoot,
|
|
55
|
+
encoding: 'utf8',
|
|
56
|
+
stdio: ['ignore', 'pipe', 'inherit']
|
|
57
|
+
})
|
|
58
|
+
packFiles = JSON.parse(out)[0].files.map(f => f.path)
|
|
59
|
+
} catch (err) {
|
|
60
|
+
console.error('[prepublish-gate] npm pack --dry-run 失败:', err.message)
|
|
61
|
+
process.exit(2)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const missing = MUST_INCLUDE.filter(p => !packFiles.includes(p))
|
|
65
|
+
if (missing.length > 0) {
|
|
66
|
+
errors.push(`tarball 缺少必含文件: ${missing.join(', ')}\n → 在 package.json 'files' 数组里列出, 或确认文件实际存在`)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ── 2. assets/ 目录必含至少一张 SVG ─────────────────────────────────────────
|
|
70
|
+
const assetSvgs = packFiles.filter(p => p.startsWith('assets/') && p.endsWith('.svg'))
|
|
71
|
+
if (assetSvgs.length < ASSETS_MIN) {
|
|
72
|
+
errors.push(`tarball assets/ 里 .svg < ${ASSETS_MIN}: 找到 ${assetSvgs.length} 张\n → 在 assets/ 下放图, 并确认 package.json 'files' 含 'assets'`)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ── 3. CHANGELOG 顶部必含 '## [<当前 version>]' 段 ─────────────────────────
|
|
76
|
+
const changelogPath = join(pkgRoot, 'CHANGELOG.md')
|
|
77
|
+
let changelogText
|
|
78
|
+
try {
|
|
79
|
+
changelogText = readFileSync(changelogPath, 'utf8')
|
|
80
|
+
} catch (err) {
|
|
81
|
+
errors.push(`CHANGELOG.md 读取失败: ${err.message}`)
|
|
82
|
+
changelogText = ''
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (changelogText) {
|
|
86
|
+
const expectedHeader = `## [${version}]`
|
|
87
|
+
if (!changelogText.includes(expectedHeader)) {
|
|
88
|
+
errors.push(`CHANGELOG.md 缺少 '${expectedHeader}' 段\n → publish.yml 的 release body 直接 grep 这一行; 缺了 GH Release 创建会失败, npm 上却有版本号, 出现「npm 上了 / Release 没建」的漂移`)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ── 报告 ──────────────────────────────────────────────────────────────────
|
|
93
|
+
if (errors.length > 0) {
|
|
94
|
+
console.error(`\n[prepublish-gate] ${errors.length} 条契约不满足, 拒绝发版:\n`)
|
|
95
|
+
for (const e of errors) {
|
|
96
|
+
console.error(' ✖', e)
|
|
97
|
+
console.error('')
|
|
98
|
+
}
|
|
99
|
+
console.error('[prepublish-gate] exit 1 → npm publish 已中止。修完再推。')
|
|
100
|
+
process.exit(1)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
console.log(`[prepublish-gate] ✓ @${pkg.name}@${version} 三条契约通过`)
|
|
104
|
+
console.log(`[prepublish-gate] · tarball: ${packFiles.length} 个文件, 含 ${assetSvgs.length} 张 assets/*.svg`)
|
|
105
|
+
console.log(`[prepublish-gate] · CHANGELOG 含 '## [${version}]' 段`)
|