dsh-decision-engine 0.5.2 → 0.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/README.md +39 -7
- package/config.example.yml +11 -4
- package/lib/client.js +477 -213
- package/lib/endpoint-fallback.js +143 -0
- package/lib/index.js +132 -41
- package/lib/providers.js +72 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -100,14 +100,21 @@ Windows 允许点开头的目录。真正与平台相关的是分隔符与家目
|
|
|
100
100
|
- 两个开关:`启用守卫`、`真正拦截`
|
|
101
101
|
- **思考模式**下拉:`never` / `auto` / `always`(见下文「省 token 的手段」里的取舍)
|
|
102
102
|
- **模型**下拉(来自当前 provider 的 `/v1/models`,含「自动(服务端默认)」)
|
|
103
|
-
- 一个 **API Key 输入框**
|
|
103
|
+
- 一个 **API Key 输入框**
|
|
104
104
|
- 选 `custom` 时展开四个字段:`Base URL`(必填)、`端点风格`、`附加请求头`、`密钥变量名`
|
|
105
105
|
- 一个 `测试端点` 按钮(回显 provider、实际 POST 的完整地址、HTTP 码、请求 id 与响应体)
|
|
106
106
|
- **决策模型参与点**列表:每个决策点一行,右侧是 `关闭 / 观察 / 生效` 三态
|
|
107
107
|
- `自身 token 预算` 输入框,以及实时的缓存命中率与每个点的 token / 延迟统计
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
**改完即保存,没有「保存」按钮**:开关 / 下拉 / 分段控件点一下就落盘;文本框
|
|
110
|
+
(地址、请求头、预算)停手约 0.7 秒或失焦后落盘;API Key 只在**失焦或回车**
|
|
111
|
+
时落盘(避免把打字途中的半截 key 写进凭据文件)。底部状态行实时显示
|
|
112
|
+
`待保存… / 保存中… / 已保存 / 未保存:原因`,失败时附「重试」。落盘即写入
|
|
113
|
+
`config.yml`,**不需要重启**:监听器常驻注册,provider 与模式在每次调用时现读;
|
|
114
|
+
预算与缓存参数同样是取值函数而非启动期快照。
|
|
115
|
+
|
|
116
|
+
一个例外:选 `custom` 但 `Base URL` 还没填或不合法时,配置改动会**整体延后**
|
|
117
|
+
(状态行给出原因),地址补全后自动落盘;此时决策点改动不受影响,照常保存。
|
|
111
118
|
|
|
112
119
|
## Provider:接任意 system-one 风格服务
|
|
113
120
|
|
|
@@ -152,7 +159,7 @@ content-type: application/json
|
|
|
152
159
|
| 字段 | 必填 | 说明 |
|
|
153
160
|
|---|---|---|
|
|
154
161
|
| `Base URL` | **是** | 必须是 `http://` 或 `https://` 地址。不支持其它协议(`ftp:` 等会被拒绝),不带 scheme 也会被拒绝——自定义地址必须显式,避免猜错协议。不能含空格、换行或查询串。 |
|
|
155
|
-
| `端点风格` | 否 | `auto`(默认)/ `decisions` / `systemone
|
|
162
|
+
| `端点风格` | 否 | `auto`(默认)/ `decisions` / `systemone`。这是**首选**路径,不是唯一路径:首选返回 404 时插件会自动改用另一条再试一次(见下)。 |
|
|
156
163
|
| `附加请求头` | 否 | 格式 `名称: 值`,多项用分号分隔,如 `X-Tenant: team-a; X-Trace: dsh`。`authorization` / `content-type` / `host` 由插件固定,写了也会被忽略。 |
|
|
157
164
|
| `密钥变量名` | 否 | 填了就从该环境变量或 `~/.dsh/.credentials.yaml` 的 `refs:` 段取 key;也可以直接在 API Key 输入框粘贴。 |
|
|
158
165
|
| `模型` | 否 | 留空 = 由服务端选默认;实测留空比发空串安全(发 `"model": ""` 会被 400)。 |
|
|
@@ -170,6 +177,31 @@ content-type: application/json
|
|
|
170
177
|
|
|
171
178
|
拼接是幂等的:对结果再拼一次不会变成 `/v1/v1/decisions` 或 `//decisions`。
|
|
172
179
|
|
|
180
|
+
### 端点路径由服务商决定,不由模型决定
|
|
181
|
+
|
|
182
|
+
这是本插件最容易踩空的一处,因此**实测**过(2026-10-25,真实 key 打真实端点):
|
|
183
|
+
|
|
184
|
+
| 服务商 | 模型 | `/v1/decisions` | `/v1/systemone` |
|
|
185
|
+
|---|---|---|---|
|
|
186
|
+
| SiliconFlow | `Kev-4B` | **404 Not Found** | **200 ✅** |
|
|
187
|
+
| bamboonode | `startlux-decision-27b-autothink` | 200 ✅ | 200 ✅ |
|
|
188
|
+
|
|
189
|
+
也就是说,`Kev-4B` 并不是「只能用 `/systemone` 的模型」——**路径由服务商决定**。
|
|
190
|
+
同一个 `Kev-4B` 换一个服务商,路径就得跟着换。
|
|
191
|
+
|
|
192
|
+
**因此 `端点风格` 只是「首选」**:
|
|
193
|
+
|
|
194
|
+
1. 先打首选路径;
|
|
195
|
+
2. 收到 **404**(= 路径不存在)时,自动改用另一条再试一次;
|
|
196
|
+
3. 试通的那条会被**记住**(按 base URL 区分),下次直接打它,不再多一次往返;
|
|
197
|
+
4. 两条都 404 时,遥测与「测试端点」会**列出试过的两个地址**并提示改端点风格。
|
|
198
|
+
|
|
199
|
+
只有 404 会触发换路径:400(模型/内容不合法)、401(key 不对)、5xx 都与路径无关,
|
|
200
|
+
换路径只是多烧一次请求。配置页的「生效端点」下方会显示「已验证可用:…」。
|
|
201
|
+
|
|
202
|
+
> 旧版本没有回退:路径踩空就是 404,而守卫是 fail-open 的——**静默失效**。
|
|
203
|
+
> 现场证据:`telemetry.jsonl` 里 2026-10-25 13:16–13:41 有 8 次 `http-404` 降级。
|
|
204
|
+
|
|
173
205
|
### 持久化与切换行为
|
|
174
206
|
|
|
175
207
|
- 所有 provider 的配置**并列**存在 `config.yml` 里,互不覆盖:
|
|
@@ -193,7 +225,7 @@ content-type: application/json
|
|
|
193
225
|
| `credentials`(默认) | `~/.dsh/.credentials.yaml` 的 `refs:` 段 | 与其他服务(DeepSeek / ModelScope …)统一托管,插件目录不留明文 |
|
|
194
226
|
| `config` | 插件配置目录下的 `config.yml` | 希望配置自包含、能随目录整体备份或迁移;注意是**明文** |
|
|
195
227
|
|
|
196
|
-
|
|
228
|
+
在设置界面「密钥保存位置」下拉切换,切换即按新位置写入;已有的 key 不会被
|
|
197
229
|
自动搬家(避免"看不到的地方被改动"),需要时重新粘贴一次即可。
|
|
198
230
|
|
|
199
231
|
写入 `credentials` 的行为约束:
|
|
@@ -210,7 +242,7 @@ content-type: application/json
|
|
|
210
242
|
|
|
211
243
|
| 情形 | 表现 |
|
|
212
244
|
|---|---|
|
|
213
|
-
| base URL 非法 / 为空(custom) |
|
|
245
|
+
| base URL 非法 / 为空(custom) | 该次落盘直接被拒(HTTP 400 + 具体原因,如「必须以 http:// 或 https:// 开头」),**不会写进 yml**;自动保存会一直挂着「未保存」并允许重试 |
|
|
214
246
|
| 密钥缺失 | 不发请求,`no-key` 降级(记录里带该 provider 的变量名) |
|
|
215
247
|
| 鉴权失败(401/403) | `auth-failed` 降级,提示检查该 provider 的 key 是否有效、是否与地址匹配 |
|
|
216
248
|
| 地址错(404/400) | `http-404` / `http-400` 降级,记录里带 `provider`、`endpoint` 与响应体 |
|
|
@@ -416,7 +448,7 @@ pnpm verify # 前两条一起跑
|
|
|
416
448
|
| `test/engine.test.js` | 适配器接线、off/observe/enforce 语义、全部降级分支 |
|
|
417
449
|
| `test/providers.test.js` | provider 预设、地址拼接、URL 校验、鉴权与请求构造 |
|
|
418
450
|
| `test/config-file.test.js` | `config.yml` 读写往返:保存后再打开的回显、切换不互相覆盖 |
|
|
419
|
-
| `test/client-ui.test.js` |
|
|
451
|
+
| `test/client-ui.test.js` | 设置界面渲染与交互:provider 下拉、custom 字段、错误提示、**改动即保存**(无保存按钮、改动自动 PUT /config、API Key 失焦提交) |
|
|
420
452
|
|
|
421
453
|
`test/providers.test.js` 是 provider 改造的验收用例(不依赖宿主依赖,
|
|
422
454
|
裸仓库可直接跑),覆盖六项硬约束:
|
package/config.example.yml
CHANGED
|
@@ -71,10 +71,17 @@ systemoneModel: ""
|
|
|
71
71
|
# 允许省略 scheme,custom 不允许——自定义地址必须显式,避免猜错协议)。
|
|
72
72
|
# customBaseUrl: https://api.example.com/v1
|
|
73
73
|
#
|
|
74
|
-
#
|
|
75
|
-
# auto 地址已带 /decisions 或 /systemone
|
|
76
|
-
# decisions POST <base>/decisions
|
|
77
|
-
# systemone POST <base>/systemone
|
|
74
|
+
# 端点风格(**首选**路径,不是唯一路径):
|
|
75
|
+
# auto 地址已带 /decisions 或 /systemone 就原样用,否则先试 decisions
|
|
76
|
+
# decisions 先试 POST <base>/decisions
|
|
77
|
+
# systemone 先试 POST <base>/systemone
|
|
78
|
+
#
|
|
79
|
+
# 路径后缀由**服务商**决定,不由模型决定。实测(2026-10-25,真实端点):
|
|
80
|
+
# SiliconFlow 的 Kev-4B /v1/decisions → 404,/v1/systemone → 200
|
|
81
|
+
# bamboonode 的决策模型 两条路径都 200
|
|
82
|
+
#
|
|
83
|
+
# 所以首选路径返回 404 时,插件会自动改用另一条再试一次,并记住试通的那条。
|
|
84
|
+
# 只有 404 会触发换路径:400(模型/内容不合法)与 401(key 不对)都跟路径无关。
|
|
78
85
|
customEndpointStyle: auto
|
|
79
86
|
#
|
|
80
87
|
# custom 自己的模型(留空 = 服务端默认)。与内置预设的 model 分开存,
|