dsh-model-input-toggle 0.0.0-stage → 1.0.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/README.md +353 -2
- package/cordis.patch.yml +13 -0
- package/lib/client.js +731 -0
- package/lib/index.js +892 -0
- package/package.json +48 -4
- package/tools/settings-semantics.mjs +68 -0
- package/tools/test-client.mjs +954 -0
- package/tools/test-host.mjs +761 -0
- package/tools/test.mjs +27 -0
- package/tools/verify-endpoint.mjs +478 -0
package/README.md
CHANGED
|
@@ -1,3 +1,354 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dsh-model-input-toggle
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
在 **设置 → 模型** 页面,为每个模型直接开关**图片输入**声明 —— 不用再手改 `settings.yaml`。
|
|
4
|
+
|
|
5
|
+
DSH 的 `llm-pi-ai` / `llm-deepseek` 适配器本来就支持 `input: ["text", "image"]`,
|
|
6
|
+
但官方模型设置页只让你填 `id` / `name` / `contextWindow` / `maxTokens`。
|
|
7
|
+
第三方 provider 添加的模型因此默认「仅文本」,你发图片会被 DSH 直接拦下。
|
|
8
|
+
这个插件补上了缺失的那个开关。
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## ⚠️ 先读这一条:声明 ≠ 能力
|
|
13
|
+
|
|
14
|
+
勾选复选框只是**写入一条声明**,告诉 DSH「这个模型能收图片」。
|
|
15
|
+
它让 DSH 不再拦截图片消息,**但它不能让远端端点真的支持图片**。
|
|
16
|
+
|
|
17
|
+
| | 勾选前 | 勾选后(端点其实不支持) |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| 你会看到 | DSH 本地拦截,报 `UNSUPPORTED_CONTENT` | 请求发出去,端点回 **HTTP 400**(或网关包装后的 4xx/5xx) |
|
|
20
|
+
| 失败发生在 | 本地 | 远端 |
|
|
21
|
+
|
|
22
|
+
**失败只是换了地方,并没有消失。** 所以本插件提供两种验证手段(下面第 4 节),
|
|
23
|
+
请务必在勾选后**实际验证一次**。不要因为勾上了就以为图片能用了。
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 功能
|
|
28
|
+
|
|
29
|
+
- **每个模型一个开关**:在 provider 卡片中列出该 provider 的所有模型,逐个勾选。
|
|
30
|
+
- **立即写入**:勾选即写入 `settings.yaml`,没有「保存」按钮。
|
|
31
|
+
- **写入后立即验证**:写完后插件会通过 `llm.resolveModelInfo` 真实读取适配器解析结果,
|
|
32
|
+
确认 DSH 侧已经认可这条声明(而不只是「字段写进去了」)。
|
|
33
|
+
- **失败自动回滚**:写入失败时开关自动弹回原状态,并显示红色错误。
|
|
34
|
+
- **首次开启二次确认**:第一次勾选会弹出风险说明,确认后不再重复打扰;取消勾选永不弹窗。
|
|
35
|
+
- **验证端点**:每个模型一个「验证端点」按钮,真实发送一条带 `image_url` 的请求,
|
|
36
|
+
并自动补发一条去掉图片的对照请求,区分「端点拒绝图片」与「这次请求本身就被拒」。结果是
|
|
37
|
+
✓ 接受图片、✕ 拒绝图片、? 与图片无关、或凭据/网络/超时问题。
|
|
38
|
+
- **官方声明的视觉模型会锁定**:由官方目录声明的模型显示为已勾选 + 禁用,标注
|
|
39
|
+
「该模型由官方目录声明」,不会被覆盖。
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 安装
|
|
44
|
+
|
|
45
|
+
插件已在 `web` profile 中安装并挂载。手动安装步骤如下。
|
|
46
|
+
|
|
47
|
+
### 方式一:从本地目录安装(推荐)
|
|
48
|
+
|
|
49
|
+
```powershell
|
|
50
|
+
dsh plugin --profile web add C:\Users\XIAOPAN\Desktop\dsh\dsh-model-input-toggle
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`dsh.bundle.patch` 会让 DSH 自动读取插件的 `cordis.patch.yml`,无需手改 profile 配置。
|
|
54
|
+
**安装后需要完整重启 DSH**(浏览器端的 HMR 只对已在运行的 client bundle 生效)。
|
|
55
|
+
|
|
56
|
+
### 方式二:手动放置
|
|
57
|
+
|
|
58
|
+
```powershell
|
|
59
|
+
# 1. 复制到 profile 的 node_modules
|
|
60
|
+
$dst = "$env:USERPROFILE\.dsh\profiles\web\node_modules\dsh-model-input-toggle"
|
|
61
|
+
Copy-Item C:\Users\XIAOPAN\Desktop\dsh\dsh-model-input-toggle $dst -Recurse -Force
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
```yaml
|
|
65
|
+
# 2. 在 $DSH_HOME\profiles\web\cordis.patch.yml 末尾追加
|
|
66
|
+
- insert:
|
|
67
|
+
- id: dsh-model-input-toggle
|
|
68
|
+
name: 'dsh-model-input-toggle'
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
```powershell
|
|
72
|
+
# 3. 完整重启 DSH
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 卸载
|
|
76
|
+
|
|
77
|
+
删掉 `cordis.patch.yml` 中上面那段 `- insert:` 行,删除 `node_modules\dsh-model-input-toggle`
|
|
78
|
+
目录,然后重启 DSH。插件不会留下任何其它状态(改过的 `settings.yaml` 内容请自行决定是否还原)。
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 使用
|
|
83
|
+
|
|
84
|
+
1. 打开 **设置 → 模型**。
|
|
85
|
+
2. 每个 provider 卡片下方有一行**折叠**的「**图片输入**」条目,默认收起,只占一行:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
▶ 图片输入 1/2 已开启
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
这一行本身就带信息:右侧显示该 provider 下有多少模型已声明图片输入
|
|
92
|
+
(全部未开启时显示「全部仅文本」),所以不展开也能看出当前状态。
|
|
93
|
+
卡片很多时不会把页面撑长。
|
|
94
|
+
|
|
95
|
+
3. **点这一行**展开,按模型逐行列出:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
▼ 图片输入 1/2 已开启
|
|
99
|
+
勾选即刻写入配置,无需保存。注意:这里只是声明模型可接收图片,DSH 因此
|
|
100
|
+
不再拦截图片消息;若端点实际不支持图片,请求会返回 400。请用「验证端点」
|
|
101
|
+
确认实际能力。
|
|
102
|
+
|
|
103
|
+
☐ Buddy V4.1 Flash buddy:deepseek-v4.1-flash [验证端点]
|
|
104
|
+
☐ GLM 5.3 Flash buddy:glm-5.3-flash [验证端点]
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
4. 勾选目标模型 → 首次会弹出确认框 → 点「确认开启」→ 开关变为 ✓ 已保存。
|
|
108
|
+
5. 点「**验证端点**」→ 等待几秒 → 看到 ✓ 或 ✕ 的结论。
|
|
109
|
+
|
|
110
|
+
展开状态是**每个 provider 卡片各自独立**的,且**不持久化**:刷新页面后
|
|
111
|
+
重新回到折叠状态——因为大多数时候用户只是来扫一眼,默认安静更合适。
|
|
112
|
+
|
|
113
|
+
勾选框的悬停提示:
|
|
114
|
+
|
|
115
|
+
> 勾选后该模型可接收图片消息,取消勾选则仅支持文本。修改后建议用带图片的请求验证端点实际能力。
|
|
116
|
+
|
|
117
|
+
### 界面状态说明
|
|
118
|
+
|
|
119
|
+
| 显示 | 含义 |
|
|
120
|
+
|---|---|
|
|
121
|
+
| ☐ 可点击 | 当前声明为仅文本 |
|
|
122
|
+
| ☑ ✓ 已保存 | 声明已写入,且适配器已确认 |
|
|
123
|
+
| ⟳ 正在写入… | 写入中,期间禁止重复点击 |
|
|
124
|
+
| ✕ 红色文字 | 写入失败,开关已回滚到操作前状态 |
|
|
125
|
+
| ☑ 禁用 + 「该模型由官方目录声明」 | 官方目录声明的模型,插件不覆盖 |
|
|
126
|
+
| ✓ 端点接受了带图片的请求 | 端点确实支持图片 |
|
|
127
|
+
| ✕ 端点拒绝了图片输入 | 端点拒绝图片,且去掉图片的同一请求能通过 → **建议取消勾选** |
|
|
128
|
+
| ? 端点失败,但与图片无关 | 去掉图片的同一请求**也**失败 → 先排查该模型能否正常对话 |
|
|
129
|
+
| ! 凭据 / 网络 / 超时 | 未走到图片判定,按提示修凭据或网络 |
|
|
130
|
+
|
|
131
|
+
> **为什么会有「与图片无关」这一档**:网关经常把上游错误包成 HTTP 502 再套一层 JSON
|
|
132
|
+
> (例如 `CodeBuddy 上游 HTTP 400:{"msg":"model [...] service info not found"}`)。
|
|
133
|
+
> 早期版本把所有 400/422 都判成「不支持图片」,会把**模型未开通、网关策略、请求格式**
|
|
134
|
+
> 这类问题冤枉到图片头上。现在判定前会补发一条**去掉图片的对照请求**:
|
|
135
|
+
> 只有「带图失败、不带图成功」才算端点拒绝图片。
|
|
136
|
+
|
|
137
|
+
### 截图
|
|
138
|
+
|
|
139
|
+
> 截图占位:请按下列五张补齐后放入 `docs/`,并替换本节。
|
|
140
|
+
>
|
|
141
|
+
> | 文件 | 内容 |
|
|
142
|
+
> |---|---|
|
|
143
|
+
> | `docs/00-collapsed.png` | 设置 → 模型中默认折叠的一行「▶ 图片输入 1/2 已开启」 |
|
|
144
|
+
> | `docs/01-panel.png` | 展开后的「图片输入」区域与模型列表 |
|
|
145
|
+
> | `docs/02-confirm.png` | 首次勾选时的风险确认对话框(取消 / 确认开启) |
|
|
146
|
+
> | `docs/03-saved.png` | 勾选后的 ✓ 已保存状态 |
|
|
147
|
+
> | `docs/04-verify.png` | 「验证端点」的三种结论:✓ 支持、✕ 拒绝、? 与图片无关 |
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 验证端点(两种方式)
|
|
152
|
+
|
|
153
|
+
### 方式一:界面上的「验证端点」按钮
|
|
154
|
+
|
|
155
|
+
对单个模型点击即可,Host 侧发送:
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
POST {baseURL}/chat/completions
|
|
159
|
+
{
|
|
160
|
+
"model": "<模型 id>",
|
|
161
|
+
"max_tokens": 16,
|
|
162
|
+
"messages": [
|
|
163
|
+
{ "role": "system", "content": "You are a helpful assistant." },
|
|
164
|
+
{ "role": "user", "content": [
|
|
165
|
+
{ "type": "text", "text": "Reply with the single word: ok" },
|
|
166
|
+
{ "type": "image_url", "image_url": { "url": "data:image/png;base64,<64x64 蓝色 PNG>" } }
|
|
167
|
+
]}
|
|
168
|
+
]
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
> **第一条必须是 system 消息**。部分网关(如本机 `jiuling` 背后的 CodeBuddy 代理)
|
|
173
|
+
> 会先校验消息顺序,不是 system 开头就直接返回 502 `first message is not system prompt`
|
|
174
|
+
> —— 此时它**根本还没看图片**。早期版本漏了这条,导致所有 jiuling 验证都误报 502。
|
|
175
|
+
|
|
176
|
+
结论判定:
|
|
177
|
+
|
|
178
|
+
| 情况 | 结论 |
|
|
179
|
+
|---|---|
|
|
180
|
+
| HTTP 200 | ✓ 端点接受图片,确实支持视觉输入 |
|
|
181
|
+
| 带图失败、**不带图成功** | ✕ 端点拒绝图片,建议取消勾选 |
|
|
182
|
+
| 带图失败、**不带图也失败** | ? 与图片无关(模型未开通 / 网关策略 / 参数不符),先让该模型能正常对话 |
|
|
183
|
+
| 401 / 403 | 凭据问题,换密钥后重试 |
|
|
184
|
+
| 404 | baseURL 或协议不对 |
|
|
185
|
+
| 超时 / 连接失败 | 网络或端点不可达 |
|
|
186
|
+
|
|
187
|
+
HTTP 200 只发一条请求;非 200 才补发对照请求,因此成功路径没有额外开销。
|
|
188
|
+
|
|
189
|
+
### 方式二:命令行脚本(不依赖 DSH 运行)
|
|
190
|
+
|
|
191
|
+
适合在勾选**之前**先验证,或放进 CI。
|
|
192
|
+
|
|
193
|
+
```powershell
|
|
194
|
+
# 从 settings.yaml 自动读取 baseURL 与密钥引用
|
|
195
|
+
node tools/verify-endpoint.mjs --provider jiuling --model buddy:glm-5.3-flash
|
|
196
|
+
|
|
197
|
+
# 完全手工指定
|
|
198
|
+
node tools/verify-endpoint.mjs --base-url https://api.example.com/v1 --model my-vision-model --api-key sk-...
|
|
199
|
+
|
|
200
|
+
# JSON 输出(便于脚本消费)
|
|
201
|
+
node tools/verify-endpoint.mjs --provider agnes --model agnes-3.0-flash --json
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
退出码:`0` 接受图片 · `1` 拒绝图片(带图失败但不带图成功)· `2` 无法判定(与图片无关 / 凭据 / 网络 / 404 / 超时)。
|
|
205
|
+
|
|
206
|
+
> 脚本会先关闭 undici 的 dispatcher 再退出。Windows 上若在两条请求的 socket 仍在
|
|
207
|
+
> 拆除时直接 `process.exit()`,会触发 libuv 断言(`UV_HANDLE_CLOSING`)并把退出码
|
|
208
|
+
> 变成 `-1073740791`;现在改用 `process.exitCode`,退出码可靠。
|
|
209
|
+
|
|
210
|
+
实测示例:
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
$ node tools/verify-endpoint.mjs --provider jiuling --model buddy:deepseek-v4.1-flash
|
|
214
|
+
✓ 端点接受了带图片的请求(HTTP 200):该模型确实支持视觉输入。
|
|
215
|
+
请求地址: http://47.106.84.173:8899/v1/chat/completions
|
|
216
|
+
|
|
217
|
+
$ node tools/verify-endpoint.mjs --provider jiuling --model buddy:glm-5.3-flash
|
|
218
|
+
? 端点返回 HTTP 502,但这与图片无关:去掉图片的同一请求仍然返回 HTTP 502,说明该端点拒绝了这次请求本身(模型未开通、网关策略、参数不符等)。请先确认该模型可正常对话,再验证图片能力。
|
|
219
|
+
请求地址: http://47.106.84.173:8899/v1/chat/completions
|
|
220
|
+
端点响应: CodeBuddy 上游 HTTP 400:model [glm-5.3-flash] service info not found
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
第二个例子是真实的:`buddy:glm-5.3-flash` 在上游**根本没有开通**,纯文本请求也是同样的 502。
|
|
224
|
+
插件如实报告「与图片无关」,而不是甩一坨嵌套 JSON 或冤枉模型不支持视觉。
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## 错误处理
|
|
229
|
+
|
|
230
|
+
| 场景 | 表现 | 你该做什么 |
|
|
231
|
+
|---|---|---|
|
|
232
|
+
| **Provider 不存在** | 开关回滚,红色显示 `provider "xxx" 不存在于 llm-pi-ai 配置中。` | 检查 provider 路由名是否拼错,或该 provider 是否已被删除 |
|
|
233
|
+
| **Model 不存在**(该 provider 有 `models` 列表时) | 开关回滚,`模型 "xxx" 不在 provider "yyy" 的 models 列表中;请先在设置页添加该模型。` | 先在模型设置页添加该模型,再回来勾选 |
|
|
234
|
+
| **配置版本冲突** | Host 自动重读最新配置并重试一次;仍冲突则提示 `配置已被其它操作修改,重试后仍然冲突。请在设置页面手动刷新后重试。` | 刷新页面后重试(通常是有另一个窗口/实例同时改了配置) |
|
|
235
|
+
| **Host 无响应** | 10 秒后开关回滚,显示 `连接超时,请检查 DSH 是否正常运行。` | 确认 DSH 进程还在;重启 DSH |
|
|
236
|
+
| **写入成功但适配器不认可** | 显示 `配置已写入,但适配器回报该模型的可输入模态为 [...],与请求不一致。` | 通常是 provider 未激活;重启 DSH 后再看 |
|
|
237
|
+
| **端点实际不支持图片** | 配置写入成功,但「验证端点」返回 ✕(带图失败、去掉图片成功) | **取消勾选**,或换一个真正支持视觉的模型 |
|
|
238
|
+
| **验证失败但与图片无关** | 「验证端点」返回 ?(去掉图片的同一请求也失败) | 先让该模型能正常对话(可能未开通/被网关拦),再验证图片 |
|
|
239
|
+
| **未解析到凭据** | 验证端点前就提示 `未能解析凭据 "XXX":请在设置页填写该 provider 的 API 密钥。` | 在设置页填入该 provider 的 API Key |
|
|
240
|
+
| **密钥无效** | 验证端点返回 `! 凭据被拒绝(HTTP 401):请检查 API 密钥。` | 该密钥已失效,去 provider 后台重新签发 |
|
|
241
|
+
| **协议不支持自动验证** | 提示 `协议 "xxx" 不支持自动验证(仅支持 openai-completions)。` | 改用带图片的真实请求手工验证 |
|
|
242
|
+
|
|
243
|
+
所有失败都会**回滚到操作前的状态**,不会留下「界面显示已开启、实际没写进去」的假象。
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## 它到底改了什么
|
|
248
|
+
|
|
249
|
+
| 适配器 | 命名空间 | 写入路径 |
|
|
250
|
+
|---|---|---|
|
|
251
|
+
| `llm-pi-ai` | `llm-pi-ai` | `providers.<route>.models[].input = ["text","image"]` |
|
|
252
|
+
| `llm-pi-ai`(该 route 没有用户 `models` 列表时) | `llm-pi-ai` | `providers.<route>.modelOverrides.<id>.input` |
|
|
253
|
+
| `llm-deepseek` | `llm-deepseek` | `models[].inputModalities = ["text","image"]` |
|
|
254
|
+
|
|
255
|
+
取消勾选写回 `["text"]`。
|
|
256
|
+
|
|
257
|
+
关于 `modelOverrides` 这条分支:适配器规定 **`modelOverrides` 不能与 `models` 列表同时存在**
|
|
258
|
+
(`models` 已经完整替代了目录,此时 `modelOverrides` 会被判为无效配置)。
|
|
259
|
+
所以插件只有在**该 route 没有任何用户 `models` 列表**时才走 `modelOverrides`;
|
|
260
|
+
一旦有 `models` 列表,就重写整个列表并保留所有其它字段。
|
|
261
|
+
|
|
262
|
+
> **实现注记**:`settings.mutate` 的路径操作只能逐层进入**普通对象**,遇到数组即视为终点。
|
|
263
|
+
> 因此写数组元素**不能**使用 `models.0.input` 这类路径(那样等于把整个数组替换掉、摧毁其它条目)。
|
|
264
|
+
> 插件改为读出当前数组 → 重建整个数组 → 用一次 `set` 整体写入。
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## 已知限制
|
|
269
|
+
|
|
270
|
+
- **位置**:DSH 的 `settings.models.provider-card` 插槽只能拿到 provider 信息(拿不到模型列表),
|
|
271
|
+
所以「图片输入」是渲染在 **provider 卡片内**的独立区域,而不是嵌在官方那一行
|
|
272
|
+
「上下文窗口 / 最大输出 token」下面。功能等价,位置与原需求描述有差异。
|
|
273
|
+
为不额外增加页面长度,该区域**默认折叠**,只占一行(见「使用」)。
|
|
274
|
+
- **卡片按 provider 分组**:`llm-pi-ai` 的每个 route 都会渲染同一个组件实例(按
|
|
275
|
+
`settingsNs` 分发),组件内部按 `props.provider.provider` 区分,因此多个 provider 互不干扰。
|
|
276
|
+
没有 `settingsNs` 的 provider 不渲染任何界面。
|
|
277
|
+
- **折叠状态不持久化**:刷新后回到折叠。这是有意的——避免把上一次的展开状态当成用户偏好。
|
|
278
|
+
- **官方参数不在本插件职责内**:官方的「上下文窗口 / 最大输出 token」本来就在「编辑」表单里,
|
|
279
|
+
未展开编辑时并不显示;插件只负责图片输入声明,不会去折叠或改动官方字段的行为。
|
|
280
|
+
- **只有官方目录声明的模型被锁定**;用户自己声明的模型一律可改。
|
|
281
|
+
- 判定「官方目录声明」依赖适配器暴露的 provider 目录信息;若适配器未提供该信息,
|
|
282
|
+
该 provider 的模型会按可编辑处理。
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## 疑难排查
|
|
287
|
+
|
|
288
|
+
### 「验证端点」报 502 / 与图片无关
|
|
289
|
+
|
|
290
|
+
先看**它说的是不是图片的事**:
|
|
291
|
+
|
|
292
|
+
- **? 与图片无关** —— 去掉图片的同一请求也失败。常见原因:该模型在上游未开通
|
|
293
|
+
(如 `model [...] service info not found`)、网关策略拦截、参数不符。
|
|
294
|
+
**先让这个模型能正常对话**,再来验证图片。
|
|
295
|
+
- **! 凭据被拒绝(HTTP 401)** —— 密钥失效。用裸请求也能复现,与本插件无关:
|
|
296
|
+
```powershell
|
|
297
|
+
node tools/verify-endpoint.mjs --base-url https://apihub.agnes-ai.cn/v1 --model agnes-3.0-flash --api-key sk-xxx
|
|
298
|
+
```
|
|
299
|
+
换密钥即可。
|
|
300
|
+
|
|
301
|
+
### 改了插件代码但界面/行为没变
|
|
302
|
+
|
|
303
|
+
DSH 在**启动时**读取 Host 代码与 Client bundle,**没有热重载**。改完必须:
|
|
304
|
+
|
|
305
|
+
1. 把源码同步到已安装副本(`<DSH_HOME>/profiles/web/node_modules/dsh-model-input-toggle/`)
|
|
306
|
+
2. **完整重启 DSH**(不是刷新页面)
|
|
307
|
+
|
|
308
|
+
只改源码不同步、或同步了不重启,都会继续跑旧代码 —— 表现为「改了却一模一样」。
|
|
309
|
+
|
|
310
|
+
### 本机访问 3080 要账号密码
|
|
311
|
+
|
|
312
|
+
那是 `dsh-basic-auth` 插件在 DSH 的 HTTP server 上装的门卫,与插件的**出站**请求无关
|
|
313
|
+
(本插件的探测请求由 Host 进程直接 `fetch` 到你的 `baseURL`,不经过 DSH 的 HTTP server)。
|
|
314
|
+
若想绕开门卫验证端点,用上面的命令行脚本。
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## 开发与测试
|
|
319
|
+
|
|
320
|
+
```powershell
|
|
321
|
+
node tools/test.mjs # 全部测试(Host 24 项 + Client 18 项)
|
|
322
|
+
node tools/test-host.mjs # Host:配置读写、冲突重试、错误分类、信任围栏、端点探测
|
|
323
|
+
node tools/test-client.mjs # Client:真实渲染、折叠/展开、勾选/回滚/确认框/超时/验证按钮
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
测试不依赖 DSH 进程:Host 测试用实现了官方 `applyPathOp` / `mergeLayers` 语义的桩服务挂载
|
|
327
|
+
真实的 `apply()`,Client 测试用带 hook 生命周期的 React 替身真实渲染 bundle 并驱动交互。
|
|
328
|
+
|
|
329
|
+
```
|
|
330
|
+
dsh-model-input-toggle/
|
|
331
|
+
├── lib/
|
|
332
|
+
│ ├── index.js Host 半:设置读写 + 端点验证 + 受围栏保护的 HTTP 路由
|
|
333
|
+
│ └── client.js Client 半:设置页 UI(provider-card 插槽)
|
|
334
|
+
├── tools/
|
|
335
|
+
│ ├── verify-endpoint.mjs 独立端点验证脚本(可接 CI)
|
|
336
|
+
│ ├── test.mjs 测试入口
|
|
337
|
+
│ ├── test-host.mjs Host 测试
|
|
338
|
+
│ ├── test-client.mjs Client 测试
|
|
339
|
+
│ └── settings-semantics.mjs 官方 settings 语义的测试替身
|
|
340
|
+
├── cordis.patch.yml bundle patch(loader 行)
|
|
341
|
+
├── package.json dsh.bundle.patch + dsh.client manifest
|
|
342
|
+
└── README.md
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## 安全说明
|
|
348
|
+
|
|
349
|
+
Host 路由 `/dsh-model-input-toggle/api` 只接受来自 loopback 或 `trustedHosts` 的请求,
|
|
350
|
+
并拒绝 `sec-fetch-site: cross-site` 与跨站 `Origin`。这不是身份认证,而是防止 DNS rebinding /
|
|
351
|
+
跨站页面借道写入你的模型配置或消耗你的端点额度。
|
|
352
|
+
|
|
353
|
+
验证端点会在请求里带上该 provider 的 API 密钥(从凭据服务或环境变量解析),
|
|
354
|
+
仅发往你在 `settings.yaml` 中配置的 `baseURL`。
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# dsh-model-input-toggle bundle patch — one loader entry mounting the plugin.
|
|
2
|
+
#
|
|
3
|
+
# The entry is a normal cordis loader entry (id + package name). The browser
|
|
4
|
+
# half is picked up by dsh-client-modules through the package's dsh.client
|
|
5
|
+
# declaration + exports["./client"], exactly like the shipped ui-* packages and
|
|
6
|
+
# like dsh-agconfig / dsh-agimage.
|
|
7
|
+
#
|
|
8
|
+
# Manual mount: add the same row to the profile's cordis.patch.yml, or install
|
|
9
|
+
# the package with `dsh plugin --profile web add ./dsh-model-input-toggle`
|
|
10
|
+
# (the bundle channel reads this file automatically).
|
|
11
|
+
- insert:
|
|
12
|
+
- id: dsh-model-input-toggle
|
|
13
|
+
name: 'dsh-model-input-toggle'
|