dsh-model-groups 0.3.6 → 0.3.8

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/README.md CHANGED
@@ -1,208 +1,89 @@
1
- # DSH Model Groups
1
+ # DSH Model Groups · 模型分组
2
2
 
3
- 为 DeepSeek Harness(DSH)提供分层模型选择与多密钥配置管理。
3
+ **在 DeepSeek Harness(DSH)网页端,按供应商、密钥配置和模型逐级选择。** 如果同一家供应商有多把 API 密钥,可以为每把密钥分别设置模型列表和 API 协议。即使模型名称一样,也能选中你要用的那份配置。插件不会自动换密钥或切换供应商。
4
4
 
5
- 插件在 DSH 网页界面中提供“供应商 → 密钥配置 → 模型”三级模型菜单,并支持在同一供应商下维护多份独立的密钥与模型列表。
5
+ 支持 **DSH `0.2.2-rc.1`**、**Node.js 22 或更新版本**。本插件适用于 DSH 网页端,不替换原生 App 的模型菜单。
6
6
 
7
- ## 核心功能
7
+ ## 安装
8
8
 
9
- - **三级分层选择**:在会话模型菜单中按“供应商 → 密钥配置 → 模型”浏览和选择模型。
10
- - **同供应商多密钥管理**:同一供应商共享 Provider ID 与 API 地址,每份密钥配置独立设置名称、API 密钥、模型列表及 API 协议;未指定协议的旧配置继续跟随供应商,不需迁移或重建密钥。
11
- - **每组独立协议**:支持 OpenAI Chat Completions、OpenAI Responses 与 Anthropic Messages,同一个模型 ID 也可在不同密钥组走不同协议;只按显式选择发送,不按模型名称猜测。
12
- - **手动选择,不自动切换**:不同密钥配置可使用相同的模型 ID;每次调用严格使用所选配置的密钥,不自动轮换密钥,也不偷偷切换到其他配置或服务。
13
- - **多种浏览与搜索方式**:支持“原地折叠”与“侧边面板”两种展示模式,支持名称搜索、展开全部与收起全部,并自动记住各级折叠状态(搜索时临时展开匹配项)。
14
- - **配置项折叠编辑**:在模型设置页中,已保存的密钥配置默认折叠,仅保留配置名称与原密钥输入栏(继续沿用宿主原有的密钥遮罩与存储机制,不直接显示已保存密钥明文);点击“展开详情”可编辑模型列表,新建项与校验未通过项保持展开,收起详情不会丢失未保存草稿。
15
- - **网页端补丁维护**:在“设置 → 模型分组”页面手动启用、更新或关闭多密钥补丁,并提供“关闭并卸载插件”操作及脱敏诊断复制。
16
-
17
- ## 支持环境
18
-
19
- - **DeepSeek Harness**:`0.2.2-rc.1`
20
- - **Node.js**:`>=22`
21
- - **适用界面**:DSH 网页界面(不影响非网页端的原生模型菜单)
22
- - **文件权限**:DSH 安装目录需可写,且目标程序文件需符合受支持版本的原始或已知补丁哈希
23
-
24
- ## 安装与首次启用
25
-
26
- 插件分为**安装插件包**与**启用多密钥补丁**两步。加载插件本身不会自动修改宿主文件;未启用多密钥补丁时,仍可正常使用分层模型菜单浏览普通单密钥模型。
27
-
28
- ### 1. 安装插件
29
-
30
- 在 DSH 运行环境中执行以下命令安装正式版 npm 包:
9
+ 在运行 DSH 的环境里执行(如果你使用的 DSH 配置不是 `web`,把命令中的 `web` 换成你的配置名):
31
10
 
32
11
  ```bash
33
- dsh plugin --profile web add dsh-model-groups
12
+ dsh plugin --profile web add dsh-model-groups@latest --registry=https://registry.npmjs.org/
34
13
  ```
35
14
 
