dsh-yolo-mode 0.5.2-beta.0 → 0.5.3
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 +40 -9
- package/README.md +4 -2
- package/lib/client/index.js +97 -10
- package/package.json +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,17 +2,48 @@
|
|
|
2
2
|
|
|
3
3
|
本项目遵循 [Semantic Versioning](https://semver.org/)。
|
|
4
4
|
|
|
5
|
-
## [0.5.
|
|
5
|
+
## [0.5.3] - 2026-09-25
|
|
6
|
+
|
|
7
|
+
### 兼容:适配 DSH 0.1.7-rc.2
|
|
8
|
+
|
|
9
|
+
- 在本机 **0.1.7-rc.2** 上真实装载运行通过:全部入口激活、零错误、无 pending
|
|
10
|
+
(`did not activate` 告警不出现);设置读写(`settingsView` / `settingsMutate`
|
|
11
|
+
乐观锁)实测往返成功。`dsh.compatibility.dshReleases` 新增
|
|
12
|
+
`"0.1.7-rc.2": "compatible"`;README 徽章与兼容性说明同步。
|
|
13
|
+
- 0.1.7-rc.1 → rc.2 的官方 `@deepseek-ai/dsh-*` 公开 API **无移除、无改名**
|
|
14
|
+
(`dsh-settings` / `dsh-client-connection` / `dsh-client-ui-slots` 逐字节相同,
|
|
15
|
+
其余为增量新增),本插件无源码适配需求。
|
|
16
|
+
|
|
17
|
+
### 修复:设置页「供应商」下拉为空
|
|
18
|
+
|
|
19
|
+
设置页 `judgeProvider` 下拉始终为空。根因:0.1.7 起客户端 `connection.api.llm`
|
|
20
|
+
已不存在,store 构造时 `this.llm` 恒为 `null`,`_fetchLlmDirectory()` 直接返回空数组。
|
|
21
|
+
本次改为经客户端 Remote 服务读取:
|
|
22
|
+
|
|
23
|
+
- **供应商**:`ctx.remote.llm.listProviders()`(已注册路由)与
|
|
24
|
+
`listConfigurableProviders()`(已声明可配置)经 `joinProviderDirectory` 合并为与官方
|
|
25
|
+
settings-models 页一致的 `{provider, displayName}` 行。
|
|
26
|
+
- **模型**:`ctx.remote.session.modelCatalog()` 的 `groups`(按 provider 分组),
|
|
27
|
+
与官方同一数据源。
|
|
28
|
+
- **inject**:`package.json` 的 `dsh.client.inject` 与客户端 `inject` 数组新增
|
|
29
|
+
`"remote.llm"`。
|
|
30
|
+
- **降级保留**:无 `remote.llm` 命名空间时回退旧 `connection.api.llm`;目录读取失败
|
|
31
|
+
不致命,仍回退自由文本输入(既有设计不变)。
|
|
6
32
|
|
|
7
|
-
###
|
|
33
|
+
### 测试
|
|
34
|
+
|
|
35
|
+
- 新增 `store-logic.joinProviderDirectory` 与 4 项 `YoloStore` `remote.llm` /
|
|
36
|
+
`remote.session` 单测(目录填充、失败非致命、legacy 回退、remote 优先);
|
|
37
|
+
`npm test` 137 项全绿。
|
|
38
|
+
- 本机无浏览器,客户端 UI 未在浏览器中实际渲染验证;已核对 `npm pack` 产物经
|
|
39
|
+
0.1.7-rc.2 profile 装载后**被服务的**客户端 bundle 含 `remote.llm.listProviders`
|
|
40
|
+
/ `listConfigurableProviders` / `session.modelCatalog`,且宿主 `llm/listProviders`、
|
|
41
|
+
`session/modelCatalog` 实测返回非空目录(供应商下拉将填充 5 项)。
|
|
42
|
+
|
|
43
|
+
### Beta 说明
|
|
8
44
|
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
`lib/remote.js`),`@deepseek-ai/dsh-llm`、`dsh-timeout`、`dsh-settings`、
|
|
12
|
-
`dsh-client-connection`、`dsh-client-ui-slots`、`dsh-client-locale` 的 peer 范围升至
|
|
13
|
-
`^0.1.7-rc.1`,`dsh.compatibility.dshReleases` 新增 `"0.1.7-rc.1": "compatible"`,
|
|
14
|
-
README 徽章与兼容性说明同步。详见下方 `0.5.2` 条目。
|
|
15
|
-
- 发布为 npm 测试版(`--tag beta`);`latest` 保持不变。正式版 `0.5.2` 待 `main` 合并后发布。
|
|
45
|
+
- 测试版 `0.5.2-beta.0`(`--tag beta`)的内容——设置子系统迁移至 DSH 0.1.7 的
|
|
46
|
+
`SettingsForms`——随本版一并正式发布,详见下方 `0.5.2` 条目。
|
|
16
47
|
|
|
17
48
|
## [0.5.2] - 2026-09-24
|
|
18
49
|
|
package/README.md
CHANGED
|
@@ -6,10 +6,12 @@
|
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/dsh-yolo-mode)
|
|
8
8
|
[](LICENSE)
|
|
9
|
-
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
9
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
10
10
|
[](https://awesome-dsh-plugin.com)
|
|
11
11
|
|
|
12
|
-
>
|
|
12
|
+
> **维护状态**:官方已在 DSH 中提供实验性 Auto review 能力(`@deepseek-ai/dsh-experimental-auto-review`,LLM 逐工具授权审查,在 `ask` 审批策略下替代人工审批),与本插件的「LLM 裁判自动审批」功能重叠。因此本插件**可能在未来停止维护**;如需官方原生的自动审批,可评估该实验性功能。当前版本仍会跟进 DSH 兼容(最近实测 **0.1.7-rc.2**)。
|
|
13
|
+
|
|
14
|
+
> **兼容性**:v0.5.3 支持 DSH **0.1.5-rc.1+**,已在 **0.1.5-rc.1 / 0.1.5-rc.2 / 0.1.6-alpha.2 / 0.1.7-rc.1 / 0.1.7-rc.2** 实测(真实-Cordis 探针通过;设置子系统已迁移至 0.1.7 的 `SettingsForms`——插件 Config schema + volatile 热更 + 自建设置页;0.1.7-rc.2 上 provider/model 目录改由 client `remote.llm` + `remote.session` 读取)。旧版 DSH(0.1.0-rc.6 / rc.8)请使用最后兼容的 npm 版本 **0.4.1**。
|
|
13
15
|
|
|
14
16
|
---
|
|
15
17
|
|
package/lib/client/index.js
CHANGED
|
@@ -234,6 +234,42 @@ window.__ModuleLoader__.load({
|
|
|
234
234
|
if (code === "settings-rejected" || code === "schema-validation") return "rejected";
|
|
235
235
|
return "fatal";
|
|
236
236
|
}
|
|
237
|
+
/**
|
|
238
|
+
* Join the live provider routes (`remote.llm.listProviders`, rows `{id, name}`)
|
|
239
|
+
* with the declared configurable providers
|
|
240
|
+
* (`remote.llm.listConfigurableProviders`, rows `{provider, displayName, …}`)
|
|
241
|
+
* into one directory of `{ provider, displayName }` rows the select consumes.
|
|
242
|
+
* Declared entries lead (so a configured-but-not-yet-registered provider still
|
|
243
|
+
* appears), then any registered route the declaration does not name. Mirrors
|
|
244
|
+
* the official settings-models `joinProviderDirectory`.
|
|
245
|
+
*/
|
|
246
|
+
function joinProviderDirectory(registered, declared) {
|
|
247
|
+
const routes = Array.isArray(registered) ? registered : [];
|
|
248
|
+
const directory = Array.isArray(declared) ? declared : [];
|
|
249
|
+
const rows = [];
|
|
250
|
+
const named = /* @__PURE__ */ new Set();
|
|
251
|
+
for (const entry of directory) {
|
|
252
|
+
if (entry === null || typeof entry !== "object") continue;
|
|
253
|
+
if (typeof entry.provider !== "string" || entry.provider === "") continue;
|
|
254
|
+
named.add(entry.provider);
|
|
255
|
+
rows.push({
|
|
256
|
+
provider: entry.provider,
|
|
257
|
+
displayName: typeof entry.displayName === "string" && entry.displayName !== "" ? entry.displayName : void 0,
|
|
258
|
+
active: routes.some((route) => route && route.id === entry.provider)
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
for (const route of routes) {
|
|
262
|
+
if (route === null || typeof route !== "object") continue;
|
|
263
|
+
if (typeof route.id !== "string" || route.id === "") continue;
|
|
264
|
+
if (named.has(route.id)) continue;
|
|
265
|
+
rows.push({
|
|
266
|
+
provider: route.id,
|
|
267
|
+
displayName: typeof route.name === "string" && route.name !== "" ? route.name : void 0,
|
|
268
|
+
active: true
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
return rows;
|
|
272
|
+
}
|
|
237
273
|
//#endregion
|
|
238
274
|
//#region src/client/store.js
|
|
239
275
|
/**
|
|
@@ -266,9 +302,9 @@ window.__ModuleLoader__.load({
|
|
|
266
302
|
writable: true,
|
|
267
303
|
error: void 0,
|
|
268
304
|
open: false,
|
|
269
|
-
/**
|
|
305
|
+
/** Provider directory: remote.llm joined rows, or legacy llm.providers. */
|
|
270
306
|
providers: [],
|
|
271
|
-
/** Model catalog groups
|
|
307
|
+
/** Model catalog groups: remote.session.modelCatalog, or legacy llm.models. */
|
|
272
308
|
models: []
|
|
273
309
|
};
|
|
274
310
|
}
|
|
@@ -279,14 +315,20 @@ window.__ModuleLoader__.load({
|
|
|
279
315
|
* @param {{ call: (channel: string, endpoint: string, payload: any) => Promise<any> }} options.rpc
|
|
280
316
|
* rpc.call(channel, endpoint, payload) resolves to { ok: true, value } |
|
|
281
317
|
* { ok: false, error }.
|
|
282
|
-
* @param {object|null} [options.llm] - optional `connection.api.llm` face
|
|
318
|
+
* @param {object|null} [options.llm] - optional legacy `connection.api.llm` face
|
|
283
319
|
* ({ providers(), models() } returning { result: { ok, value } }); when null
|
|
284
320
|
* the directory stays empty and the judge fields fall back to free text.
|
|
321
|
+
* @param {object|null} [options.remote] - optional client Remote service; when
|
|
322
|
+
* it carries an `llm` namespace the directory comes from
|
|
323
|
+
* `llm.listProviders()` + `llm.listConfigurableProviders()` (0.1.7+) and the
|
|
324
|
+
* model catalog from `session.modelCatalog()`. Falls back to `llm` when the
|
|
325
|
+
* Remote namespace is absent.
|
|
285
326
|
*/
|
|
286
327
|
var YoloStore = class {
|
|
287
|
-
constructor({ rpc, llm }) {
|
|
328
|
+
constructor({ rpc, llm, remote }) {
|
|
288
329
|
this.rpc = rpc;
|
|
289
330
|
this.llm = llm == null ? null : llm;
|
|
331
|
+
this.remote = remote == null ? null : remote;
|
|
290
332
|
this._state = initialYoloState();
|
|
291
333
|
this._listeners = /* @__PURE__ */ new Set();
|
|
292
334
|
this._generation = 0;
|
|
@@ -331,12 +373,54 @@ window.__ModuleLoader__.load({
|
|
|
331
373
|
if (error !== null && typeof error === "object" && typeof error.code === "string") return error.code;
|
|
332
374
|
}
|
|
333
375
|
/**
|
|
334
|
-
* Fetch the optional LLM directory (provider list + model catalog)
|
|
335
|
-
*
|
|
336
|
-
*
|
|
337
|
-
*
|
|
376
|
+
* Fetch the optional LLM directory (provider list + model catalog).
|
|
377
|
+
*
|
|
378
|
+
* 0.1.7+ exposes it through the client Remote service: the provider directory
|
|
379
|
+
* is the join of `remote.llm.listProviders()` (registered routes) and
|
|
380
|
+
* `remote.llm.listConfigurableProviders()` (declared providers), and the model
|
|
381
|
+
* catalog is `remote.session.modelCatalog().value.groups` — the same sources
|
|
382
|
+
* the official settings-models page reads. Older hosts without a Remote `llm`
|
|
383
|
+
* namespace fall back to the legacy `connection.api.llm` face.
|
|
384
|
+
*
|
|
385
|
+
* Directory failures are NOT fatal: they leave the snapshot's providers/models
|
|
386
|
+
* empty without flipping status to 'error' — only the settings/status bridge
|
|
387
|
+
* calls can do that.
|
|
338
388
|
*/
|
|
339
389
|
async _fetchLlmDirectory() {
|
|
390
|
+
const fromRemote = await this._fetchRemoteDirectory();
|
|
391
|
+
if (fromRemote !== void 0) return fromRemote;
|
|
392
|
+
return await this._fetchLegacyDirectory();
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Read the directory from the client Remote service. Returns undefined when
|
|
396
|
+
* no `remote.llm` namespace is present, so the caller can fall back.
|
|
397
|
+
*/
|
|
398
|
+
async _fetchRemoteDirectory() {
|
|
399
|
+
const llm = this.remote ? this.remote.llm : null;
|
|
400
|
+
if (llm === null || llm === void 0) return void 0;
|
|
401
|
+
let providers = [];
|
|
402
|
+
let models = [];
|
|
403
|
+
try {
|
|
404
|
+
const [registered, declared] = await Promise.all([typeof llm.listProviders === "function" ? llm.listProviders() : void 0, typeof llm.listConfigurableProviders === "function" ? llm.listConfigurableProviders() : void 0]);
|
|
405
|
+
providers = joinProviderDirectory(registered && registered.ok === true && Array.isArray(registered.value) ? registered.value : [], declared && declared.ok === true && Array.isArray(declared.value) ? declared.value : []);
|
|
406
|
+
} catch {
|
|
407
|
+
providers = [];
|
|
408
|
+
}
|
|
409
|
+
const session = this.remote ? this.remote.session : null;
|
|
410
|
+
if (session && typeof session.modelCatalog === "function") try {
|
|
411
|
+
const response = await session.modelCatalog();
|
|
412
|
+
const value = response && response.ok === true ? response.value : void 0;
|
|
413
|
+
if (value && Array.isArray(value.groups)) models = value.groups;
|
|
414
|
+
} catch {
|
|
415
|
+
models = [];
|
|
416
|
+
}
|
|
417
|
+
return {
|
|
418
|
+
providers,
|
|
419
|
+
models
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
/** Legacy directory read for hosts whose transport still exposes `api.llm`. */
|
|
423
|
+
async _fetchLegacyDirectory() {
|
|
340
424
|
if (this.llm === null || this.llm === void 0) return {
|
|
341
425
|
providers: [],
|
|
342
426
|
models: []
|
|
@@ -1349,13 +1433,15 @@ window.__ModuleLoader__.load({
|
|
|
1349
1433
|
*/
|
|
1350
1434
|
/**
|
|
1351
1435
|
* Services required by these slot registrations (dsh.client.inject is the same
|
|
1352
|
-
* short-name set): slots, locale, connection, remote.
|
|
1436
|
+
* short-name set): slots, locale, connection, remote, remote.llm. The dotted
|
|
1437
|
+
* `remote.llm` namespace carries the provider/model directory on 0.1.7+.
|
|
1353
1438
|
*/
|
|
1354
1439
|
const inject = [
|
|
1355
1440
|
"slots",
|
|
1356
1441
|
"locale",
|
|
1357
1442
|
"connection",
|
|
1358
|
-
"remote"
|
|
1443
|
+
"remote",
|
|
1444
|
+
"remote.llm"
|
|
1359
1445
|
];
|
|
1360
1446
|
/**
|
|
1361
1447
|
* Register the YOLO section/chip/popup once the slot declarations are on the
|
|
@@ -1374,6 +1460,7 @@ window.__ModuleLoader__.load({
|
|
|
1374
1460
|
const t = ctx.locale.bind(NS);
|
|
1375
1461
|
const store = new YoloStore({
|
|
1376
1462
|
rpc: connection.rpc,
|
|
1463
|
+
remote: ctx.get("remote") ?? null,
|
|
1377
1464
|
llm: connection.api ? connection.api.llm : null
|
|
1378
1465
|
});
|
|
1379
1466
|
const useSnapshot = bindSnapshotSelector(store);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-yolo-mode",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "dsh-yolo-mode —— DeepSeek Harness 双面包插件:当会话处于可写沙箱模式且审批策略为 ask 时,用大模型自动裁决沙箱升权申请,支持内置预设与自定义权限层级,并提供宿主 settings + 自发布设置桥(/yolo-mode)与 Web 客户端 UI。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -74,7 +74,8 @@
|
|
|
74
74
|
"slots",
|
|
75
75
|
"locale",
|
|
76
76
|
"connection",
|
|
77
|
-
"remote"
|
|
77
|
+
"remote",
|
|
78
|
+
"remote.llm"
|
|
78
79
|
]
|
|
79
80
|
},
|
|
80
81
|
"compatibility": {
|
|
@@ -82,7 +83,8 @@
|
|
|
82
83
|
"0.1.5-rc.1": "compatible",
|
|
83
84
|
"0.1.5-rc.2": "compatible",
|
|
84
85
|
"0.1.6-alpha.2": "compatible",
|
|
85
|
-
"0.1.7-rc.1": "compatible"
|
|
86
|
+
"0.1.7-rc.1": "compatible",
|
|
87
|
+
"0.1.7-rc.2": "compatible"
|
|
86
88
|
},
|
|
87
89
|
"node": ">=20"
|
|
88
90
|
}
|