@dsh-plugins/dsh-llm-hub 1.6.0 → 1.6.1
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 +9 -0
- package/lib/client.js +62 -88
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
本项目遵循 [Semantic Versioning](https://semver.org/lang/zh-CN/)。
|
|
4
4
|
|
|
5
|
+
## [1.6.1] - 2026-09-28
|
|
6
|
+
|
|
7
|
+
### 🧹 去掉模型页底部的「热门大模型一键装配」,改为添加时按厂商匹配
|
|
8
|
+
|
|
9
|
+
- 删掉页脚常驻的预设抽屉:它和用户正在配哪一家无关,读起来像一块广告
|
|
10
|
+
- 改为在「添加提供方」里**选中某一家时**,草稿卡上只给匹配到的那一家一行提示:名称 · 推荐模型 · 获取 Key ↗;没匹配到的厂商不显示任何东西
|
|
11
|
+
- 不再提供 YAML 模板:草稿卡本身就是配置表单,而模板根键(`minimax`)与目录 id(`minimax-cn`)对不上,复制过去反而误导
|
|
12
|
+
- 修复:添加提供方时,只是选了下拉框就出现红字「llm-pi-ai 段里没有 "xxx" 这个 provider」。草稿态不再渲染原卡内容
|
|
13
|
+
|
|
5
14
|
## [1.6.0] - 2026-09-28
|
|
6
15
|
|
|
7
16
|
### ✨ 智能路由:组可排序 + 折叠摘要
|
package/lib/client.js
CHANGED
|
@@ -213,10 +213,6 @@ window.__ModuleLoader__.load({
|
|
|
213
213
|
heroFastest: '最优延迟',
|
|
214
214
|
heroSecurity: '凭据防护',
|
|
215
215
|
heroSecSafe: '零明文脱敏中',
|
|
216
|
-
presetsTitle: '⚡ 热门大模型一键装配',
|
|
217
|
-
presetsSub: '点击主流服务商快速复制 YAML 配置模板与直达控制台',
|
|
218
|
-
presetsCopied: '已复制配置片段',
|
|
219
|
-
presetsCopyBtn: '复制 YAML',
|
|
220
216
|
presetsDocsBtn: '获取 Key ↗',
|
|
221
217
|
usageTitle: '本月用量',
|
|
222
218
|
usageCalls: '次调用',
|
|
@@ -367,10 +363,6 @@ window.__ModuleLoader__.load({
|
|
|
367
363
|
heroFastest: 'Fastest ping',
|
|
368
364
|
heroSecurity: 'Key security',
|
|
369
365
|
heroSecSafe: 'Masked in memory',
|
|
370
|
-
presetsTitle: '⚡ Popular LLM Quick Presets',
|
|
371
|
-
presetsSub: 'One-click YAML config snippets and official key links',
|
|
372
|
-
presetsCopied: 'YAML snippet copied',
|
|
373
|
-
presetsCopyBtn: 'Copy YAML',
|
|
374
366
|
presetsDocsBtn: 'Get Key ↗',
|
|
375
367
|
usageTitle: 'This month',
|
|
376
368
|
usageCalls: 'calls',
|
|
@@ -685,17 +677,12 @@ window.__ModuleLoader__.load({
|
|
|
685
677
|
'.dsh-llm-hub-hero__card{display:flex;flex-direction:column;gap:2px;padding:8px 10px;border-radius:6px;border:.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2,rgba(255,255,255,.02));backdrop-filter:blur(6px)}',
|
|
686
678
|
'.dsh-llm-hub-hero__num{font-size:15px;font-weight:700;color:var(--dsw-alias-label-primary);font-family:ui-monospace,SFMono-Regular,monospace;letter-spacing:-0.3px;line-height:1.2}',
|
|
687
679
|
'.dsh-llm-hub-hero__label{font-size:10.5px;color:var(--dsw-alias-label-secondary);opacity:.85}',
|
|
688
|
-
//
|
|
689
|
-
'.dsh-llm-hub-
|
|
690
|
-
'
|
|
691
|
-
'.dsh-llm-hub-
|
|
692
|
-
'.dsh-llm-hub-
|
|
693
|
-
'.dsh-llm-hub-
|
|
694
|
-
'.dsh-llm-hub-presets__item:hover{border-color:var(--dsw-alias-brand-primary,#3b82f6);transform:translateY(-1px);background:var(--dsw-alias-bg-layer-3,rgba(255,255,255,.05))}',
|
|
695
|
-
'.dsh-llm-hub-presets__name{font-weight:600;font-size:11.5px;color:var(--dsw-alias-label-primary)}',
|
|
696
|
-
'.dsh-llm-hub-presets__desc{font-size:10px;color:var(--dsw-alias-label-secondary);opacity:.75;line-height:1.3}',
|
|
697
|
-
'.dsh-llm-hub-presets__detail{margin-top:6px;padding:8px;border-radius:4px;background:var(--dsw-alias-bg-layer-3,rgba(0,0,0,.2));border:.5px solid var(--dsw-alias-border-l1);font-size:11px}',
|
|
698
|
-
'.dsh-llm-hub-presets__code{font-family:ui-monospace,SFMono-Regular,monospace;font-size:10px;white-space:pre-wrap;color:var(--dsw-alias-label-secondary);margin:4px 0}',
|
|
680
|
+
// 添加提供方草稿卡上的匹配提示(1.6.0)
|
|
681
|
+
'.dsh-llm-hub-preset-hint{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 8px;margin:0 0 8px;padding:6px 10px;border-radius:6px;',
|
|
682
|
+
'border:.5px solid var(--dsw-alias-border-l1);font-size:11px;line-height:1.5}',
|
|
683
|
+
'.dsh-llm-hub-preset-hint__name{font-weight:600;color:var(--dsw-alias-label-primary)}',
|
|
684
|
+
'.dsh-llm-hub-preset-hint__desc{color:var(--dsw-alias-label-secondary);flex:1 1 auto;min-width:0}',
|
|
685
|
+
'.dsh-llm-hub-preset-hint__link{color:var(--dsw-alias-brand-primary,#3b82f6);text-decoration:none;white-space:nowrap}',
|
|
699
686
|
// 延迟高亮胶囊
|
|
700
687
|
'.dsh-llm-hub-latency-badge{display:inline-flex;align-items:center;gap:3.5px;padding:1px 5px;border-radius:3px;font-size:10.5px;font-variant-numeric:tabular-nums;line-height:1}',
|
|
701
688
|
'.dsh-llm-hub-latency-badge.is-fast{background:rgba(16,185,129,.08);color:var(--dsw-alias-state-success-primary,#10b981);border:.5px solid rgba(16,185,129,.2)}',
|
|
@@ -1543,45 +1530,45 @@ window.__ModuleLoader__.load({
|
|
|
1543
1530
|
const PRESETS = [
|
|
1544
1531
|
{
|
|
1545
1532
|
id: 'deepseek',
|
|
1533
|
+
match: ['deepseek', 'llm-deepseek'],
|
|
1546
1534
|
name: '🇨🇳 DeepSeek 官方',
|
|
1547
1535
|
desc: 'V4.1 Flash / V4 Pro 极速官方直连',
|
|
1548
|
-
docUrl: 'https://platform.deepseek.com/api_keys'
|
|
1549
|
-
yaml: 'llm-deepseek:\n keyPool:\n llm-deepseek:\n - name: "主账号"\n env: DEEPSEEK_API_KEY\n models:\n - id: deepseek-flash\n name: DeepSeek-V4.1-Flash\n - id: deepseek-v4-pro\n name: DeepSeek-V4-Pro'
|
|
1536
|
+
docUrl: 'https://platform.deepseek.com/api_keys'
|
|
1550
1537
|
},
|
|
1551
1538
|
{
|
|
1552
1539
|
id: 'minimax',
|
|
1540
|
+
match: ['minimax', 'minimax-cn'],
|
|
1553
1541
|
name: '⚡ MiniMax',
|
|
1554
1542
|
desc: 'MiniMax-M3 百万上下文超强大模型',
|
|
1555
|
-
docUrl: 'https://platform.minimaxi.com/user-center/basic-information/interface-key'
|
|
1556
|
-
yaml: 'minimax:\n displayName: MiniMax\n api: openai-completions\n baseURL: https://api.minimaxi.com/v1\n apiKeyEnv: MINIMAX_API_KEY\n models:\n - id: MiniMax-M3\n name: MiniMax-M3\n - id: MiniMax-M2.7\n name: MiniMax-M2.7'
|
|
1543
|
+
docUrl: 'https://platform.minimaxi.com/user-center/basic-information/interface-key'
|
|
1557
1544
|
},
|
|
1558
1545
|
{
|
|
1559
1546
|
id: 'zhipu',
|
|
1547
|
+
match: ['zai-coding-cn', 'zai', 'zhipu'],
|
|
1560
1548
|
name: '🧠 智谱清言 GLM',
|
|
1561
1549
|
desc: 'GLM-5 / GLM-4.7 国内 Coding 利器',
|
|
1562
|
-
docUrl: 'https://open.bigmodel.cn/usercenter/apikeys'
|
|
1563
|
-
yaml: 'zai-coding-cn:\n displayName: 智谱 GLM\n api: openai-completions\n baseURL: https://open.bigmodel.cn/api/paas/v4\n apiKeyEnv: ZHIPU_API_KEY\n models:\n - id: glm-5-turbo\n - id: glm-4.7'
|
|
1550
|
+
docUrl: 'https://open.bigmodel.cn/usercenter/apikeys'
|
|
1564
1551
|
},
|
|
1565
1552
|
{
|
|
1566
1553
|
id: 'volc',
|
|
1554
|
+
match: ['volcengine', 'volc', 'ark'],
|
|
1567
1555
|
name: '🌋 火山方舟 Ark',
|
|
1568
1556
|
desc: '字节豆包 Doubao-1.5 多模态矩阵',
|
|
1569
|
-
docUrl: 'https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey'
|
|
1570
|
-
yaml: 'volcengine:\n displayName: 火山方舟\n api: openai-completions\n baseURL: https://ark.cn-beijing.volces.com/api/v3\n apiKeyEnv: ARK_API_KEY\n models:\n - id: doubao-1.5-pro-32k\n - id: doubao-1.5-lite-32k'
|
|
1557
|
+
docUrl: 'https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey'
|
|
1571
1558
|
},
|
|
1572
1559
|
{
|
|
1573
1560
|
id: 'siliconflow',
|
|
1561
|
+
match: ['siliconflow'],
|
|
1574
1562
|
name: '🚀 硅基流动',
|
|
1575
1563
|
desc: 'SiliconFlow 聚合开源高性价比模型',
|
|
1576
|
-
docUrl: 'https://cloud.siliconflow.cn/account/ak'
|
|
1577
|
-
yaml: 'siliconflow:\n displayName: 硅基流动\n api: openai-completions\n baseURL: https://api.siliconflow.cn/v1\n apiKeyEnv: SILICONFLOW_API_KEY\n models:\n - id: deepseek-ai/DeepSeek-V3\n - id: Qwen/Qwen2.5-72B-Instruct'
|
|
1564
|
+
docUrl: 'https://cloud.siliconflow.cn/account/ak'
|
|
1578
1565
|
},
|
|
1579
1566
|
{
|
|
1580
1567
|
id: 'openrouter',
|
|
1568
|
+
match: ['openrouter'],
|
|
1581
1569
|
name: '🌐 OpenRouter',
|
|
1582
1570
|
desc: '聚合全球 Claude / GPT / Gemini 全模型',
|
|
1583
|
-
docUrl: 'https://openrouter.ai/keys'
|
|
1584
|
-
yaml: 'openrouter:\n displayName: OpenRouter\n api: openai-completions\n baseURL: https://openrouter.ai/api/v1\n apiKeyEnv: OPENROUTER_API_KEY\n models:\n - id: anthropic/claude-3.7-sonnet\n - id: deepseek/deepseek-r1'
|
|
1571
|
+
docUrl: 'https://openrouter.ai/keys'
|
|
1585
1572
|
}
|
|
1586
1573
|
]
|
|
1587
1574
|
|
|
@@ -1621,58 +1608,52 @@ window.__ModuleLoader__.load({
|
|
|
1621
1608
|
}
|
|
1622
1609
|
|
|
1623
1610
|
/**
|
|
1624
|
-
*
|
|
1611
|
+
* 添加提供方时的匹配提示(1.6.0 起取代页脚的「热门大模型一键装配」抽屉)。
|
|
1612
|
+
*
|
|
1613
|
+
* 为什么改:抽屉常驻在模型页底部,和用户正在配哪一家毫无关系,读起来像一块广告。
|
|
1614
|
+
* 该出现的时机是「用户在添加提供方里选中了某一家」—— 宿主此时渲染草稿卡,并以
|
|
1615
|
+
* `configured: false` 派发 settings.models.provider-card(见宿主 slot-contract.d.ts)。
|
|
1616
|
+
* 于是只在这张卡上、只给匹配到的那一家一行:名称 · 推荐模型 · 获取 Key。
|
|
1617
|
+
* 不再给 YAML:草稿卡本身就是配置表单,而模板根键(minimax)与目录 id(minimax-cn)
|
|
1618
|
+
* 对不上,复制过去反而误导。没匹配到的厂商不渲染任何东西。
|
|
1619
|
+
*
|
|
1620
|
+
* @param {unknown} provider - 宿主传入的 entry 对象或 provider id 字符串。
|
|
1621
|
+
* @returns {object | undefined} 命中的预设。
|
|
1625
1622
|
*/
|
|
1626
|
-
|
|
1627
|
-
const
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
const [copied, setCopied] = React.useState(false)
|
|
1623
|
+
const presetFor = (provider) => {
|
|
1624
|
+
const id = typeof provider === 'string' ? provider : (provider && typeof provider.provider === 'string' ? provider.provider : '')
|
|
1625
|
+
return id === '' ? undefined : PRESETS.find((preset) => preset.match.includes(id))
|
|
1626
|
+
}
|
|
1631
1627
|
|
|
1628
|
+
function PresetHint(props) {
|
|
1629
|
+
const t = typeof props.t === 'function' ? props.t : fallbackT
|
|
1630
|
+
const preset = presetFor(props.provider)
|
|
1631
|
+
if (preset === undefined) return null
|
|
1632
1632
|
ensureStyle()
|
|
1633
|
+
return h('div', { className: 'dsh-llm-hub-preset-hint' },
|
|
1634
|
+
h('span', { className: 'dsh-llm-hub-preset-hint__name' }, preset.name),
|
|
1635
|
+
h('span', { className: 'dsh-llm-hub-preset-hint__desc' }, preset.desc),
|
|
1636
|
+
h('a', {
|
|
1637
|
+
href: preset.docUrl,
|
|
1638
|
+
target: '_blank',
|
|
1639
|
+
rel: 'noreferrer',
|
|
1640
|
+
className: 'dsh-llm-hub-preset-hint__link'
|
|
1641
|
+
}, t('presetsDocsBtn')))
|
|
1642
|
+
}
|
|
1633
1643
|
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
h('span', { className: 'dsh-llm-hub-presets__title' },
|
|
1648
|
-
t('presetsTitle'),
|
|
1649
|
-
h('span', { style: { fontSize: '10px', opacity: 0.6 } }, expanded ? ' ▲ 收起' : ' ▼ 展开模版')),
|
|
1650
|
-
h('span', { className: 'dsh-llm-hub-subtext' }, t('presetsSub'))),
|
|
1651
|
-
expanded ? h('div', { className: 'dsh-llm-hub-presets__grid' },
|
|
1652
|
-
PRESETS.map((p) => h('div', {
|
|
1653
|
-
key: p.id,
|
|
1654
|
-
className: 'dsh-llm-hub-presets__item',
|
|
1655
|
-
onClick: () => setSelected(selected?.id === p.id ? null : p)
|
|
1656
|
-
},
|
|
1657
|
-
h('span', { className: 'dsh-llm-hub-presets__name' }, p.name),
|
|
1658
|
-
h('span', { className: 'dsh-llm-hub-presets__desc' }, p.desc)))) : null,
|
|
1659
|
-
expanded && selected !== null ? h('div', { className: 'dsh-llm-hub-presets__detail' },
|
|
1660
|
-
h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
|
|
1661
|
-
h('span', { style: { fontWeight: '600' } }, `${selected.name} 配置模版`),
|
|
1662
|
-
h('div', { style: { display: 'flex', gap: '6px' } },
|
|
1663
|
-
h('button', {
|
|
1664
|
-
type: 'button',
|
|
1665
|
-
className: 'dsh-llm-hub-btn',
|
|
1666
|
-
onClick: (e) => copyYaml(e, selected.yaml)
|
|
1667
|
-
}, copied ? t('presetsCopied') : t('presetsCopyBtn')),
|
|
1668
|
-
h('a', {
|
|
1669
|
-
href: selected.docUrl,
|
|
1670
|
-
target: '_blank',
|
|
1671
|
-
rel: 'noreferrer',
|
|
1672
|
-
className: 'dsh-llm-hub-btn',
|
|
1673
|
-
style: { textDecoration: 'none' }
|
|
1674
|
-
}, t('presetsDocsBtn')))),
|
|
1675
|
-
h('pre', { className: 'dsh-llm-hub-presets__code' }, selected.yaml)) : null)
|
|
1644
|
+
/**
|
|
1645
|
+
* 给 provider-card 组件套上草稿态行为。直接调用原组件(而不是 h(Card)),
|
|
1646
|
+
* 保证原组件的 hooks 挂在同一个组件上、调用顺序不变 —— 草稿保存后 configured
|
|
1647
|
+
* 翻成 true,同一个组件实例继续渲染,hook 数量不能变。
|
|
1648
|
+
*
|
|
1649
|
+
* 草稿态(configured === false)只给匹配提示、丢掉原卡输出:原卡此时去查一个
|
|
1650
|
+
* 还没写进配置的 provider,必然渲染红字「llm-pi-ai 段里没有 "xxx" 这个 provider」,
|
|
1651
|
+
* 用户只是选了一下下拉框,看到的却像报错(2026-09-28 浏览器实测)。
|
|
1652
|
+
*/
|
|
1653
|
+
const withPresetHint = (Card) => (props) => {
|
|
1654
|
+
const card = Card(props)
|
|
1655
|
+
if (props.configured !== false) return card
|
|
1656
|
+
return PresetHint(props)
|
|
1676
1657
|
}
|
|
1677
1658
|
|
|
1678
1659
|
/**
|
|
@@ -2631,13 +2612,13 @@ window.__ModuleLoader__.load({
|
|
|
2631
2612
|
key: CARD_KEY,
|
|
2632
2613
|
locale: NS,
|
|
2633
2614
|
inject: () => ({ t, availability })
|
|
2634
|
-
}, BalanceCard))
|
|
2615
|
+
}, withPresetHint(BalanceCard)))
|
|
2635
2616
|
ctx.slots.inject('settings.models.provider-card', () => ctx.slots.register({
|
|
2636
2617
|
name: 'settings.models.provider-card',
|
|
2637
2618
|
key: PIAI_CARD_KEY,
|
|
2638
2619
|
locale: NS,
|
|
2639
2620
|
inject: () => ({ t, availability })
|
|
2640
|
-
}, PiAiCard))
|
|
2621
|
+
}, withPresetHint(PiAiCard)))
|
|
2641
2622
|
// settings.models.footer 的契约是 kind:'list'(见宿主 dsh-client-ui-settings-models
|
|
2642
2623
|
// 的 children 声明),list 类 slot 注册**必须带 id** —— 参照宿主自己的
|
|
2643
2624
|
// settings.onboarding 注册(id:'welcome-notice', order:-100)。
|
|
@@ -2651,13 +2632,6 @@ window.__ModuleLoader__.load({
|
|
|
2651
2632
|
locale: NS,
|
|
2652
2633
|
inject: () => ({ t, availability })
|
|
2653
2634
|
}, HeroOverviewCard))
|
|
2654
|
-
ctx.slots.inject('settings.models.footer', () => ctx.slots.register({
|
|
2655
|
-
name: 'settings.models.footer',
|
|
2656
|
-
id: 'dsh-llm-hub-presets',
|
|
2657
|
-
order: 65,
|
|
2658
|
-
locale: NS,
|
|
2659
|
-
inject: () => ({ t })
|
|
2660
|
-
}, QuickPresetsCard))
|
|
2661
2635
|
ctx.slots.inject('settings.models.footer', () => ctx.slots.register({
|
|
2662
2636
|
name: 'settings.models.footer',
|
|
2663
2637
|
id: 'dsh-llm-hub-health',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-plugins/dsh-llm-hub",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"description": "DSH 模型管理层:网关可达性探测、模型目录拉取、DeepSeek + MiniMax/智谱/Moonshot/StepFun 余额与配额、本月用量统计、余额预警、Provider 健康看板,再把本机装好的 codex / claude / agy 注册成子代理(装了才出现)。零运行时依赖,不改动 DSH 安装。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|