36
- 也可以指定具体版本号安装:
37
-
38
- ```bash
39
- dsh plugin --profile web add dsh-model-groups@0.3.6
40
- ```
41
-
42
- > 备用方式:若当前环境无法访问 npm 源,可改用对应 GitHub Release 发布的 `.tgz` 包地址进行安装。
43
-
44
- 安装完成后,**重启原 DSH 引擎并刷新网页**,使插件加载生效。
15
+ 如果 npm 尚未同步到你需要的版本,可以把 `dsh-model-groups@latest` 换成 [GitHub 0.3.8 正式版安装包](https://github.com/betsunninda9-lgtm/dsh-model-groups/releases/download/v0.3.8/dsh-model-groups-0.3.8.tgz) 的下载地址。安装后,**重启正在使用的 DSH 引擎,再刷新网页**。只想给现有模型分组?装好就可以用,不需要启用多密钥。
45
16
 
46
- ### 2. 启用多密钥补丁
17
+ ## 在对话中选模型
47
18
 
48
- 如需使用同一供应商下的多密钥配置功能,请在网页界面完成启用:
19
+ 打开输入框旁的模型菜单,展开供应商,选择模型。启用了多密钥的供应商会多一级 **密钥配置**。你可以搜索模型或配置名称、展开或收起全部分组,也可以在菜单底部切换 **侧边面板** 或 **原地折叠**。清空搜索后会恢复原来的展开状态。
49
20
 
50
- 1. 打开 **设置 → 模型分组**。
51
- 2. 查看“当前状态”卡片,确认无冲突或活动任务限制。
52
- 3. 在“多密钥操作”区域点击 **启用多密钥**,阅读提示后点击 **确认执行**。
53
- 4. 页面提示已实际修改宿主文件后,**重启原 DSH 引擎并刷新网页**。
21
+ 开启多密钥前就已选中普通模型的会话会保留原选择,菜单中标为 **原单密钥(兼容旧会话)**。
54
22
 
55
- > **说明**:启用操作会校验并备份受支持的 5 个宿主文件(备份保存在 `DSH_HOME/dsh-model-groups/<安装目录指纹>/backups`),再写入多密钥补丁。若遇到未知版本或已被其他修改覆盖的文件,插件会拒绝写入,不会强制覆盖。
56
-
57
- ## 日常使用
58
-
59
- ### 1. 配置多密钥与模型
60
-
61
- 1. 打开 **设置 → 模型**,新增或编辑自定义模型供应商。
62
- 2. 在 **公共设置** 中填写共享的显示名称、API 地址与协议。
63
- 3. 开启 **多密钥配置** 开关。
64
- 4. 点击 **添加密钥配置**(首次开启会自动生成一项),为每份配置填写 **配置名称**、**API 密钥** 并配置模型列表:
65
- - 已保存的密钥配置默认折叠;如需修改配置名称、增删模型或移除该配置,点击 **展开详情**,完成后可点击 **收起详情**。
66
- - 在 **分组 API 协议** 中选择“跟随供应商”或该中转站支持的协议。供应商地址仍为共享地址;不自动按模型名切换协议。协议选项、模型获取与请求发送均按当前密钥组生效。
67
- - 已配置密钥的输入栏留空即可保留原密钥;输入新密钥会替换对应凭据引用。
68
- 5. 点击底部操作栏的 **应用**(或新建时的保存按钮)提交修改。保存成功后,已确认无误的密钥配置会自动折叠。
69
-
70
- 如需在单个供应商内关闭 **多密钥配置** 开关:
71
- - 若当前有已输入但尚未保存的 API 密钥,需先点击“应用”保存或清空输入,才能关闭开关。
72
- - 关闭开关并应用后,该供应商恢复使用原有的单密钥配置;已保存的多密钥配置项和密钥凭据不会被删除。
73
-
74
- ### 2. 在会话中选择模型
75
-
76
- 打开对话输入框旁的模型菜单,按层级展开并选择目标模型:
77
-
78
- ```text
79
- 示例供应商 A
80
- ├─ 密钥配置 A
81
- │ └─ deepseek-chat
82
- └─ 密钥配置 B
83
- └─ deepseek-chat
84
- 示例供应商 B
85
- └─ gpt-4o
86
- ```
87
-
88
- - **展示模式切换**:在菜单底部可切换 **侧边面板**(多级悬浮面板,窄屏下自动调整各级宽度,名称过长时截断显示)与 **原地折叠**(单列表内树状展开)。
89
- - **快捷操作**:菜单顶部工具栏支持搜索模型或配置名称,以及一键 **展开全部** / **收起全部**。
90
- - **旧会话兼容**:开启多密钥前已选中原单密钥模型的会话会保留原选择,并在对应供应商下显示为“原单密钥(兼容旧会话)”;插件不会自动合并已有供应商或自动迁移旧会话的模型选择。
91
-
92
- ## 更新
23
+ ## 为同一家供应商添加多把密钥
93
24
 
94
- 1. 执行安装命令更新插件包:
95
- ```bash
96
- dsh plugin --profile web add dsh-model-groups@latest
97
- ```
98
- 2. 更新插件包后,先 **重启原 DSH 引擎并刷新网页**。
99
- 3. 打开 **设置 → 模型分组** 查看补丁状态:
100
- - 若多密钥操作按钮显示为 **更新多密钥补丁**(提示“多密钥补丁有更新可用”),请点击该按钮并 **确认执行**,完成后再次 **重启原 DSH 引擎并刷新网页**。
101
- - 若状态显示“多密钥已启用(磁盘状态)”且无更新提示,说明当前宿主补丁已是最新兼容版本,无需重复重打补丁。
25
+ ### 启用多密钥
102
26
 
103
- ### 很老的版本能直接更新吗?
27
+ 1. 在网页打开 **设置 → 模型分组**,点击 **启用多密钥 → 确认执行**。
28
+ 2. 等页面提示已更新 DSH 文件后,**重启 DSH 引擎,再刷新网页**。只刷新网页不够。
104
29
 
105
- 可以直接更新**已识别的历史补丁**,不必逐版安装、先关闭多密钥或先卸载。正式版保留历史补丁的精确逆向配方:先验证旧文件可还原为它自己的原版,再生成该构建对应的最新补丁;5 个文件全部通过后才备份并写入。不按插件版本号猜测文件内容,也不会拿另一设备的构建覆盖当前构建。
30
+ 这一步会检查并备份 DSH 程序文件,再安装补丁。安装目录必须可写;如果文件版本无法识别,插件会停止,不会强行覆盖。
106
31
 
107
- | 当前情况 | 最新版处理 |
108
- | --- | --- |
109
- | 未打补丁的受支持原版 | 手动确认“启用多密钥” |
110
- | 已识别的旧补丁,包括旧自动应用版本 | 直接提示“更新多密钥补丁”,不重建配置、密钥 ID 或会话 |
111
- | 补丁已是本构建最新版 | 只检查,不重复写入 |
112
- | 仅识别旧补丁、缺少验证过的新版配方 | 整批阻止更新,保留已支持的检查与还原能力;反馈诊断,不建议先还原 |
113
- | 未知哈希、缺文件、不同宿主版本或不安全路径 | 整批停止,不覆盖;详情显示固定文件标识、版本及程序哈希 |
114
- | 网页与插件后端版本不一致 | 禁止维护,先重启原引擎并刷新网页,再重新确认 |
32
+ ### 添加密钥配置
115
33
 
116
- 旧版中有自动应用补丁的版本(也包括 `0.3.5-beta.1`~`beta.3`);最新版加载插件**不会自动改宿主**。即使安装器热重载了插件,或页面显示磁盘文件齐全,也不能证明旧进程已加载新宿主模块,仍应按上述顺序重启原引擎和刷新原网页。
34
+ 1. 打开 **设置 → 模型**,新增或编辑一个支持多密钥的供应商。在 **公共设置** 中填写共享的 API 地址和默认协议。
35
+ 2. 打开 **多密钥配置**,为第一项填写配置名称、API 密钥和模型列表;有更多密钥就点击 **添加密钥配置**。
36
+ 3. 如果某把密钥需要不同的 API 协议,在 **分组 API 协议** 中选择;不确定时保留 **跟随供应商**,并以供应商说明为准。可选协议包括 OpenAI Chat Completions、OpenAI Responses 和 Anthropic Messages。API 地址写中转站给你的那个(结尾带不带 `/v1` 都可以):Anthropic 这一项会自动去掉结尾的 `/v1`,避免同一段路径出现两次。
37
+ 4. 点击 **应用**(新建时点击 **创建提供商**)。已保存的配置默认收起;要修改模型列表,点击 **展开详情**。编辑时将已保存的密钥输入框留空,原密钥会保留。
117
38
 
118
- 从 GitHub 测试分支安装的用户,请在**原 profile** 执行上面的 npm `@latest` 命令切回正式渠道,再按本节复查;分支来源不会因正式发版或删除测试分支自动迁移。若实际使用的 profile 不是 `web`,请使用原 profile 名,不另建一份插件。
39
+ ![展开后的密钥配置:分别填写 API 密钥、配置名称和协议,并可添加模型](docs/images/key-configuration.webp)
119
40
 
120
- 若更新后仍有冲突:先复制脱敏诊断,保留现场;**不要先卸载、还原补丁、删除配置或重建密钥**。需要适配时,只提供详情标记的程序文件,不提供凭据、配置或聊天记录。旧配置未填写分组协议时继续跟随供应商;显式切换协议也不保证上游一定返回缓存命中,缓存统计以实际 API usage 为准。
41
+ *展开一项密钥配置后,可以设置该项的 API 协议和模型列表。截图中的内部密钥引用已遮盖。*
121
42
 
122
- > **升级 DSH 主程序前请注意**:本插件补丁仅适配受支持的 DSH 版本(当前为 `0.2.2-rc.1`)。升级 DSH 前请先确认插件已完成对应版本适配,或在理解“关闭与卸载后的影响”并处理多密钥引用后,再关闭补丁;不要为解决插件更新冲突而盲目还原。
43
+ <details>
44
+ <summary>查看开关位置、折叠效果和添加按钮</summary>
123
45
 
124
- ## 关闭与卸载
46
+ **找到开关**:新建供应商时,选择 **自定义模型 API**,在 **API 协议** 下方打开 **多密钥配置**。
125
47
 
126
- **请勿直接从普通插件列表或命令行卸载仍启用补丁的插件。** 普通卸载只会移除插件包本身,不会还原已修改的宿主文件。
48
+ ![自定义模型 API 表单中,多密钥配置开关位于 API 协议下方](docs/images/provider-multi-key-toggle.webp)
127
49
 
128
- ### 推荐方式:通过设置页关闭或卸载
50
+ **查看多份配置**:点击 **展开详情** 编辑对应配置,不必逐个展开其他配置。
129
51
 
130
- 维护前请先停止正在运行的对话或任务,并保存其他设置页的草稿:
52
+ ![两份密钥配置均已折叠,各自保留独立的展开入口](docs/images/collapsed-key-configurations.webp)
131
53
 
132
- 1. 打开 **设置 → 模型分组**。
133
- 2. 根据需要选择操作并点击 **确认执行**:
134
- - **仅关闭多密钥(保留插件)**:点击 **关闭多密钥**。宿主文件将恢复为原版,插件本身保留,可继续作为普通模型的分组选择器使用。
135
- - **还原补丁并卸载插件**:点击 **关闭并卸载插件**。系统会先校验并恢复宿主原版文件,验证成功后再移除插件包,并清理本插件在当前浏览器的两个显示偏好项(`dsh:model-groups:v1` 与 `dsh:model-groups:mode`)。
136
- 3. 操作完成并提示需要重启后,**重启原 DSH 引擎并刷新网页**。
54
+ **继续添加**:在配置列表下方点击 **添加密钥配置**。每份密钥配置至少需要一个模型。
137
55
 
138
- ### 关闭与卸载后的影响说明
56
+ ![添加密钥配置按钮及每份配置至少需要一个模型的提示](docs/images/add-key-configuration.webp)
139
57
 
140
- - **不删除用户数据**:关闭多密钥或卸载插件不会删除已保存的 API 密钥、供应商配置、聊天历史或文件备份。
141
- - **不自动切换或清理配置**:插件不会自动将使用多密钥模型的会话、默认模型或子代理配置切换回普通模型,也不会自动清理配置文件中的 `multiKey` 与 `keyEntries` 字段。
142
- - **后续使用限制**:还原宿主文件后,原版 DSH 不支持识别 `@dsh-key/` 多密钥模型路由及 `multiKey` / `keyEntries` 配置字段。仍引用多密钥模型的旧会话在手动改选普通模型前将无法直接继续请求;残留的多密钥配置字段也可能影响原版引擎的配置校验或重启。建议在关闭或卸载前,先将相关会话切换回普通单密钥模型,并在需要时关闭对应供应商的多密钥开关或清理相关配置字段。
58
+ </details>
143
59
 
144
- ### 命令行备用还原方式
60
+ 如果只想让某个供应商恢复使用单密钥,先保存或清空尚未保存的密钥输入,再关掉该供应商的 **多密钥配置** 并点击 **应用**。已保存的多密钥配置不会被删除。
145
61
 
146
- 若已通过命令行移除插件或无法进入网页设置页,可在停止原 DSH 服务后,使用保留的插件目录执行脚本恢复宿主文件:
147
-
148
- ```bash
149
- node scripts/native-patches.mjs --dsh-root /opt/dsh --revert
150
- ```
151
-
152
- 请将 `/opt/dsh` 替换为实际的 DSH 安装目录。完成后重新启动原 DSH 服务并刷新网页。
153
-
154
- ## 常见问题
155
-
156
- ### 1. 为什么在“设置 → 模型”里看不到“多密钥配置”开关?
157
-
158
- - 请先到 **设置 → 模型分组** 确认是否已点击 **启用多密钥**。安装插件后默认不会自动打补丁。
159
- - 若已点击“启用多密钥”,请确认操作完成后已经 **重启原 DSH 引擎** 并 **刷新网页**。
160
- - “多密钥配置”仅适用于自定义或已声明的 `pi-ai` 供应商编辑卡片,仅输入凭据的简化卡片不显示该开关。
161
-
162
- ### 2. “刷新检查”、“刷新网页”和“重启引擎”有什么区别?
163
-
164
- - **刷新检查**(位于“设置 → 模型分组”):仅只读检查磁盘上的宿主文件状态与依赖提醒,不会修改任何文件,也不意味着需要重启引擎。
165
- - **刷新网页**(浏览器刷新):重新加载前端网页资源,使前端界面与当前引擎状态同步。
166
- - **重启原 DSH 引擎**:重启运行中的 DSH 后端服务进程。更新插件包或遇到网页/后端版本不一致时,应先重启并刷新以加载同一版维护逻辑;执行“启用多密钥”、“更新多密钥补丁”、“关闭多密钥”或“关闭并卸载插件”并实际修改宿主文件后,还必须再次重启以加载新宿主模块。
167
-
168
- ### 3. 为什么页面显示“多密钥已启用(磁盘状态)”,但提示运行时状态未知?
169
-
170
- 磁盘校验只能确认安装目录中的文件已写入补丁,无法直接证明当前运行中的 Node.js 进程是在打补丁前还是打补丁后启动的。只要在修改补丁后重启过一次原引擎并刷新了网页,即可正常使用。
171
-
172
- ### 4. 如何进行只读安装诊断或反馈问题?
173
-
174
- 可在网页 **设置 → 模型分组** 底部展开 **检查详情与脱敏诊断**,点击 **复制脱敏诊断**。仅包含固定状态、错误码、插件/宿主版本及程序文件 SHA-256,不含文件路径、程序正文、密钥、配置或聊天记录。
175
-
176
- 也可在插件目录运行只读命令行诊断:
62
+ ## 更新
177
63
 
178
- ```bash
179
- node scripts/doctor.mjs --dsh-root /opt/dsh --json
180
- ```
64
+ 1. 在原 DSH 配置中用目标正式版本重新执行安装命令,**不需要先卸载**。重启 DSH 引擎并刷新网页。
65
+ 2. 打开 **设置 → 模型分组**。如果出现 **更新多密钥补丁**,点击并确认;更新完成后,再重启引擎并刷新网页。没有更新提示就不用重复操作。
181
66
 
182
- (请将 `/opt/dsh` 替换为实际 DSH 安装目录。)
67
+ 已识别且受支持的旧补丁可以直接更新,不用逐版安装。若提示文件冲突或不支持更新,请先复制诊断反馈;不要先卸载、还原补丁或删除配置。升级 **DSH 本身**前,请先确认目标 DSH 版本是否受插件支持。
183
68
 
184
- 若因前次维护异常中断留下锁目录 `DSH_HOME/dsh-model-groups/<安装目录指纹>/patch.lock`,请先确认没有任何正在运行的补丁维护进程后再人工清理,切勿并发重试。
69
+ ## 关闭或卸载
185
70
 
186
- ## 开发与许可证
71
+ **如果已启用多密钥,不要直接从插件列表或命令行卸载。** 那样只会移除插件,不会还原 DSH 文件。
187
72
 
188
- 常用开发与检查命令:
73
+ 1. 保存设置草稿、停止运行中的任务,并把仍使用多密钥模型的会话、默认模型及子代理切回普通模型。建议先在各供应商设置里关闭 **多密钥配置** 并应用。
74
+ 2. 打开 **设置 → 模型分组**,选择 **关闭多密钥**(保留模型分组插件),或 **关闭并卸载插件**(先还原 DSH 文件,再卸载),然后确认。
75
+ 3. 页面提示需要重启时,**重启 DSH 引擎并刷新网页**。
189
76
 
190
- ```bash
191
- npm run build
192
- npm test
193
- npm run check:build
194
- ```
77
+ ![模型分组设置页:多密钥已启用,可以关闭多密钥或关闭并卸载插件](docs/images/multi-key-management.webp)
195
78
 
196
- 设置 `DSH_ROOT` 可启用依赖对应 DSH 程序文件的只读回归测试;可用 `PI_AI_SOURCES` 传入其他已知原始/旧补丁程序的路径(按系统路径分隔符分开),覆盖三种构建。第三种另有从真实完整文件核验的最小 delta 夹具,重建后仍检查完整 SHA-256;不包含用户配置或凭据。真实安装/更新/还原集成测试仅在临时副本中写入,配置和凭据使用合成哨兵。源码包含层级、选择器交互、协议探测、删除确认、面板布局、补丁安装与恢复,以及真实 pi-ai 登录/令牌刷新取消行为的离线测试。
79
+ *「设置 → 模型分组」在多密钥已启用时的界面(0.3.6)。按钮会随当前状态变化。*
197
80
 
198
- 宿主设置页属于 `@deepseek-ai/dsh-client-ui-settings-models`,不是插件自己的 `lib/client.js`。`npm run build` 仅构建插件,不能替代生成宿主补丁。修改生成器后用明确的未打补丁宿主源码生成/校验(源文件只读,哈希必须匹配):
81
+ 关闭或卸载不会删除 API 密钥、供应商配置、聊天历史或备份,也不会替你切换模型。还原后,旧会话里的多密钥模型可能无法继续使用;原版 DSH 也可能无法读取残留的多密钥设置。遇到这种情况请先反馈诊断,不要直接删除密钥或整个配置。
199
82
 
200
- ```bash
201
- node scripts/settings-models-collapse.mjs --source /path/to/pristine-client.js
202
- node scripts/settings-models-collapse.mjs --source /path/to/pristine-client.js --check
203
- DSH_ROOT=/opt/dsh npm test
204
- ```
83
+ ## 遇到问题
205
84
 
206
- 生成器不会隐式读取或修改已安装宿主。分发包包含预先验证的 `native/*.patch.json`,维护页显式确认后才应用。测试夹具与开发生成器不参与运行时补丁应用。
85
+ - **找不到多密钥开关**:先确认已在 **设置 → 模型分组** 启用,并已重启引擎、刷新网页。只有支持多密钥的供应商编辑页会显示此开关,只能填写凭据的简化页面不会显示。
86
+ - **不确定是否已经生效**:设置页的 **刷新检查** 只检查文件,不会修改文件或重启引擎。若刚启用、更新或关闭多密钥,请重启引擎再刷新网页。
87
+ - **无法启用、更新或卸载**:打开 **设置 → 模型分组 → 检查详情与脱敏诊断**,点击 **复制脱敏诊断**,附在 [GitHub Issue](https://github.com/betsunninda9-lgtm/dsh-model-groups/issues) 中。该诊断不包含 API 密钥、文件路径、配置正文或聊天记录。
207
88
 
208
- 本项目基于 [MIT 许可证](LICENSE) 开源。部分模型选择器代码改编自 DeepSeek Harness,保留原始版权声明。
89
+ 开发、测试和命令行恢复说明见 [维护指南](docs/maintenance.md)。项目基于 [MIT 许可证](LICENSE) 开源。部分模型选择器代码改编自 DeepSeek Harness,保留原始版权声明。
@@ -0,0 +1,47 @@
1
+ # 开发与维护指南
2
+
3
+ 日常安装和使用见 [README](../README.md)。
4
+
5
+ ## 本地验证
6
+
7
+ 需要 Node.js 22 或更新版本。修改网页端源码后,重新生成并提交客户端产物:
8
+
9
+ ```bash
10
+ npm run build
11
+ npm test
12
+ npm run check:build
13
+ ```
14
+
15
+ `npm run check:build` 只比对产物,不会覆盖它。历史版本升级测试读取 Git 历史,建议使用完整克隆。部分集成测试需要指定受支持的 DSH 安装目录;未指定时会跳过相应场景。需要覆盖其他已知构建时,可通过 `PI_AI_SOURCES` 传入只包含程序代码的文件,多个路径用系统路径分隔符隔开。集成测试在临时副本中写入,不要提供用户配置或凭据。
16
+
17
+ ```bash
18
+ DSH_ROOT=/path/to/dsh npm test
19
+ ```
20
+
21
+ ## 两类网页代码
22
+
23
+ - 插件自己的网页界面位于 `src/`,由 `npm run build` 生成 `lib/client.js`。
24
+ - DSH 的「设置 → 模型」由宿主提供,发布包中的 `native/*.patch.json` 为已验证的程序文件补丁,不随客户端构建重新生成。若修改模型设置页补丁生成器,必须提供哈希匹配的原始程序文件,并验证相关构建的启用、升级及还原,不要直接编辑分发补丁或用其他构建的文件替换。
25
+
26
+ ```bash
27
+ node scripts/settings-models-collapse.mjs --source /path/to/pristine-client.js
28
+ node scripts/settings-models-collapse.mjs --source /path/to/pristine-client.js --check
29
+ ```
30
+
31
+ ## 诊断与恢复
32
+
33
+ 只读诊断(请替换实际安装路径):
34
+
35
+ ```bash
36
+ node scripts/doctor.mjs --dsh-root /path/to/dsh --json
37
+ ```
38
+
39
+ 遇到文件校验冲突或无法更新时,先保留现场并收集脱敏诊断。不要强制覆盖程序文件、删除配置或重建密钥。若此前从测试分支安装,可在原 DSH 配置中使用 README 的正式版本命令直接替换插件包,再按更新流程检查补丁。
40
+
41
+ 若插件已误卸载或无法打开网页设置,在处理多密钥模型引用后,先停止正在使用的 DSH 引擎,再从保留的插件目录执行:
42
+
43
+ ```bash
44
+ node scripts/native-patches.mjs --dsh-root /path/to/dsh --revert
45
+ ```
46
+
47
+ 确认恢复完成后,重新启动同一个 DSH 引擎并刷新网页。备份存放在 `DSH_HOME/dsh-model-groups/<安装目录指纹>/backups`。若因异常中断遗留同目录下的 `patch.lock`,请先确认没有补丁维护进程正在运行,切勿并发重试。原版 DSH 可能无法识别 `@dsh-key/` 路由以及 `multiKey`、`keyEntries` 等设置;恢复前请按 README 处理相关模型引用和配置,避免影响启动。
package/lib/client.js CHANGED
@@ -1270,7 +1270,7 @@ function installSettingsPageStyles() {
1270
1270
  document.head.appendChild(style);
1271
1271
  }
1272
1272
 
1273
- const MODEL_GROUPS_CLIENT_VERSION = "0.3.6";
1273
+ const MODEL_GROUPS_CLIENT_VERSION = "0.3.8";
1274
1274
  // Public program metadata only. Never include paths, source text, configuration,
1275
1275
  // credentials, environment variables, or arbitrary exception messages.
1276
1276
  const PATCH_IDS = ['pi-ai.patch.json', 'settings-models.patch.json', 'llm-typert.host.patch.json', 'llm-typert.remote-client.patch.json', 'api-remotes.patch.json'];
@@ -1364,8 +1364,8 @@ function maintenanceBlockerText(blocker) {
1364
1364
  inspection_unknown: '无法确认运行状态,请先停止任务并使用安装诊断排查。',
1365
1365
  profile_unknown: '无法确认当前配置档,不会执行维护。',
1366
1366
  cross_profile_bundle: '其他配置档也在使用此插件,请先处理跨配置档依赖。',
1367
- alias_dependency: '仍有会话或配置引用多密钥模型,请先切换为普通模型再检查;本预览不会自动转换。',
1368
- key_config_dependency: '仍有多密钥配置依赖:请先禁用 multiKey 并清理 keyEntries 配置;已保存的密钥会保留。本预览不会自动转换。',
1367
+ alias_dependency: '仍有会话或设置在使用多密钥模型。请先切换为普通模型;插件不会自动转换。',
1368
+ key_config_dependency: '仍有供应商启用了多密钥。请先在「设置 → 模型」中关闭对应开关并保存;已保存的密钥会保留,配置不会自动转换。',
1369
1369
  expression_unknown: '存在无法安全判断的配置表达式,请先人工检查配置。',
1370
1370
  other_process: '其他引擎进程可能正在使用补丁,请先停止相关进程。',
1371
1371
  };
@@ -1508,15 +1508,15 @@ function ModelGroupsSettingsPage() {
1508
1508
  catch { setCopyStatus('无法复制,请检查浏览器剪贴板权限。'); }
1509
1509
  };
1510
1510
  return h('section', { className: 'mg-maintenance', 'aria-label': '模型分组设置', 'aria-busy': state.busy },
1511
- h('h2', null, '模型分组 · 多密钥管理'),
1512
- h('p', null, '选择操作,再确认一次即可。不会调用 AI,不会显示或删除 API 密钥。'),
1513
- snapshot?.pluginVersion && h('p', { className: 'mg-maintenance-help' }, `插件后端 ${snapshot.pluginVersion} · 宿主 ${snapshot.compatibility?.hostVersion ?? '版本未确认'}`),
1511
+ h('h2', null, '多密钥管理'),
1512
+ h('p', null, '在这里启用、更新或关闭多密钥。如果只想按供应商浏览模型,无需启用多密钥。'),
1513
+ snapshot?.pluginVersion && h('p', { className: 'mg-maintenance-help' }, `插件 ${snapshot.pluginVersion} · DSH ${snapshot.compatibility?.hostVersion ?? '版本未确认'}`),
1514
1514
  h('section', { className: 'mg-maintenance-card', 'aria-label': '当前状态' },
1515
1515
  h('div', { className: 'mg-maintenance-row' }, h('h3', null, '当前状态'), h('button', { type: 'button', disabled: state.busy, onClick: refresh }, state.busy ? '处理中…' : '刷新检查')),
1516
1516
  h('p', { role: 'status', 'aria-live': 'polite', className: 'mg-maintenance-help' }, state.busy ? '正在检查或执行维护,请勿关闭或重复操作。' : snapshot ? statusLabel : '尚无可验证状态,请刷新检查。'),
1517
1517
  state.error && h('p', { role: 'alert', className: 'mg-maintenance-error' }, state.error),
1518
- state.patchedWarning && h('p', { role: 'alert', className: 'mg-maintenance-error' }, '警告:从普通插件列表卸载只移除插件,仍会留下宿主补丁,可能造成升级、文件冲突及旧多密钥模型依赖问题。请使用这里的“关闭并卸载插件”。'),
1519
- snapshot?.restartRequired && h('p', { role: 'status' }, '本进程已实际修改宿主文件,需要重启原引擎并刷新;页面刷新或插件重载不等于进程重启。'),
1518
+ state.patchedWarning && h('p', { role: 'alert', className: 'mg-maintenance-error' }, '从普通插件列表卸载只移除插件,不会还原 DSH 文件。需要卸载时,请使用此页的「关闭并卸载插件」。'),
1519
+ snapshot?.restartRequired && h('p', { role: 'status' }, 'DSH 程序文件已更新,需要重启 DSH 引擎,再刷新网页。只刷新网页不会生效。'),
1520
1520
  compatibilityGuidance(snapshot?.compatibility) && h('p', { role: 'status', className: 'mg-maintenance-help' }, compatibilityGuidance(snapshot.compatibility)),
1521
1521
  updatesAvailable && h('p', { role: 'status' }, '多密钥补丁有更新可用;确认后将备份、校验并更新已识别的旧补丁。'),
1522
1522
  snapshot?.phase === 'removed' && !snapshot.versionMismatch && h('p', { role: 'status' }, '卸载已确认:仅清理本插件的两个浏览器显示偏好,密钥、历史和备份均保留。'),
@@ -1529,13 +1529,16 @@ function ModelGroupsSettingsPage() {
1529
1529
  !anyAllowed && h('p', null, '请刷新检查或处理上方操作限制。检查提醒本身不会禁用按钮。'),
1530
1530
  pending && h('div', { role: 'dialog', 'aria-labelledby': confirmationId, 'aria-describedby': `${confirmationId}-help`, className: 'mg-maintenance-dialog' },
1531
1531
  h('h3', { id: confirmationId }, `确认${actions.find(([action]) => action === pending)[1]}?`),
1532
- h('p', { id: `${confirmationId}-help` }, pending === 'apply' ? '将备份、校验并修改宿主文件以启用多密钥。不会自动换服务或模型。请保存草稿、停止任务,完成后重启原引擎。' : '将校验并恢复宿主原版,关闭多密钥。密钥、配置和历史保留,不自动换服务或模型;旧多密钥选择和配置可能影响后续使用或重启。请保存草稿、停止任务,完成后重启原引擎。'),
1533
- h('p', null, '请先停止所有任务。部分使用情况未能检查不等于安全;检查提醒不会替代您的判断。'),
1534
- pending === 'restore-and-uninstall' && h('p', null, '确认原版恢复成功后才卸载插件;只有确认卸载完成才清理本插件的两个浏览器显示偏好。连接中断不代表成功。'),
1532
+ h('p', { id: `${confirmationId}-help` }, pending === 'apply'
1533
+ ? `插件会检查并备份 DSH 程序文件,再${updatesAvailable ? '更新多密钥补丁' : '启用多密钥'}。不会自动切换模型。`
1534
+ : '插件会还原 DSH 程序文件,保留密钥、配置和聊天记录。请先将仍使用多密钥的会话和默认模型改为普通模型;残留的多密钥配置可能影响 DSH 启动。'),
1535
+ h('p', null, '请先保存草稿并停止所有任务。完成后按提示重启 DSH 引擎,再刷新网页。'),
1536
+ snapshot?.warnings.length > 0 && h('p', null, '部分使用情况无法检查,请先阅读页面中的检查详情。'),
1537
+ pending === 'restore-and-uninstall' && h('p', null, '还原成功后才会卸载插件。确认卸载后会清除本浏览器中的模型菜单显示偏好;连接中断不代表卸载成功。'),
1535
1538
  h('div', { className: 'mg-maintenance-actions' }, h('button', { type: 'button', onClick: () => setPending(null) }, '取消'), h('button', { type: 'button', disabled: state.busy || !maintenanceCanAction(snapshot, pending), onClick: confirm }, '确认执行')))),
1536
1539
  h('details', { className: 'mg-maintenance-card' },
1537
1540
  h('summary', null, '检查详情与脱敏诊断'),
1538
- h('p', null, '这里只验证磁盘和安全权限,运行时是否已切换未知。每次确认后会重新检查;状态变化需重新确认。未知文件不会强制覆盖,检查不完整仅提醒;操作仍以各自安全权限为准。'),
1541
+ h('p', null, '这里能检查 DSH 文件,但无法确认正在运行的引擎是否已加载更新。确认操作后会再次检查;如果状态变化,需要重新确认。无法识别的文件不会被覆盖。'),
1539
1542
  snapshot?.warnings.length > 0 && h('ul', null, ...snapshot.warnings.map((warning, index) => h('li', { key: index }, maintenanceWarningText(warning)))),
1540
1543
  snapshot && h('ul', null, ...snapshot.patches.map((patch, index) => h('li', { key: index }, `宿主文件 ${index + 1}:${patchLabels[patch.state]}${patch.applySupported === false ? '(此构建不支持新版补丁)' : patch.updateAvailable ? '(更新可用)' : ''}`))),
1541
1544
  snapshot?.compatibility && h('ul', null, ...snapshot.compatibility.files.map(item => h('li', { key: item.id }, `${item.id} · ${item.installedVersion ?? '版本未知'} · ${item.code} · SHA-256 ${item.observedSha256 ?? '不可读取'}`))),
@@ -1567,8 +1570,8 @@ function apply(ctx) {
1567
1570
  statusNotice.setAttribute('role', 'status');
1568
1571
  statusNotice.style.cssText = 'position:fixed;bottom:16px;right:16px;max-width:min(360px,80vw);z-index:1000;background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-primary,#222);padding:12px;border:1px solid currentColor;border-radius:8px;box-sizing:border-box;pointer-events:none;';
1569
1572
  statusNotice.textContent = status.failed
1570
- ? '多密钥自动补丁未完成。请回到 App 对话查看引擎日志或运行安装诊断,勿强制覆盖。请暂勿编辑模型配置;可到「设置 → 模型分组」检查并安全恢复。'
1571
- : '多密钥补丁已自动安装。请先保存其他页面的草稿,再到 App 重启原引擎并刷新此网页。请暂勿编辑模型配置,避免新旧模块混用;维护入口仍可使用。';
1573
+ ? '无法检查多密钥功能所需的 DSH 文件。请打开「设置 → 模型分组」查看详情,不要手动覆盖文件。'
1574
+ : 'DSH 程序文件已更新。请先保存草稿,再重启 DSH 引擎并刷新网页。重启前请暂缓修改模型设置。';
1572
1575
  document.body.appendChild(statusNotice);
1573
1576
  }).catch(() => {});
1574
1577
  ctx.on('dispose', () => { statusDisposed = true; statusNotice?.remove(); });