@dsh-plugins/dsh-llm-hub 1.5.0 → 1.5.2

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 CHANGED
@@ -2,6 +2,56 @@
2
2
 
3
3
  本项目遵循 [Semantic Versioning](https://semver.org/lang/zh-CN/)。
4
4
 
5
+ ## [1.5.2] - 2026-09-26
6
+
7
+ ### 🔧 发版门禁 + README 推广区
8
+
9
+ - **`prepublishOnly` 门禁脚本** `scripts/prepublish-gate.mjs`:
10
+ 在 `npm publish` 之前跑三条硬契约 —— tarball 必含 `package.json` / `cordis.patch.yml` /
11
+ `lib/*.js` / `README.md` / `LICENSE`、必含 `assets/*.svg`、CHANGELOG 顶部必含
12
+ `## [<当前 version>]` 段。任一条挂了 → `exit 1` → publish 整体失败。
13
+ 跑 check + test + 门禁三件套,缺一不可。
14
+ - **README 新增「最新发布」区**:进 README 30 秒内看到 1.5.1 的三件用户事 + 三张 SVG 缩略图 +
15
+ npm / GitHub Release / 完整 CHANGELOG 三个直链 + 升级命令 + 破坏性变更说明。
16
+ - **README 双语同步**:英文版 `README.en.md` 不在 1.5.2 范围内(仅中文版挂推广区),
17
+ 保持原样不动 —— 与既有双语策略一致,推广区只挂主语言。
18
+
19
+ **没有功能改动**,没有破坏性变更。从 1.5.1 升级只是拿到 README 排版与发版前多跑一道门禁。
20
+
21
+ 升级:
22
+
23
+ ```bash
24
+ dsh plugin --profile web update @dsh-plugins/dsh-llm-hub@^1.5.2
25
+ ```
26
+
27
+ ### 为什么没做
28
+
29
+ - 不动英文 README:推广文案与图片需要单独翻译、单独审,1.5.2 走中文单语先行;下一版(1.6.x)做 EN/中英对照。
30
+ - 不在 publish.yml 里加同一道门禁:publish.yml 是 GitHub Actions 那一侧的事,
31
+ 本机 `npm publish` 不走它。门禁必须双侧都加才完整;本版只加了本机侧,Actions 侧的 `tag 与版本一致性 + npm view 探测` 已经在 publish.yml 里。
32
+ 下一步若要也防 GitHub 侧 drift,加一条「`npm view <pkg>@<ver>` 命中即跳过 publish」的 guard
33
+ 已经在 publish.yml 里存在(步骤「校验 tag 与版本一致,并探测 npm」),所以 Actions 侧风险已封。
34
+ - 不动 `npm run deploy`:dev HEAD 已经与 npm 1.5.1 字节一致,profile 升级只走 `dsh plugin update`。
35
+
36
+ ## [1.5.1] - 2026-09-26
37
+
38
+ ### 🐛 修复 tarball 漏配 `assets/`
39
+
40
+ 1.5.0 推到 npm 后校验发现 `package.json` 的 `files` 数组没有 `assets/`,导致从 npm 读
41
+ CHANGELOG.md 的人看不到截图(相对路径 `assets/*.svg` 在 tarball 里不存在)。
42
+
43
+ GH Release 那边**没有**受影响 —— 它解析 tag 时是去仓库拿文件,不是去 tarball,所以 1.5.0
44
+ 的 Release 页面渲染图正常。
45
+
46
+ **没有功能改动**,没有破坏性变更。已装 1.5.0 的用户升级 1.5.1 只会拿到 tarball 多 3 个 SVG
47
+ (约 12 kB),其余字节级一致。
48
+
49
+ 升级命令不变:
50
+
51
+ ```bash
52
+ dsh plugin --profile web add @dsh-plugins/dsh-llm-hub@^1.5.1
53
+ ```
54
+
5
55
  ## [1.5.0] - 2026-09-26
6
56
 
7
57
  > **一句话**: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
+ ![](assets/02-billing-capsule.svg)
67
+ 2. **LLM 下拉套餐优先**:composer 模型选择器按当前 provider 的 billingMode 把套餐模型
68
+ 置顶(绿色「套餐」徽章段),按量模型跟在后面。**不**自动改路由、不隐藏按量。
69
+ ![](assets/03-model-dropdown-priorities.svg)
70
+ 3. **家族面板真实激活探测(修 bug)**:设置 → 模型 → 底部「Webkubor DSH 扩展家族」,
71
+ 之前的版本不管装几个插件永远只亮自己。改读 `window.__DSH_BOOT__.entries`
72
+ 做真实激活探测,读不到时显示「判定不可用」而非谎报「没装」。
73
+ ![](assets/01-family-dock.svg)
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 自己已经具备全部机制,缺的只是"官方适配器没去用它们":
@@ -0,0 +1,79 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="640" height="340" viewBox="0 0 640 340" font-family="-apple-system, 'SF Pro Text', 'PingFang SC', system-ui, sans-serif">
2
+ <defs>
3
+ <linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
4
+ <stop offset="0%" stop-color="#1f1d2b"/>
5
+ <stop offset="100%" stop-color="#16151f"/>
6
+ </linearGradient>
7
+ <linearGradient id="card" x1="0" y1="0" x2="0" y2="1">
8
+ <stop offset="0%" stop-color="#2a2738"/>
9
+ <stop offset="100%" stop-color="#221f2c"/>
10
+ </linearGradient>
11
+ <radialGradient id="dot" cx="0.5" cy="0.5" r="0.5">
12
+ <stop offset="0%" stop-color="#34d399"/>
13
+ <stop offset="100%" stop-color="#10b981"/>
14
+ </radialGradient>
15
+ <filter id="blur"><feGaussianBlur stdDeviation="6"/></filter>
16
+ </defs>
17
+
18
+ <rect width="640" height="340" fill="url(#bg)"/>
19
+ <rect x="0" y="0" width="640" height="340" fill="#000" opacity="0.0"/>
20
+ <circle cx="80" cy="60" r="120" fill="#7c3aed" opacity="0.10" filter="url(#blur)"/>
21
+ <circle cx="560" cy="280" r="140" fill="#3b82f6" opacity="0.10" filter="url(#blur)"/>
22
+
23
+ <!-- panel container -->
24
+ <rect x="32" y="22" width="576" height="296" rx="12" fill="#1a1825" stroke="#2d2b3a" stroke-width="1"/>
25
+
26
+ <!-- head -->
27
+ <g transform="translate(48,46)">
28
+ <text x="0" y="14" font-size="14" font-weight="650" fill="#e5e7eb">🌟 Webkubor DSH 扩展家族</text>
29
+ <text x="384" y="14" font-size="10" fill="#9ca3af" text-anchor="end">一键构建完整智能体开发环境</text>
30
+ </g>
31
+
32
+ <!-- 4 cards grid 2x2, each 270x110 -->
33
+ <!-- card 1: Bloom Theme -->
34
+ <g transform="translate(48,82)">
35
+ <rect width="266" height="104" rx="8" fill="url(#card)" stroke="#2d2b3a"/>
36
+ <text x="14" y="24" font-size="14">🌸</text>
37
+ <text x="34" y="26" font-size="12" font-weight="600" fill="#e5e7eb">Bloom Theme</text>
38
+ <text x="14" y="50" font-size="10.5" fill="#9ca3af">落霞 Bloom 极客质感毛玻璃主题与代码高亮</text>
39
+ <circle cx="14" cy="78" r="3.5" fill="url(#dot)"/>
40
+ <text x="24" y="82" font-size="10.5" font-weight="600" fill="#10b981">已激活</text>
41
+ <text x="252" y="82" font-size="10" fill="#6b7280" text-anchor="end">GitHub ↗</text>
42
+ </g>
43
+
44
+ <!-- card 2: LLM Hub -->
45
+ <g transform="translate(326,82)">
46
+ <rect width="266" height="104" rx="8" fill="url(#card)" stroke="#2d2b3a"/>
47
+ <text x="14" y="24" font-size="14">🎛️</text>
48
+ <text x="34" y="26" font-size="12" font-weight="600" fill="#e5e7eb">LLM Hub</text>
49
+ <text x="14" y="50" font-size="10.5" fill="#9ca3af">多模型网关、余额配额、多 Key 轮换与极客大屏</text>
50
+ <circle cx="14" cy="78" r="3.5" fill="url(#dot)"/>
51
+ <text x="24" y="82" font-size="10.5" font-weight="600" fill="#10b981">已激活</text>
52
+ <text x="252" y="82" font-size="10" fill="#6b7280" text-anchor="end">GitHub ↗</text>
53
+ </g>
54
+
55
+ <!-- card 3: User Mirror -->
56
+ <g transform="translate(48,196)">
57
+ <rect width="266" height="104" rx="8" fill="url(#card)" stroke="#2d2b3a"/>
58
+ <text x="14" y="24" font-size="14">🪞</text>
59
+ <text x="34" y="26" font-size="12" font-weight="600" fill="#e5e7eb">User Mirror</text>
60
+ <text x="14" y="50" font-size="10.5" fill="#9ca3af">用户角色数字画像、习惯偏好与记忆网络</text>
61
+ <circle cx="14" cy="78" r="3.5" fill="url(#dot)"/>
62
+ <text x="24" y="82" font-size="10.5" font-weight="600" fill="#10b981">已激活</text>
63
+ <text x="252" y="82" font-size="10" fill="#6b7280" text-anchor="end">GitHub ↗</text>
64
+ </g>
65
+
66
+ <!-- card 4: Env Inspector -->
67
+ <g transform="translate(326,196)">
68
+ <rect width="266" height="104" rx="8" fill="url(#card)" stroke="#2d2b3a"/>
69
+ <text x="14" y="24" font-size="14">🖥️</text>
70
+ <text x="34" y="26" font-size="12" font-weight="600" fill="#e5e7eb">Env Inspector</text>
71
+ <text x="14" y="50" font-size="10.5" fill="#9ca3af">端口监听释放、CLI 工具链与环境大屏</text>
72
+ <circle cx="14" cy="78" r="3.5" fill="url(#dot)"/>
73
+ <text x="24" y="82" font-size="10.5" font-weight="600" fill="#10b981">已激活</text>
74
+ <text x="252" y="82" font-size="10" fill="#6b7280" text-anchor="end">GitHub ↗</text>
75
+ </g>
76
+
77
+ <!-- caption hint -->
78
+ <text x="320" y="332" font-size="9" fill="#6b7280" text-anchor="middle">设置 → 模型 → 底部「Webkubor DSH 扩展家族」</text>
79
+ </svg>
@@ -0,0 +1,72 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="720" height="280" viewBox="0 0 720 280" font-family="-apple-system, 'SF Pro Text', 'PingFang SC', system-ui, sans-serif">
2
+ <defs>
3
+ <linearGradient id="bg2" x1="0" y1="0" x2="0" y2="1">
4
+ <stop offset="0%" stop-color="#1f1d2b"/>
5
+ <stop offset="100%" stop-color="#16151f"/>
6
+ </linearGradient>
7
+ <linearGradient id="card2" x1="0" y1="0" x2="0" y2="1">
8
+ <stop offset="0%" stop-color="#2a2738"/>
9
+ <stop offset="100%" stop-color="#221f2c"/>
10
+ </linearGradient>
11
+ <linearGradient id="success" x1="0" y1="0" x2="1" y2="0">
12
+ <stop offset="0%" stop-color="#10b981"/>
13
+ <stop offset="100%" stop-color="#059669"/>
14
+ </linearGradient>
15
+ <linearGradient id="muted" x1="0" y1="0" x2="1" y2="0">
16
+ <stop offset="0%" stop-color="#3a3748"/>
17
+ <stop offset="100%" stop-color="#2d2b3a"/>
18
+ </linearGradient>
19
+ </defs>
20
+
21
+ <rect width="720" height="280" fill="url(#bg2)"/>
22
+
23
+ <!-- title bar -->
24
+ <text x="36" y="38" font-size="14" font-weight="650" fill="#e5e7eb">📦 模型卡片 · 套餐智能识别</text>
25
+ <text x="684" y="38" font-size="10.5" fill="#9ca3af" text-anchor="end">ModelGo 中转 · 11 个模型 · key 已配置</text>
26
+
27
+ <!-- one provider card expanded -->
28
+ <rect x="36" y="58" width="648" height="178" rx="10" fill="url(#card2)" stroke="#2d2b3a"/>
29
+
30
+ <!-- left: provider meta -->
31
+ <g transform="translate(56,82)">
32
+ <text x="0" y="0" font-size="12" font-weight="650" fill="#e5e7eb">ModelGo 中转</text>
33
+ <text x="0" y="18" font-size="10.5" fill="#9ca3af">https://api.modelgo.com · anthropic-messages</text>
34
+ <text x="0" y="36" font-size="10" fill="#6b7280">key ✓ · gpt-6-astra · claude-sonnet-4.5 · …</text>
35
+
36
+ <!-- billing capsule -->
37
+ <g transform="translate(0,58)">
38
+ <rect width="148" height="22" rx="11" fill="#1a1825" stroke="#2d2b3a"/>
39
+ <!-- left pill: pay-as-you-go active -->
40
+ <rect x="2" y="2" width="72" height="18" rx="9" fill="url(#success)"/>
41
+ <text x="38" y="15" font-size="10.5" font-weight="600" fill="#fff" text-anchor="middle">按量付费</text>
42
+ <!-- right pill: subscription -->
43
+ <rect x="76" y="2" width="68" height="18" rx="9" fill="url(#muted)"/>
44
+ <text x="110" y="15" font-size="10.5" fill="#d1d5db" text-anchor="middle">套餐</text>
45
+ </g>
46
+
47
+ <!-- caption -->
48
+ <text x="0" y="98" font-size="9.5" fill="#9ca3af">已按 /usage + /token_plan/remains 自动识别,</text>
49
+ <text x="0" y="112" font-size="9.5" fill="#9ca3af">可用时默认切到「套餐」分组。</text>
50
+ </g>
51
+
52
+ <!-- right: visual proof of toggle -->
53
+ <g transform="translate(420,82)">
54
+ <!-- before: scatter -->
55
+ <text x="0" y="0" font-size="10.5" fill="#9ca3af">切换前</text>
56
+ <rect x="0" y="10" width="240" height="60" rx="6" fill="#1a1825" stroke="#2d2b3a"/>
57
+ <text x="10" y="28" font-size="10" fill="#9ca3af">gpt-6-astra</text>
58
+ <text x="10" y="42" font-size="10" fill="#9ca3af">claude-sonnet-4.5</text>
59
+ <text x="10" y="56" font-size="10" fill="#9ca3af">deepseek-r1</text>
60
+
61
+ <!-- after: split -->
62
+ <text x="0" y="84" font-size="10.5" fill="#9ca3af">切换后</text>
63
+ <rect x="0" y="94" width="240" height="74" rx="6" fill="#1a1825" stroke="#2d2b3a"/>
64
+ <text x="10" y="112" font-size="10" font-weight="600" fill="#10b981">套餐</text>
65
+ <text x="50" y="112" font-size="10" fill="#d1d5db">claude-sonnet-4.5 · gpt-6-astra</text>
66
+ <text x="10" y="134" font-size="10" fill="#9ca3af">按量 · deepseek-r1 · qwen-2.5</text>
67
+ <text x="10" y="150" font-size="10" fill="#9ca3af">按量 · gemini-2.5-pro · …</text>
68
+ </g>
69
+
70
+ <!-- caption -->
71
+ <text x="360" y="266" font-size="9" fill="#6b7280" text-anchor="middle">设置 → 模型 → 单个 provider 卡 · 账单胶囊</text>
72
+ </svg>
@@ -0,0 +1,76 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="720" height="360" viewBox="0 0 720 360" font-family="-apple-system, 'SF Pro Text', 'PingFang SC', system-ui, sans-serif">
2
+ <defs>
3
+ <linearGradient id="bg3" x1="0" y1="0" x2="0" y2="1">
4
+ <stop offset="0%" stop-color="#1f1d2b"/>
5
+ <stop offset="100%" stop-color="#16151f"/>
6
+ </linearGradient>
7
+ <linearGradient id="card3" x1="0" y1="0" x2="0" y2="1">
8
+ <stop offset="0%" stop-color="#2a2738"/>
9
+ <stop offset="100%" stop-color="#221f2c"/>
10
+ </linearGradient>
11
+ <linearGradient id="pillSub" x1="0" y1="0" x2="1" y2="0">
12
+ <stop offset="0%" stop-color="#10b981"/>
13
+ <stop offset="100%" stop-color="#059669"/>
14
+ </linearGradient>
15
+ <linearGradient id="pillUsage" x1="0" y1="0" x2="1" y2="0">
16
+ <stop offset="0%" stop-color="#3b82f6"/>
17
+ <stop offset="100%" stop-color="#2563eb"/>
18
+ </linearGradient>
19
+ </defs>
20
+
21
+ <rect width="720" height="360" fill="url(#bg3)"/>
22
+
23
+ <!-- composer surface (faded) -->
24
+ <rect x="0" y="0" width="720" height="360" fill="#0d0c12" opacity="0.5"/>
25
+ <text x="36" y="46" font-size="14" font-weight="650" fill="#e5e7eb">🎯 模型下拉 · 套餐优先</text>
26
+ <text x="684" y="46" font-size="10.5" fill="#9ca3af" text-anchor="end">composer 模型选择器</text>
27
+
28
+ <!-- mock composer input -->
29
+ <rect x="36" y="68" width="648" height="48" rx="8" fill="url(#card3)" stroke="#2d2b3a"/>
30
+ <text x="56" y="98" font-size="12" fill="#9ca3af">描述你想要构建的内容,/ 调用指令,@ 文件或对话</text>
31
+
32
+ <!-- dropdown panel -->
33
+ <g transform="translate(36,134)">
34
+ <rect width="648" height="206" rx="10" fill="url(#card3)" stroke="#2d2b3a"/>
35
+
36
+ <!-- section header: 套餐 -->
37
+ <g transform="translate(20,18)">
38
+ <rect width="40" height="14" rx="7" fill="url(#pillSub)"/>
39
+ <text x="20" y="11" font-size="9" font-weight="700" fill="#fff" text-anchor="middle">套餐</text>
40
+ <text x="48" y="11" font-size="10" fill="#10b981" font-weight="600">优先</text>
41
+ </g>
42
+
43
+ <!-- sub items -->
44
+ <g transform="translate(20,40)">
45
+ <rect width="608" height="26" rx="4" fill="#1f1d2b"/>
46
+ <text x="14" y="17" font-size="11" fill="#e5e7eb">claude-sonnet-4.5</text>
47
+ <text x="180" y="17" font-size="9" fill="#10b981">套餐 · 剩 42h / week</text>
48
+ </g>
49
+ <g transform="translate(20,70)">
50
+ <rect width="608" height="26" rx="4" fill="#1f1d2b"/>
51
+ <text x="14" y="17" font-size="11" fill="#e5e7eb">gpt-6-astra</text>
52
+ <text x="180" y="17" font-size="9" fill="#10b981">套餐 · 套餐余额 92%</text>
53
+ </g>
54
+
55
+ <!-- divider -->
56
+ <line x1="20" y1="106" x2="628" y2="106" stroke="#2d2b3a" stroke-dasharray="2 2"/>
57
+
58
+ <!-- section header: 按量 -->
59
+ <g transform="translate(20,114)">
60
+ <rect width="48" height="14" rx="7" fill="url(#pillUsage)"/>
61
+ <text x="24" y="11" font-size="9" font-weight="700" fill="#fff" text-anchor="middle">按量</text>
62
+ </g>
63
+
64
+ <g transform="translate(20,136)">
65
+ <rect width="608" height="26" rx="4" fill="#1f1d2b"/>
66
+ <text x="14" y="17" font-size="11" fill="#e5e7eb">deepseek-r1</text>
67
+ <text x="180" y="17" font-size="9" fill="#9ca3af">按量 · $3.40 / 1M</text>
68
+ </g>
69
+ <g transform="translate(20,166)">
70
+ <rect width="608" height="22" rx="4" fill="transparent"/>
71
+ <text x="14" y="16" font-size="10" fill="#9ca3af">展开其余 4 个按量模型</text>
72
+ </g>
73
+ </g>
74
+
75
+ <text x="360" y="350" font-size="9" fill="#6b7280" text-anchor="middle">套餐模式识别后自动置顶 · 单击切换模式走 settings</text>
76
+ </svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-plugins/dsh-llm-hub",
3
- "version": "1.5.0",
3
+ "version": "1.5.2",
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",
@@ -73,6 +74,7 @@
73
74
  "LICENSE",
74
75
  "README.en.md",
75
76
  "README.md",
77
+ "assets",
76
78
  "cordis.patch.yml",
77
79
  "lib",
78
80
  "types"