dsh-project-mcp-manager 0.6.0 → 0.7.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 +26 -9
- package/docs/README.zh.md +23 -6
- package/docs/code-review/review-feat-adapt-dsh-0.2.0-rc.2.zh.md +190 -0
- package/docs/design/adaptation-dsh-0.1.6-alpha.2.md +262 -0
- package/docs/design/adaptation-dsh-0.2.0-rc.2.md +89 -0
- package/docs/guide/env-expansion.md +7 -0
- package/docs/guide/env-expansion.zh.md +5 -0
- package/docs/guide/format.md +7 -2
- package/docs/guide/format.zh.md +6 -2
- package/docs/releases/v0.7.0.md +41 -0
- package/docs/releases/v0.7.1.md +49 -0
- package/lib/json-file.js +3 -0
- package/lib/json-write.js +3 -1
- package/lib/model.js +12 -1
- package/lib/registry.js +40 -29
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -9,10 +9,21 @@ session opens in that project. Changes to the file hot-reload into the running
|
|
|
9
9
|
dsh process, and tool visibility is scoped per session cwd. No UI — core
|
|
10
10
|
functionality only.
|
|
11
11
|
|
|
12
|
-
**Capability boundary
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
**Capability boundary** (dsh ≥ 0.2.0-rc.2): the official client owns the
|
|
13
|
+
protocol, reconnect, tool names, resources, and server instructions. Shipped
|
|
14
|
+
profiles already mount shared MCP resource tools. Official configuration is
|
|
15
|
+
a profile-layer Cordis patch (with that layer's own HMR) plus
|
|
16
|
+
`plugin_manager`. This plugin still owns what the host does not:
|
|
17
|
+
|
|
18
|
+
1. Project-level discovery of `<projectRoot>/.dsh/mcp.yml`, `.dsh/mcp.json`,
|
|
19
|
+
and the read-only legacy `.mcp.json`.
|
|
20
|
+
2. Tool visibility isolated by session cwd.
|
|
21
|
+
3. The MCP file format and the `dsh-mcp` CLI.
|
|
22
|
+
|
|
23
|
+
Project-file hot reload is this plugin's file watcher. It does not replace
|
|
24
|
+
official profile HMR. **Transport types are decided by the official client.**
|
|
25
|
+
v0.7.x targets the dsh `0.2.0` line starting at 0.2.0-rc.2. Hosts still on
|
|
26
|
+
dsh 0.1.5 should stay on plugin v0.6.0.
|
|
16
27
|
|
|
17
28
|
If this plugin is useful, a GitHub
|
|
18
29
|
[star](https://github.com/wldxiaobai/dsh-project-mcp-manager) is appreciated.
|
|
@@ -33,11 +44,15 @@ Feature documentation lives in `docs/`, English and Chinese side by side:
|
|
|
33
44
|
its diagnostics.
|
|
34
45
|
- [CLI `dsh-mcp`](docs/guide/cli.md) — scopes, write formats, ownership contract.
|
|
35
46
|
|
|
36
|
-
Design and release records (Chinese): [dsh 0.
|
|
47
|
+
Design and release records (Chinese): [dsh 0.2.0-rc.2 adaptation](docs/design/adaptation-dsh-0.2.0-rc.2.md) ·
|
|
48
|
+
[dsh 0.1.6-alpha.2 adaptation plan](docs/design/adaptation-dsh-0.1.6-alpha.2.md) ·
|
|
49
|
+
[dsh 0.1.5-rc.2 adaptation](docs/design/adaptation-dsh-0.1.5-rc2.md) ·
|
|
37
50
|
[dsh 0.1.5-rc.1 adaptation](docs/design/adaptation-dsh-0.1.5-rc1.md) ·
|
|
38
51
|
[dsh 0.1.2-rc.1 adaptation](docs/design/adaptation-dsh-0.1.2-rc1.md) ·
|
|
39
52
|
[JSON config layer proposal](docs/design/proposal-json-mcp-config.md) ·
|
|
40
53
|
[Runtime robustness & JSON interop proposal](docs/design/proposal-runtime-robustness-and-json-interop.md) ·
|
|
54
|
+
[v0.7.1 release notes](docs/releases/v0.7.1.md) ·
|
|
55
|
+
[v0.7.0 release notes](docs/releases/v0.7.0.md) ·
|
|
41
56
|
[v0.6.0 release notes](docs/releases/v0.6.0.md) ·
|
|
42
57
|
[v0.4.3 release notes](docs/releases/v0.4.3.md) ·
|
|
43
58
|
[v0.4.2 release notes](docs/releases/v0.4.2.md) ·
|
|
@@ -47,7 +62,8 @@ Design and release records (Chinese): [dsh 0.1.5-rc.2 adaptation](docs/design/ad
|
|
|
47
62
|
|
|
48
63
|
Code review records (Chinese): [TypeScript changes since v0.3.1](docs/code-review/ts-review-since-v0.3.1.zh.md) ·
|
|
49
64
|
[v0.4.3 to v0.6.0](docs/code-review/ts-review-v0.4.3-to-v0.6.0.zh.md) ·
|
|
50
|
-
[7e0088d to 804662f (fix follow-up)](docs/code-review/ts-review-7e0088d-to-804662f.zh.md)
|
|
65
|
+
[7e0088d to 804662f (fix follow-up)](docs/code-review/ts-review-7e0088d-to-804662f.zh.md) ·
|
|
66
|
+
[feat/adapt-dsh-0.2.0-rc.2 (v0.7.0)](docs/code-review/review-feat-adapt-dsh-0.2.0-rc.2.zh.md).
|
|
51
67
|
|
|
52
68
|
## Installation (mount into a profile)
|
|
53
69
|
|
|
@@ -74,7 +90,7 @@ dsh plugin --profile web add dsh-project-mcp-manager@latest
|
|
|
74
90
|
|
|
75
91
|
# Install a specific version (check available versions with
|
|
76
92
|
# npm view dsh-project-mcp-manager versions)
|
|
77
|
-
dsh plugin --profile web add dsh-project-mcp-manager@0.
|
|
93
|
+
dsh plugin --profile web add dsh-project-mcp-manager@0.7.1
|
|
78
94
|
```
|
|
79
95
|
|
|
80
96
|
**Option 2: install directly with pnpm** (equivalent to option 1):
|
|
@@ -101,8 +117,9 @@ pnpm add link:<path-to-your-dsh-mcp-project-source> # e.g. D:\dev\dsh-mcp-proj
|
|
|
101
117
|
> trigger the bundle reconcile.
|
|
102
118
|
|
|
103
119
|
**Upgrading / pinning versions**: re-run the `add` command from option 1 with
|
|
104
|
-
the desired version suffix — `@latest` upgrades to the newest release, `@0.
|
|
105
|
-
pins to a specific version.
|
|
120
|
+
the desired version suffix — `@latest` upgrades to the newest release, `@0.7.1`
|
|
121
|
+
pins to a specific version. v0.7.x needs dsh 0.2.0-rc.2 (the `0.2.0` line).
|
|
122
|
+
dsh 0.1.5 keeps working with plugin `@0.6.0`.
|
|
106
123
|
|
|
107
124
|
## Build & test
|
|
108
125
|
|
package/docs/README.zh.md
CHANGED
|
@@ -7,8 +7,19 @@
|
|
|
7
7
|
`@deepseek-ai/dsh-mcp-client`),文件改动热重载到运行中的 dsh 进程,并按
|
|
8
8
|
会话 cwd 控制工具可见性。无 UI,仅具备核心功能。
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
**能力边界**(dsh ≥ 0.2.0-rc.2):协议、重连、工具名、resources 与服务器
|
|
11
|
+
instructions 归官方 client。发行版 profile 已经装了共享的 MCP 资源工具。官方
|
|
12
|
+
配置是 profile 层 Cordis patch(该层自有 HMR)加上 `plugin_manager`。宿主还没做、
|
|
13
|
+
仍由本插件负责的是:
|
|
14
|
+
|
|
15
|
+
1. 项目级发现:`<projectRoot>/.dsh/mcp.yml`、`.dsh/mcp.json`,以及只读的遗留
|
|
16
|
+
`.mcp.json`。
|
|
17
|
+
2. 按会话 cwd 隔离工具可见性。
|
|
18
|
+
3. MCP 专用配置格式和 `dsh-mcp` CLI。
|
|
19
|
+
|
|
20
|
+
项目文件热重载是本插件自己的文件监听,不替代官方 profile HMR。**传输类型由官方
|
|
21
|
+
client 决定。** v0.7.x 面向 dsh `0.2.0` 线(从 0.2.0-rc.2 起)。仍在 dsh 0.1.5
|
|
22
|
+
上的宿主继续用插件 v0.6.0。
|
|
12
23
|
|
|
13
24
|
若这个插件对你有帮助,欢迎给仓库点一颗
|
|
14
25
|
[star](https://github.com/wldxiaobai/dsh-project-mcp-manager)。遇到问题、宿主
|
|
@@ -26,11 +37,15 @@
|
|
|
26
37
|
- [`${VAR}` 展开](guide/env-expansion.zh.md)——装载时插值与对应诊断。
|
|
27
38
|
- [CLI `dsh-mcp`](guide/cli.zh.md)——作用域、写入格式与独占契约。
|
|
28
39
|
|
|
29
|
-
设计与发布记录(中文):[dsh 0.
|
|
40
|
+
设计与发布记录(中文):[dsh 0.2.0-rc.2 适配记录](design/adaptation-dsh-0.2.0-rc.2.md) ·
|
|
41
|
+
[dsh 0.1.6-alpha.2 适配方案](design/adaptation-dsh-0.1.6-alpha.2.md) ·
|
|
42
|
+
[dsh 0.1.5-rc.2 适配记录](design/adaptation-dsh-0.1.5-rc2.md) ·
|
|
30
43
|
[dsh 0.1.5-rc.1 适配记录](design/adaptation-dsh-0.1.5-rc1.md) ·
|
|
31
44
|
[dsh 0.1.2-rc.1 适配记录](design/adaptation-dsh-0.1.2-rc1.md) ·
|
|
32
45
|
[JSON 配置层设计提案](design/proposal-json-mcp-config.md) ·
|
|
33
46
|
[运行时稳健性与 JSON 互通提案](design/proposal-runtime-robustness-and-json-interop.md) ·
|
|
47
|
+
[v0.7.1 发布说明](releases/v0.7.1.md) ·
|
|
48
|
+
[v0.7.0 发布说明](releases/v0.7.0.md) ·
|
|
34
49
|
[v0.6.0 发布说明](releases/v0.6.0.md) ·
|
|
35
50
|
[v0.4.3 发布说明](releases/v0.4.3.md) ·
|
|
36
51
|
[v0.4.2 发布说明](releases/v0.4.2.md) ·
|
|
@@ -40,7 +55,8 @@
|
|
|
40
55
|
|
|
41
56
|
代码审查记录(中文):[v0.3.1 以来 TypeScript 变更审查](code-review/ts-review-since-v0.3.1.zh.md) ·
|
|
42
57
|
[v0.4.3 至 v0.6.0](code-review/ts-review-v0.4.3-to-v0.6.0.zh.md) ·
|
|
43
|
-
[7e0088d 至 804662f(审查落地复查)](code-review/ts-review-7e0088d-to-804662f.zh.md)
|
|
58
|
+
[7e0088d 至 804662f(审查落地复查)](code-review/ts-review-7e0088d-to-804662f.zh.md) ·
|
|
59
|
+
[feat/adapt-dsh-0.2.0-rc.2(v0.7.0)](code-review/review-feat-adapt-dsh-0.2.0-rc.2.zh.md)。
|
|
44
60
|
|
|
45
61
|
## 安装(挂载到 profile)
|
|
46
62
|
|
|
@@ -63,7 +79,7 @@ npm install -g deepseek-ai/dsh # 或从 GitHub 源码安装
|
|
|
63
79
|
dsh plugin --profile web add dsh-project-mcp-manager@latest
|
|
64
80
|
|
|
65
81
|
# 安装指定版本(版本号可先 npm view dsh-project-mcp-manager versions 查看)
|
|
66
|
-
dsh plugin --profile web add dsh-project-mcp-manager@0.
|
|
82
|
+
dsh plugin --profile web add dsh-project-mcp-manager@0.7.1
|
|
67
83
|
```
|
|
68
84
|
|
|
69
85
|
**方式二:直接 pnpm 安装**(与方式一等价):
|
|
@@ -88,7 +104,8 @@ pnpm add link:<你的 dsh-mcp-project 源码目录> # 例如 D:\dev\dsh-mcp-pr
|
|
|
88
104
|
> `dsh-project-mcp-manager` 行)触发 bundle reconcile。
|
|
89
105
|
|
|
90
106
|
**升级/锁定版本**:重跑方式一的 `add` 命令并带上目标版本后缀——`@latest`
|
|
91
|
-
升级到最新,`@0.
|
|
107
|
+
升级到最新,`@0.7.1` 锁定到指定版本。v0.7.x 需要 dsh 0.2.0-rc.2(`0.2.0` 线)。
|
|
108
|
+
dsh 0.1.5 继续用插件 `@0.6.0`。
|
|
92
109
|
|
|
93
110
|
## 构建与测试
|
|
94
111
|
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# 代码审查:feat/adapt-dsh-0.2.0-rc.2(v0.7.0,适配 dsh 0.2.0-rc.2)
|
|
2
|
+
|
|
3
|
+
[← 返回 README](../README.zh.md) | 相关:[上一轮审查(7e0088d 至 804662f)](ts-review-7e0088d-to-804662f.zh.md) ·
|
|
4
|
+
[dsh 0.2.0-rc.2 适配记录](../design/adaptation-dsh-0.2.0-rc.2.md) ·
|
|
5
|
+
[v0.7.0 发布说明](../releases/v0.7.0.md)
|
|
6
|
+
|
|
7
|
+
**审查日期**:2026-09-30 | **分支**:`feat/adapt-dsh-0.2.0-rc.2`(HEAD `1d586a9`)
|
|
8
|
+
**基线**:`dev`(merge-base `1af9887`)| **静态分析**:SonarCloud PR #13
|
|
9
|
+
([issues 列表](https://sonarcloud.io/project/issues?id=wldxiaobai_dsh-project-mcp-manager&pullRequest=13&issueStatuses=OPEN%2CCONFIRMED&s=IMPACT_RANK),
|
|
10
|
+
OPEN/CONFIRMED 共 24 条,技术债合计 120 min)
|
|
11
|
+
|
|
12
|
+
**范围**:4 个 commit,21 文件 `+583 / −954`。代码逻辑只动了 4 个 `src` 文件
|
|
13
|
+
(`model.ts` +23、`registry.ts` +1/−8、`json-file.ts` +2、`json-write.ts` +2/−1),
|
|
14
|
+
其余是依赖、锁文件与文档。
|
|
15
|
+
|
|
16
|
+
| commit | 内容 |
|
|
17
|
+
|---|---|
|
|
18
|
+
| `aea9aea` | `dsh-mcp-client` `^0.1.5-rc.1` → `^0.2.0-rc.2`,cordis `^4.0.2` → `^4.0.4`,重写 `minimumReleaseAgeExclude` |
|
|
19
|
+
| `1893ec5` | 删除 `agent/session-start` 监听 |
|
|
20
|
+
| `b2f945e` | 透传可选 `maxInstructionBytes`(yml / JSON / view / CLI 写 JSON) |
|
|
21
|
+
| `1d586a9` | 版本 0.7.0、CHANGELOG、README、适配记录、发布说明 |
|
|
22
|
+
|
|
23
|
+
**关于 PR #13 的口径**:GitHub 上 PR #13 是 `dev → main`(标题 "Dev",无描述),
|
|
24
|
+
6 个 commit、21 文件 `+844 / −953`。这与本地 `origin/dev..feat/adapt-dsh-0.2.0-rc.2`
|
|
25
|
+
的统计完全一致,即 PR #13 = 本分支 4 个 commit + `1af9887`(0.1.6-alpha.2 方案文档)
|
|
26
|
+
+ `e76eb1c`(README 提示)。因此 Sonar 结果可以直接对应本分支。
|
|
27
|
+
|
|
28
|
+
**方法**:通读 `dev...feat` 全部 diff 与相关上下文;逐条对照 Sonar 问题所在行;
|
|
29
|
+
本地验证见第 5 节。
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 1. 结论
|
|
34
|
+
|
|
35
|
+
**可以合入,建议先处理 S1(未处理的 Promise)。** 本分支自身的改动小而准:
|
|
36
|
+
依赖范围、事件删除、新字段透传三处都和适配记录里的上游变化一一对应,测试覆盖了
|
|
37
|
+
新字段的透传与缺省省略。
|
|
38
|
+
|
|
39
|
+
Sonar 的 24 条问题**没有一条落在本分支改动的行上**:它们全在 `dev` 已有代码里
|
|
40
|
+
(创建日期 2026-08-22 至 2026-09-12,早于本分支),因为 PR 碰了 `registry.ts`
|
|
41
|
+
而被一并列出(S9381/S9382/S9383 是较新的规则编号)。其中只有 3 条 S9383 是真实的
|
|
42
|
+
可靠性问题,其余属于有意设计或风格项。
|
|
43
|
+
|
|
44
|
+
| 级别 | 数量 | 说明 |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| 中 | 1 | S1:构造函数里三处 `enqueue(...)` 未处理 rejection(Sonar S9383 ×3) |
|
|
47
|
+
| 低 | 5 | 分支自身 B1–B4;Sonar S7503 / S9381 风格项 |
|
|
48
|
+
| 接受现状 | 15 | Sonar S9382「循环内 await」:串行化是装载语义的一部分 |
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 2. Sonar 问题逐条研判
|
|
53
|
+
|
|
54
|
+
### 2.1 S9383 Promise 未处理(BUG,可靠性·中)×3 —— **应修**
|
|
55
|
+
|
|
56
|
+
位置:[registry.ts:784](../../src/registry.ts#L784)、[:792](../../src/registry.ts#L792)、[:798](../../src/registry.ts#L798)。
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
ctx.on("agent/created", ({ agent }: any) => {
|
|
60
|
+
if (agent === undefined) return;
|
|
61
|
+
this.enqueue(async () => { ... await this.reconcileAll(); }); // 返回值被丢弃
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`enqueue()` 返回的是 `run`([registry.ts:849-853](../../src/registry.ts#L849-L853)),
|
|
66
|
+
链尾 `this.chain` 吞掉了错误,但 `run` 本身仍会 reject。只要 `resolveProject` 之后的
|
|
67
|
+
`reconcileAll()` 抛出(chokidar `syncWatcher`、`scanProject` 中未捕获的 I/O 等),
|
|
68
|
+
就会产生 unhandled rejection。Node 15+ 默认对 unhandled rejection 直接终止进程;
|
|
69
|
+
宿主是否装了全局处理器本次没有核实,但插件不应依赖这一点。
|
|
70
|
+
|
|
71
|
+
同文件其他调用点(`kick`、`scheduleGraceUnmount`、`kickSweep`、`trackMount`)都已
|
|
72
|
+
`.catch(() => {})`,这三处是遗漏。本分支删除的 `agent/session-start` 监听恰好是第四处
|
|
73
|
+
同类问题,删掉后数量从 4 降到 3。
|
|
74
|
+
|
|
75
|
+
建议:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
void this.enqueue(async () => { ... }).catch((error) => {
|
|
79
|
+
this.ctx.logger.warn(`项目 MCP 对账失败:${error instanceof Error ? error.message : String(error)}`);
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
比 `.catch(() => {})` 多记一条日志,方便定位。可以顺手抽一个
|
|
84
|
+
`private schedule(work)` 统一所有「后台入队」调用。
|
|
85
|
+
|
|
86
|
+
### 2.2 S7503 async 箭头函数里没有 await(CODE_SMELL,低)×2
|
|
87
|
+
|
|
88
|
+
位置:[registry.ts:2208](../../src/registry.ts#L2208)(`serverView`)、[:2240](../../src/registry.ts#L2240)(`snapshot`)。
|
|
89
|
+
|
|
90
|
+
`this.enqueue(async () => this.serverViewFromMemory(...))`:`async` 只是为了满足
|
|
91
|
+
`enqueue` 的 `() => Promise<T>` 签名。行为正确。可改为
|
|
92
|
+
`this.enqueue(() => Promise.resolve(this.serverViewFromMemory(...)))`,
|
|
93
|
+
或者放宽 `enqueue` 的签名为 `() => T | Promise<T>`。优先级低。
|
|
94
|
+
|
|
95
|
+
### 2.3 S9381 嵌套 Promise(CODE_SMELL,低)×2
|
|
96
|
+
|
|
97
|
+
位置:[registry.ts:1826](../../src/registry.ts#L1826)、[:1835](../../src/registry.ts#L1835),
|
|
98
|
+
在 `trackMount` 的 `fiber.then(onActive, onFailed)` 回调里再 `enqueue(...).catch()`。
|
|
99
|
+
|
|
100
|
+
这是有意的:fiber settle 时刻不在对账链上,诊断写必须排回链里以免 RMW 竞态(代码注释
|
|
101
|
+
已写明)。不需要改语义。想消掉告警可以抽 `private enqueueDiag(container, event)`,
|
|
102
|
+
回调里只调一个同步方法。
|
|
103
|
+
|
|
104
|
+
### 2.4 S9382 循环内 await(CODE_SMELL,可维护性·低)×15 —— **建议在 Sonar 标记 Accepted**
|
|
105
|
+
|
|
106
|
+
| 行 | 位置 | 能否并行 | 理由 |
|
|
107
|
+
|---|---|---|---|
|
|
108
|
+
| 800 | 构造补扫 `resolveProject` | 可以但无收益 | 一次性,会话数很小 |
|
|
109
|
+
| 903 | `knownProjects` 的 `findProjectRoot` | 可以 | 只读,`Promise.all` 安全 |
|
|
110
|
+
| 1150、1998 | `liveMountKeys` / `sweepRestrictions` 的 `resolveProject` | 可以但无收益 | 大多命中 `agentProjects` 缓存 |
|
|
111
|
+
| 1251 | 指纹 `statConfigFile` | **可以** | 纯只读 stat,每轮对账都跑,项目多时收益最明显 |
|
|
112
|
+
| 1298、1302 | `scanProject` | 不建议 | 会写诊断、改 `configReadCount`,并发后测试口径和日志顺序会变 |
|
|
113
|
+
| 1320 | 逐项目 `reconcileProject` | 不可以 | 生效名预留与装载顺序依赖串行 |
|
|
114
|
+
| 1589、1600 | 先 unmount 再 mount | **不可以** | AGENTS.md 明确要求同名先释放预留再装载 |
|
|
115
|
+
| 1714、1719 | `writeSummaries` 逐文件写 | 可以但无收益 | 各自有锁,数量小 |
|
|
116
|
+
| 1885、1934 | 健康巡检 remount | 不可以 | 逐条 unmount/mount 改动容器状态 |
|
|
117
|
+
| 2159、2174 | `waitForState` 轮询 `delay(200)` | 不适用 | 轮询本来就要逐次等待(测试辅助) |
|
|
118
|
+
| test-json-file.mjs:258 | 逐文件读 `lib/*.js` | 不适用 | 测试代码 |
|
|
119
|
+
|
|
120
|
+
只有 1251(以及可选的 903)值得改成 `Promise.all`,其余都是装载正确性依赖的串行化。
|
|
121
|
+
建议把其余 13 条在 Sonar 标为 Accepted 并附上「串行化是 reconcile 语义」的理由,
|
|
122
|
+
避免后续有人「按 Sonar 优化」时破坏 unmount → mount 顺序。
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 3. 分支自身的发现
|
|
127
|
+
|
|
128
|
+
### B1(低)`DEFAULT_MAX_INSTRUCTION_BYTES` 是死导出
|
|
129
|
+
|
|
130
|
+
[model.ts:193](../../src/model.ts#L193) 导出了 `32768`,注释说「用于文档与对照」,但
|
|
131
|
+
`src/` 与 `test/` 里没有任何引用。它和上游默认一旦漂移,也没有东西会报错。
|
|
132
|
+
建议删掉,或者在测试里用它断言 `patchRowToView` 缺省时不出现该键,让它有实际用途。
|
|
133
|
+
|
|
134
|
+
### B2(低)`agent/session-start` 删除后缺少回归测试
|
|
135
|
+
|
|
136
|
+
删除本身正确(dsh 0.2 已移除该事件,`agent/created` 带 `source`)。但
|
|
137
|
+
[test-registry.mjs](../../test/test-registry.mjs) 里没有针对 `agent/created` 的用例,
|
|
138
|
+
`resume` / `compact` / `clear` 这些原先靠 session-start 兜底的边沿只有 headless 实机验证。
|
|
139
|
+
建议补一条:fake ctx 触发 `agent/created`(带 `source: "resume"`、已有 `session.header.cwd`),
|
|
140
|
+
断言项目被挂载且 deny 被应用。
|
|
141
|
+
|
|
142
|
+
### B3(低)`maxInstructionBytes` 变化会拆连接,无测试
|
|
143
|
+
|
|
144
|
+
`canonicalConfig` 只剥 `tools`,所以改 `maxInstructionBytes` 会触发 unmount → mount。
|
|
145
|
+
这是正确行为(官方只在连接时读取),但值得一条 `planProjectChanges` 单测固化,
|
|
146
|
+
防止以后有人把它当作「非连接字段」加进剥离列表。
|
|
147
|
+
|
|
148
|
+
### B4(低)view 透传不校验
|
|
149
|
+
|
|
150
|
+
[model.ts:684](../../src/model.ts#L684) 的 `patchRowToView` 只判 `typeof === "number"`,
|
|
151
|
+
手写 yml 里的 `0` 或 `1.5` 会原样出现在 `dsh-mcp get` 里,而装载侧
|
|
152
|
+
(`inputFromPatchRow` → zod)会拒绝并记 `config-invalid`。与 `toolCallTimeoutMs`
|
|
153
|
+
等字段现有口径一致,可以接受;如果要改,应该所有数值字段一起改。
|
|
154
|
+
|
|
155
|
+
### 其他确认项(无问题)
|
|
156
|
+
|
|
157
|
+
- **依赖范围**:`^0.2.0-rc.2` 能解析到 `0.2.0` 正式版与后续 `0.2.x`,不会跨到 `0.3`,
|
|
158
|
+
符合「`0.2.0` 线」的表述。锁文件缩减 ~950 行来自 client 0.2 换掉了一批直接依赖
|
|
159
|
+
(适配记录第 2 节已说明)。
|
|
160
|
+
- **无 `peerDependencies` / `engines`**:0.1.5 宿主装上 v0.7.0 只会在 pnpm 那里看到
|
|
161
|
+
client 的 peer 警告,插件本身不拦。现在靠 README / CHANGELOG 告知「0.1.5 用 v0.6.0」。
|
|
162
|
+
可以考虑在 `activate` 时检测宿主版本并给一条明确告警,但不是本次必须。
|
|
163
|
+
- **缺省不落键**:`toOfficialConfig`、`toJsonEntry`、`patchRowToView`、`inputFromPatchRow`
|
|
164
|
+
四处口径一致,测试覆盖了「缺省不存在该键」和「设置后往返保留」。
|
|
165
|
+
- **文档**:中英文 format / env-expansion 同步;stdio 环境清洗的说明对用户有实际价值
|
|
166
|
+
(只放在环境里、没写进 `env` 的凭据在 0.2 下子进程拿不到了),建议在发布说明里
|
|
167
|
+
把这点列为「升级注意」而非普通变化。
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## 4. 修复优先级建议
|
|
172
|
+
|
|
173
|
+
1. **合入前**:S1(三处 `enqueue` 加 `.catch` + 日志)。改动 3 行,关掉 3 条 Sonar BUG。
|
|
174
|
+
2. **合入前可选**:B1 删死导出;PR #13 补标题与描述(目前标题是 "Dev"、描述为空)。
|
|
175
|
+
3. **后续**:B2、B3 补测试;指纹 stat(1251)改 `Promise.all`;S7503 / S9381 小重构。
|
|
176
|
+
4. **Sonar 操作**:其余 13 条 S9382 标 Accepted 并写理由。
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## 5. 本地验证
|
|
181
|
+
|
|
182
|
+
| 检查 | 结果 |
|
|
183
|
+
|---|---|
|
|
184
|
+
| `tsc --noEmit` | 通过 |
|
|
185
|
+
| 编译到临时目录与 `lib/` 逐文件比哈希 | 11 个 `.js` 全部一致,`lib/` 即本分支源码的产物 |
|
|
186
|
+
| 六套测试(node 直接跑) | 全部通过:model 33 / mcp-file 7 / json-file 13 / json-write 6 / registry 46 / cli 21 |
|
|
187
|
+
|
|
188
|
+
未能执行的部分:`pnpm test` 因 pnpm store 锁文件无访问权限失败,`npm run build` 因
|
|
189
|
+
`lib/` 被占用无法清空(疑似宿主 junction 正在加载),所以改为上面的等价验证。
|
|
190
|
+
headless 实机结论引用自适配记录,本次没有复跑。
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# 适配方案:dsh v0.1.6-alpha.2
|
|
2
|
+
|
|
3
|
+
[← 返回 README](../README.zh.md) | 相关:[dsh 0.1.5-rc.2 适配记录](adaptation-dsh-0.1.5-rc2.md)
|
|
4
|
+
|
|
5
|
+
**状态**:设计决策记录。决策已按 dsh **0.2.0-rc.2** 落地,见
|
|
6
|
+
[v0.7.0 适配记录](adaptation-dsh-0.2.0-rc.2.md)。依赖下限是 `^0.2.0-rc.2`
|
|
7
|
+
(`0.2.0` 元组),不是本文当时写的 `^0.1.6-alpha.2`。**对比基线**:上游 `c291e7961a`
|
|
8
|
+
(`dsh-v0.1.5-rc.2` + 139 提交,即 v0.6.0 的适配基线)→ `dsh-v0.1.6-alpha.2`
|
|
9
|
+
(`ddefc45fbc`,区间 1548 提交)。**记录日期**:2026-09-14。
|
|
10
|
+
本文只定决策与理由,不含实施步骤;实施后按仓库惯例另写验证结论。
|
|
11
|
+
|
|
12
|
+
## 0. 结论一览
|
|
13
|
+
|
|
14
|
+
| # | 决策 | 一句话 |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| D1 | 依赖下限抬到 `^0.1.6-alpha.2`,v0.7.0 支持 dsh ≥ 0.1.6-alpha.2 | 0.1.5 用户停留在 v0.6.0(在 0.1.6 宿主上行为等价,无需回补) |
|
|
17
|
+
| D2 | 删除 `agent/session-start` 监听 | 该事件已从上游删除;其职责由 `agent/created`(新增 `source`)完整吸收 |
|
|
18
|
+
| D3 | 镜像新增可选字段 `maxInstructionBytes` | 现状会静默剥离用户配置,违背字段镜像原则 |
|
|
19
|
+
| D4 | 官方行为收紧只做文档与诊断交代,不改装载逻辑 | 均为 client 内部行为,与能力边界声明一致 |
|
|
20
|
+
| D5 | 重述定位:官方机制关系 + 三点留白 | README 能力边界章节改写 |
|
|
21
|
+
| D6 | 发 v0.7.0(minor),不等 0.1.6 正式版 | 范围 `^0.1.6-alpha.2` 已覆盖 0.1.6 元组后续全部版本 |
|
|
22
|
+
| D7 | 验证设计见 §3 各决策验证要点与 §4 | 单宿主矩阵 + resume 边回归 |
|
|
23
|
+
|
|
24
|
+
## 1. 上游变更与本插件的关系
|
|
25
|
+
|
|
26
|
+
### 1.1 `@deepseek-ai/dsh-mcp-client`(区间 15 个提交)
|
|
27
|
+
|
|
28
|
+
- **MCP SDK 整体更换**:`@modelcontextprotocol/sdk ^1.12.0` → `@modelcontextprotocol/client`
|
|
29
|
+
精确 pin `2.0.0`;协议协商升级(自动选 2026-07-28 协议并回落),stdio 协商先起临时
|
|
30
|
+
探测进程再起服务进程;tools/list 分页移交 SDK。
|
|
31
|
+
- **Config 纯新增、零删除**:两个 transport 分支各新增可选 `maxInstructionBytes`
|
|
32
|
+
(int ≥ 1,默认 32768;`packages/mcp/mcp-client/src/index.ts:129,139`)。传输集合仍为
|
|
33
|
+
`stdio | streamable-http`(无 sse);`serverName` 正则、`command/args/env/cwd`、
|
|
34
|
+
`url/headers`、`toolCallTimeoutMs`、`failOnStartupError`、`reconnect.*`(默认
|
|
35
|
+
500/30000/10)与工具名 `mcp__<serverName>__<raw>` 全部未变。
|
|
36
|
+
- **行为收紧**:legacy `toolResult` 归一化删除(非规范 tools/call 结果直接抛错);
|
|
37
|
+
服务器 instructions 超 `maxInstructionBytes` 拒绝该次连接。
|
|
38
|
+
- **行为修复**:无 tools capability 的资源型服务器从"连接失败进重连"变为"空工具集
|
|
39
|
+
保持连接"。
|
|
40
|
+
- **新能力**:新文件 `server-context.ts` 经可选注入(`mcpResources`、`systemPrompt`)
|
|
41
|
+
为每个实例注册 MCP resources provider 与 `mcp:<serverName>` 系统提示节;新导出
|
|
42
|
+
`createMcpToolDefinition`;新增可选 peer `dsh-mcp-resources`、`dsh-system-prompt`;
|
|
43
|
+
`zod` 移入 devDependencies。
|
|
44
|
+
- **不变**:命名导出函数插件形态(`name`/`inject = ['tools']`/`Config`/`apply`);
|
|
45
|
+
serverName 预留按 `scopeOf(ctx)` 作用域(两版相同);重连策略本体(退避、共享
|
|
46
|
+
预算、串行 sync 队列)未变。
|
|
47
|
+
|
|
48
|
+
### 1.2 mcp-resources 与 profile 装配
|
|
49
|
+
|
|
50
|
+
新包 `@deepseek-ai/dsh-mcp-resources` 进入 base bundle(
|
|
51
|
+
`packages/bundle/base/cordis.patch.yml:478`),所有 shipped profile 默认装载:三个共享
|
|
52
|
+
工具 `list_mcp_resources` / `list_mcp_resource_templates` / `read_mcp_resource`。它是
|
|
53
|
+
纯消费端,不做任何配置装载;**第三方编程式挂载的 client 实例自动获得资源工具与
|
|
54
|
+
提示节**(官方范例即 `packages/experimental/browser-use-runtime/src/mcp.ts`)。
|
|
55
|
+
**mcp-client 本身仍是 opt-in**(`apps/cli/tests/profile-mcp.spec.ts` 断言所有 shipped
|
|
56
|
+
profile 中 mcp-client 行数为 0)。装配生态其余变化:官方 `plugin_manager` 工具 +
|
|
57
|
+
"configuration-only bundle" 模式(官方 skill 教模型自助连 MCP);HMR 配置热重载默认
|
|
58
|
+
开启;`dsh plugin` CLI 与 bundle patch 合成机制不变。
|
|
59
|
+
|
|
60
|
+
### 1.3 宿主核心事件面
|
|
61
|
+
|
|
62
|
+
**`agent/session-start` 事件被删除**(旧 `packages/core/agent/src/runtime-types.ts:316`
|
|
63
|
+
→ 新版无此声明),职责并入 `agent/created`:payload 变为
|
|
64
|
+
`{ agent, source: 'startup'|'resume'|'clear'|'compact', signal? }`,经 `ctx.serial`
|
|
65
|
+
串行派发(`packages/core/agent/src/index.ts:533-553`),每个 agent 条目 announce 一次。
|
|
66
|
+
`agent/disposed` 保留不变。cordis `ctx.on` 不校验事件名
|
|
67
|
+
(`vendor/cordis/src/events.ts:288`)——对已删除事件的监听**不抛错、静默永不触发**。
|
|
68
|
+
`tools.restrict` / `tools.schemas` 签名不变;插件入口 `inject = ["tools","agents"]`
|
|
69
|
+
所依赖的服务面不变。
|
|
70
|
+
|
|
71
|
+
### 1.4 与本插件无关(知悉即可)
|
|
72
|
+
|
|
73
|
+
`packages/experimental` 下的 browser-use/computer-use MCP 驱动为实验性浏览器/电脑
|
|
74
|
+
使用 provider,只消费 mcp-client,与项目级装载无关。`docs/user/guide/mcp-memory.md`
|
|
75
|
+
代表的官方推荐配置方式(`$DSH_HOME` 层 cordis.patch.yml / `--patch` overlay)不含
|
|
76
|
+
项目级发现。
|
|
77
|
+
|
|
78
|
+
## 2. 兼容性矩阵
|
|
79
|
+
|
|
80
|
+
| 插件依赖点 | 0.1.6-alpha.2 现状 | 结论 |
|
|
81
|
+
|---|---|---|
|
|
82
|
+
| `ctx.plugin(mcpClient, config)` 挂载路径与 `apply` 签名 | 未变 | 兼容 |
|
|
83
|
+
| `toOfficialConfig()` 生成的全部字段 | Config 纯新增,旧字段全保留 | 兼容 |
|
|
84
|
+
| 传输集合 `stdio \| streamable-http`、别名与报错文案派生 | 未变 | 兼容,注释中的版本号表述需更新 |
|
|
85
|
+
| `MAX_TIMER_DELAY_MS` / reconnect 上限镜像 | 官方 `resolveReconnectPolicy` 未变 | 兼容 |
|
|
86
|
+
| serverName 正则与 `mcp__<名>__<工具>` 前缀 | 未变 | 兼容(effectiveName 策略不动) |
|
|
87
|
+
| `tools.restrict({deny})` 精确名展开 / `tools.schemas()` | 签名未变 | 兼容 |
|
|
88
|
+
| `agent/created` / `agent/disposed` 监听(解构 `{ agent }`) | payload 新增字段,serial 派发 | 兼容(见 D2) |
|
|
89
|
+
| `agent/session-start` 监听(`src/registry.ts:796`) | **事件已删除,监听静默失效** | 需处理(D2) |
|
|
90
|
+
| 依赖范围 `^0.1.5-rc.1` 解析 `0.1.6-alpha.2` | **不可解析**(semver 预发布规则) | 需处理(D1) |
|
|
91
|
+
| 用户在配置行写 `maxInstructionBytes` | 官方支持,但本插件 schema 会剥离 | 需处理(D3) |
|
|
92
|
+
| zod 直接依赖 | 官方移入 devDeps 不影响本插件(自声明 `zod@^4`) | 兼容 |
|
|
93
|
+
| `dsh plugin` CLI 安装入口 / bundle patch 挂载 | 不变 | 兼容 |
|
|
94
|
+
|
|
95
|
+
## 3. 设计决策
|
|
96
|
+
|
|
97
|
+
### D1 支持矩阵与依赖范围:抬下限 `^0.1.6-alpha.2`
|
|
98
|
+
|
|
99
|
+
**问题**。semver 预发布规则下,`^0.1.5-rc.1` 只能解析 `0.1.5` 元组的预发布与正式版,
|
|
100
|
+
解析不到 `0.1.6-alpha.*`(与 0.1.2 → 0.1.5 时"必须改范围"是同一局面,见
|
|
101
|
+
[rc.2 记录 §2](adaptation-dsh-0.1.5-rc2.md))。若不改:0.1.6 宿主 profile 内安装本
|
|
102
|
+
插件会产生嵌套的 0.1.5-rc.2 副本——旧协议协商、旧行为,且**拿不到 mcp-resources
|
|
103
|
+
协同**(server-context 注册只存在于新代码);双副本还意味着两份模块级
|
|
104
|
+
`activeServerNames` WeakMap,serverName 预留彼此不可见。
|
|
105
|
+
|
|
106
|
+
**决策**。依赖范围抬到 `^0.1.6-alpha.2`;v0.7.0 的支持矩阵定为 **dsh ≥
|
|
107
|
+
0.1.6-alpha.2**;0.1.5 宿主用户继续使用 v0.6.0(npm 两个版本并存,安装文档已按需
|
|
108
|
+
指定版本)。
|
|
109
|
+
|
|
110
|
+
**理由**。
|
|
111
|
+
|
|
112
|
+
1. **宿主副本一致性是挂载路径的正确性前提**。本插件经
|
|
113
|
+
`ctx.plugin(mcpClient, config)` 装载(`src/registry.ts:1762`),必须与宿主共享同一
|
|
114
|
+
份 client 实现;嵌套副本的模块级状态(serverName 预留、SDK Client 类)会与宿主
|
|
115
|
+
副本分叉。抬下限后 0.1.6 宿主内 range 直接命中宿主已解析版本,唯一副本。
|
|
116
|
+
2. **与 0.1.2 → 0.1.5 的既定先例一致**(当时直接抬下限 `^0.1.5-rc.1`),仓库已有
|
|
117
|
+
心智模型与文档表述。
|
|
118
|
+
3. **`^0.1.6-alpha.2` 覆盖 0.1.6 元组后续全部版本**(alpha 后续、rc、正式版均可
|
|
119
|
+
解析),0.1.6 周期内不再需要动范围;0.1.7 出现时按惯例重新评估。
|
|
120
|
+
4. **否决 OR 范围**(`^0.1.5-rc.1 || ^0.1.6-alpha.2`):解析器对 OR 范围独立选版时
|
|
121
|
+
取满足范围的最高版本,0.1.5 宿主内反而嵌套 0.1.6 副本,"双向复用"依赖解析器
|
|
122
|
+
实现细节而不可依赖;且双宿主测试矩阵翻倍,收益仅剩"0.1.5 用户装新版插件"——
|
|
123
|
+
该人群升级插件却没有升级宿主的动机本来就弱。
|
|
124
|
+
5. **否决维持现状**:嵌套旧副本在目标宿主(0.1.6)上丢失本版本最重要的协同收益
|
|
125
|
+
(mcp-resources 自动作用于插件挂载的 server),等于适配目的落空。
|
|
126
|
+
|
|
127
|
+
**后果**。v0.7.0 起README 安装示例的版本说明需注明支持矩阵;0.1.5 用户是稳定人群,
|
|
128
|
+
v0.6.0 在 0.1.6 宿主上的行为等价性论证见 D2,不构成回补义务。
|
|
129
|
+
|
|
130
|
+
### D2 事件面:删除 `agent/session-start`,收敛到 `agent/created`
|
|
131
|
+
|
|
132
|
+
**事实**。上游删除了该事件;本插件在 `src/registry.ts:796` 的监听在新宿主上是
|
|
133
|
+
**静默死代码**(cordis 不校验事件名,不抛错、永不触发)。新 `agent/created` 的
|
|
134
|
+
payload 携带 `source: 'startup'|'resume'|'clear'|'compact'`,经 `ctx.serial` 串行
|
|
135
|
+
派发、每个 agent 条目 announce 一次——即原 `agent/session-start`(含恢复/重挂场景
|
|
136
|
+
补扫)的职责被完整吸收。
|
|
137
|
+
|
|
138
|
+
**决策**。删除该监听,不新增替代注册;现有 `agent/created` 监听
|
|
139
|
+
(`src/registry.ts:781`:`resolveProject` + `reconcileAll`,同步 enqueue)保持原样,
|
|
140
|
+
不改为 await。需要区分边类型的将来需求由 `payload.source` 满足,当前不需要。
|
|
141
|
+
|
|
142
|
+
**理由**。
|
|
143
|
+
|
|
144
|
+
1. 并集保留(两个事件都注册)只在"同时支持新旧宿主"时才有意义;D1 已把支持矩阵
|
|
145
|
+
抬到 0.1.6+,新宿主上 `created(source)` 覆盖全部四条边,死监听没有存在理由。
|
|
146
|
+
2. 监听保持同步 enqueue、不阻塞 serial 派发:装载是尽力而为的 reconcile,不应
|
|
147
|
+
阻塞 agent 激活时序——与旧版行为一致,新版 serial 语义下这一点反而更值得守住。
|
|
148
|
+
3. v0.6.0 在 0.1.6 宿主上的行为等价性:session-start 监听变死代码,但其补扫职责
|
|
149
|
+
由 `created(source=resume|…)` 覆盖,`agent/disposed` 与构造时 `liveAgents()` 补扫
|
|
150
|
+
不变——**旧版插件在新宿主上无行为回归**,这支持 D1 的"0.1.5 用户停留 v0.6.0"
|
|
151
|
+
并降低本次适配的紧迫性。
|
|
152
|
+
|
|
153
|
+
**验证要点**。resume / clear / compact 三条边各触发一次 reconcile(对应旧
|
|
154
|
+
session-start 的全部职责面);插件先于 agent 加载、晚于 agent 加载(热更)两个
|
|
155
|
+
时序的补扫不回归。
|
|
156
|
+
|
|
157
|
+
### D3 新配置字段 `maxInstructionBytes` 的镜像透传
|
|
158
|
+
|
|
159
|
+
**事实**。官方 Config 新增可选 `maxInstructionBytes`(int ≥ 1,默认 32768);
|
|
160
|
+
超限的处置是**拒绝该次连接**——这是一个用户可调的失败模式。本插件的
|
|
161
|
+
`mcpServerInputSchema` 无此字段,zod 默认 strip:用户在 `.dsh/mcp.yml` / JSON 方言
|
|
162
|
+
里写了会被**静默剥离**,永远落回官方默认,且用户无从自救。
|
|
163
|
+
|
|
164
|
+
**决策**。按既有的字段镜像原则(与 `MAX_TIMER_DELAY_MS`、`SUPPORTED_MCP_TRANSPORTS`
|
|
165
|
+
同性质,见 AGENTS.md「关键行为约定」)透传三处:
|
|
166
|
+
|
|
167
|
+
1. `mcpServerInputSchema`(`src/model.ts`)加可选 `maxInstructionBytes`
|
|
168
|
+
(`z.number().int().min(1).optional()`)——只镜像官方存在的边界(int ≥ 1),
|
|
169
|
+
不发明官方没有的上界;
|
|
170
|
+
2. `toOfficialConfig()` 有值时写入该键,缺省不写键(让官方默认生效,不复制
|
|
171
|
+
默认值——默认值属于官方,复制会漂移);
|
|
172
|
+
3. JSON 方言白名单 `jsonServerEntrySchema` + `passthroughKeys()`
|
|
173
|
+
(`src/json-file.ts:132-156`)加同名键。
|
|
174
|
+
|
|
175
|
+
**CLI 不加参数**。理由:`dsh-mcp` CLI 面板输入项面向最常用路径,instructions 字节
|
|
176
|
+
调优是高级场景,写配置文件即可;保持 CLI 表面积稳定(与 `reconnect` 子字段不进
|
|
177
|
+
CLI 同一口径)。
|
|
178
|
+
|
|
179
|
+
**文档**。`docs/guide/format*.md` 字段表补一行:语义(含归属头的服务器 instructions
|
|
180
|
+
字节上限)、默认 32768、超限行为(该服务器连接失败,进官方重连;本插件健康巡检
|
|
181
|
+
按既有 0 工具退避逻辑处理,连续失败满 3 次 `give-up`)。
|
|
182
|
+
|
|
183
|
+
### D4 官方行为收紧:只做文档与诊断交代,不改装载逻辑
|
|
184
|
+
|
|
185
|
+
三条收紧均为 client 内部行为,本插件不拦截、不包装(与 README「能力边界:
|
|
186
|
+
传输类型由官方 client 决定」同一分工):
|
|
187
|
+
|
|
188
|
+
1. **legacy `toolResult` 服务器**(旧版容忍、新版每次调用抛 invalid MCP result):
|
|
189
|
+
文档 FAQ 加一条——升级 0.1.6 后某服务器调用开始报错是服务器端返回非规范结果,
|
|
190
|
+
修复方向在服务器侧(返回规范 content 数组);本插件的 `plugin-throw` /
|
|
191
|
+
健康巡检诊断口径不变(调用期错误不经过插件)。
|
|
192
|
+
2. **instructions 超限拒绝连接**:连接失败走官方重连 → 本插件健康巡检(fiber 世代
|
|
193
|
+
0 工具退避)→ remount 循环 → `give-up`,既有链路自然覆盖;D3 落地后用户可通过
|
|
194
|
+
调大 `maxInstructionBytes` 自救,文档与该字段说明合并交代。
|
|
195
|
+
3. **stdio 协商探测进程**:启动期子进程数与日志文案变化(官方日志新增
|
|
196
|
+
"transport closure could not be confirmed…" 等);本插件无进程数断言,仅文档
|
|
197
|
+
提示一句,避免用户误判为插件行为。
|
|
198
|
+
|
|
199
|
+
### D5 定位重述:官方机制的关系与三点留白
|
|
200
|
+
|
|
201
|
+
**官方已覆盖**(v0.7.0 文档需要承认,避免用户误判被取代):全局/每 profile 声明
|
|
202
|
+
(`$DSH_HOME` 层 `cordis.patch.yml`)、配置热重载(官方 HMR 默认开,作用于
|
|
203
|
+
**profile 配置层**)、运行时装载(`plugin_manager` + configuration-only bundle,官方
|
|
204
|
+
skill 教模型自助)、协议/重连/分页/instructions/resources 全部收进官方
|
|
205
|
+
mcp-client + mcp-resources。
|
|
206
|
+
|
|
207
|
+
**本插件的三点留白**(README「能力边界」章节改写方向):
|
|
208
|
+
|
|
209
|
+
1. **项目级配置发现**:`<projectRoot>/.dsh/mcp.yml|json`(含只读遗留 `.mcp.json`)
|
|
210
|
+
——团队可版本化共享的 per-repo 配置;官方配置全部锚在 `$DSH_HOME` profile 层。
|
|
211
|
+
2. **按会话 cwd 隔离工具可见性**:官方有 scope 机制但无 cwd→配置/scope 的自动映射。
|
|
212
|
+
3. **MCP 专用友好格式 + `dsh-mcp` CLI**:官方要求用户写 Cordis patch 语法(insert
|
|
213
|
+
包装、`!!js`),对普通用户门槛高;官方无 MCP 专用 CLI。
|
|
214
|
+
|
|
215
|
+
**热重载叙述边界**:项目文件热重载(本插件 chokidar,监视对象不在官方 HMR 的
|
|
216
|
+
profile 配置面内,机制不冲突)vs profile 配置热重载(官方 HMR)——文档明确两者
|
|
217
|
+
分工,不再笼统说"热重载"。
|
|
218
|
+
|
|
219
|
+
**协同收益**:升级依赖后(D1),本插件挂载的每个 server 自动获得三个资源工具与
|
|
220
|
+
`mcp:<serverName>` 提示节(mcp-resources 已默认在所有 profile)——README 定位章节
|
|
221
|
+
作为"与官方机制互补"的例证写入。本插件继续不碰协议层与 resources 粘合。
|
|
222
|
+
|
|
223
|
+
### D6 版本与发布策略:v0.7.0,不等 0.1.6 正式版
|
|
224
|
+
|
|
225
|
+
**决策**。以 v0.7.0(minor)发布本次适配;`package.json` 与 `CHANGELOG.md` 同步
|
|
226
|
+
(仓库既定规则)。
|
|
227
|
+
|
|
228
|
+
**理由**。范围抬升(D1)与新字段透传(D3)是行为面变化,不是 bug 修复,minor
|
|
229
|
+
合适;0.6.x 打补丁号会造成"同版本号不同依赖范围"的混乱。alpha dist-tag 已在 npm
|
|
230
|
+
发布,alpha 宿主用户现在就能撞上嵌套副本问题,没有理由压着不发。上游 API 是
|
|
231
|
+
pre-stable(官方 AGENTS 明示),alpha → rc 之间 Config/事件面可能再变:本方案的
|
|
232
|
+
决策框架(§3)按增量核对即可复用,`^0.1.6-alpha.2` 范围已覆盖 0.1.6 元组后续
|
|
233
|
+
版本,官方再动 Config 字段时按 D3 的镜像流程处理,不需要等正式版再一次性做大改。
|
|
234
|
+
|
|
235
|
+
### D7 验证设计(不含步骤)
|
|
236
|
+
|
|
237
|
+
- **单宿主矩阵**:dsh 0.1.6-alpha.2(支持矩阵抬升后不再跑 0.1.5 矩阵);`test/`
|
|
238
|
+
六套全量 + 手工场景。
|
|
239
|
+
- **resume/clear/compact 边回归**:D2 的职责迁移验证;含插件先于/晚于 agent 加载
|
|
240
|
+
两个时序。
|
|
241
|
+
- **`maxInstructionBytes` 端到端**:yml 行与 JSON 行各写一个显式值 → 装载 → 断言
|
|
242
|
+
client 收到该键;缺省行断言键不出现(官方默认生效)。
|
|
243
|
+
- **副本唯一性**:0.1.6 宿主 profile 内安装 v0.7.0 后,
|
|
244
|
+
`pnpm why @deepseek-ai/dsh-mcp-client` 应只有宿主一份。
|
|
245
|
+
- **mcp-resources 协同烟测**:挂载一个带 instructions 的 fixture server,确认
|
|
246
|
+
`mcp:<serverName>` 提示节与资源工具出现(验证 D1 副本一致性带来的协同生效)。
|
|
247
|
+
|
|
248
|
+
## 4. 风险与开放问题
|
|
249
|
+
|
|
250
|
+
1. **pre-stable API**:本方案按 0.1.6-alpha.2 快照决策;0.1.6-rc / 正式发布时官方
|
|
251
|
+
Config、事件面、peer 集合仍可能变动,按 §3 框架增量核对(重点:Config 字段、
|
|
252
|
+
`agent/created` payload、mcp-client peer 清单)。
|
|
253
|
+
2. **战略风险**:官方方向是"一切皆 Cordis 组合 + plugin_manager 自服务"。若上游
|
|
254
|
+
未来补项目级配置发现(本插件留白一),核心价值被替代;D5 的三点留白是当前的
|
|
255
|
+
差异化底线,README 定位随官方演进持续校准。
|
|
256
|
+
3. **嵌套副本的实际解析行为未实测**(0.1.5 宿主安装 v0.7.0 的边缘场景):已通过
|
|
257
|
+
支持矩阵声明规避(该组合不在支持范围),README 版本说明写清即可,不做兼容
|
|
258
|
+
测试投入。
|
|
259
|
+
4. **官方新增可选 peer 的传递影响**:mcp-client 新增 `dsh-mcp-resources` /
|
|
260
|
+
`dsh-system-prompt` 可选 peer,宿主 profile 内两者默认在装载(前者进 base
|
|
261
|
+
bundle),无需本插件干预;若用户在极简 profile(sdk-minimal 之外的自定义组合)
|
|
262
|
+
中缺装,server-context 静默不注册属官方设计,不构成本插件的问题面。
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# 适配记录:dsh v0.2.0-rc.2
|
|
2
|
+
|
|
3
|
+
[← 返回 README](../README.zh.md) | 相关:[dsh 0.1.6-alpha.2 适配方案](adaptation-dsh-0.1.6-alpha.2.md) ·
|
|
4
|
+
[dsh 0.1.5-rc.2 适配记录](adaptation-dsh-0.1.5-rc2.md) ·
|
|
5
|
+
[v0.7.0 发布说明](../releases/v0.7.0.md)
|
|
6
|
+
|
|
7
|
+
**记录日期**:2026-09-30 | **插件**:`dsh-project-mcp-manager` v0.7.0
|
|
8
|
+
**宿主**:本机 `dsh` 0.2.0-rc.2(`dsh --version`)。对照源码
|
|
9
|
+
`D:\Projects\Agent\deepseek-harness`,标签 `dsh-v0.1.5-rc.2` → `dsh-v0.2.0-rc.2`
|
|
10
|
+
(发布包 `@deepseek-ai/dsh-mcp-client@0.2.0-rc.2`、cordis 4.0.4、
|
|
11
|
+
cordis-plugin-include 1.0.9、cordis-plugin-loader 1.0.5)。
|
|
12
|
+
实机只用 **headless** profile(`~/.dsh/profiles/headless` 以 junction 链到本仓库)。
|
|
13
|
+
|
|
14
|
+
**结论**:官方没有接过本插件的项目级发现、按会话 cwd 隔离和 `dsh-mcp` CLI。
|
|
15
|
+
v0.6.0 的依赖范围解析不到 0.2.0 的 client,且 `agent/session-start` 已删除、
|
|
16
|
+
`maxInstructionBytes` 会被静默丢掉。v0.7.0 按这三处对齐后,headless 实机可以
|
|
17
|
+
装载探针并调用 `mcp__compatprobe__probe`。
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 1. 官方已经覆盖、本插件不再独占的能力
|
|
22
|
+
|
|
23
|
+
对照 `packages/mcp` 与 profile 装配(0.1.5-rc.2 之后、0.2.0-rc.2 之前落地,
|
|
24
|
+
0.2.0-rc.2 相对 0.1.6-alpha.2 的 client 源码几乎只剩类型收紧):
|
|
25
|
+
|
|
26
|
+
| 能力 | 官方现状 | 本插件 |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| 全局 / 每 profile 声明 MCP | `$DSH_HOME` 与 profile 的 Cordis patch,一行一个 `dsh-mcp-client` | 用户层 yml/json 仍是更短的写法,挂载后仍是官方 client |
|
|
29
|
+
| profile 配置热重载 | 官方 HMR,作用在 profile 配置层 | 不替代。项目文件仍由本插件 chokidar 监听 |
|
|
30
|
+
| 运行时加服务器 | `plugin_manager` 与 configuration-only bundle | 不替代 |
|
|
31
|
+
| 协议、分页、重连、instructions | client 内建;SDK `@modelcontextprotocol/client@2.0.0` | 不碰协议 |
|
|
32
|
+
| MCP resources 与服务器提示节 | `mcp-resources` 进 base bundle;client 经 `registerServerContext` 登记 | 升级到同一份 client 后,本插件挂上的服务器自动出现在资源工具里 |
|
|
33
|
+
| 工具名 | 干净时仍是 `mcp__<serverName>__<rawName>`;不合函数名契约时追加 12 hex | deny 展开仍用已注册的精确名 |
|
|
34
|
+
|
|
35
|
+
源码与文档里没有 `<projectRoot>/.dsh/mcp.yml`、`.dsh/mcp.json` 或项目级
|
|
36
|
+
`.mcp.json` 的装载器。`docs/user/guide/mcp-memory.md` 仍是 profile overlay。
|
|
37
|
+
会话 cwd 只用于文件工具和工作区指令,没有「cwd → 该项目 MCP 工具可见性」的映射。
|
|
38
|
+
|
|
39
|
+
本插件继续留下的三件事:
|
|
40
|
+
|
|
41
|
+
1. 项目级配置发现(含只读遗留 `.mcp.json`)与六层影子合并。
|
|
42
|
+
2. 按会话 cwd 的 `tools.restrict({ deny })`。
|
|
43
|
+
3. MCP 专用格式与 `dsh-mcp` CLI。
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 2. 对插件有影响的破坏性变更
|
|
48
|
+
|
|
49
|
+
| 点 | 0.1.5-rc.2 → 0.2.0-rc.2 | 处置 |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| 依赖范围 | `^0.1.5-rc.1` 解析不到 `0.2.0-rc.2`(预发布必须同一 major.minor.patch 元组) | 下限改为 `^0.2.0-rc.2`。0.1.5 用户留在 v0.6.0 |
|
|
52
|
+
| `agent/session-start` | 事件删除。`agent/created` 变为 `{ agent, source: 'startup'\|'resume'\|'clear'\|'compact', signal? }`,`ctx.serial` 派发 | 删除该监听。现有 `agent/created` 只解构 `agent`,仍然成立。构造时 `liveAgents()` 补扫保留 |
|
|
53
|
+
| Config | 两个传输各增加可选 `maxInstructionBytes`(int ≥ 1,默认 32768)。超限拒绝这一次连接 | schema / `toOfficialConfig` / JSON 透传。缺省不写键。CLI 不加参数 |
|
|
54
|
+
| cordis | 4.0.2 → 4.0.4。include 1.0.7 → 1.0.9,loader 1.0.3 → 1.0.5 | 开发依赖 `^4.0.4`。`ctx.plugin` / `ctx.on` / `ctx.provide` / `config.patches` 仍在 |
|
|
55
|
+
| client peer | 发布包 peer 钉死 `0.2.0-rc.2`(tools、scope、timeout、attachment、llm、subprocess;resources 与 system-prompt 可选)。直接依赖换成 schemastery、`dsh-util-values`、MCP client SDK 2.0.0 | 锁文件跟着解析。pnpm 12 把这批 rc 写入 `minimumReleaseAgeExclude` |
|
|
56
|
+
| stdio 环境 | 子进程环境 = 清洗后的父环境 + 配置 `env`。名字匹配凭据或 `DSH_*` 的环境变量不继承 | 文档说明。本插件展开进 `env` 的值仍是显式配置 |
|
|
57
|
+
| 结果形状 | 不再接受 legacy `toolResult`;无 tools capability 的服务器保持连接、工具集为空 | 不改装载逻辑。调用期错误仍不经过本插件 |
|
|
58
|
+
| `apply` | 等待初次连接。`failOnStartupError: false` 时失败只打日志并进入官方重连,fiber 仍 resolve | 与现有 `trackMount` 一致:fiber resolve 即 `active`,0 工具的首连交给官方重连 |
|
|
59
|
+
| `tools.restrict` / `schemas()` | 仍要求 agent 作用域上的精确工具名;`schemas()` 多了可选 `deferLoading` | 本插件本来就走 `agent.ctx.tools.restrict` 并按 `name` 读 schema |
|
|
60
|
+
| `session.header.cwd` | 仍在 | 项目发现路径不变 |
|
|
61
|
+
| 传输集合 / serverName / `MAX_TIMER_DELAY_MS` | 仍是 `stdio` \| `streamable-http`,`[A-Za-z0-9_-]{1,32}`,`2147483647` | 常量注释改为 0.2.0-rc.2,值未改 |
|
|
62
|
+
|
|
63
|
+
0.2.0-rc.1 → 0.2.0-rc.2 的 client 源码差异是一处类型断言,没有新的配置字段。
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 3. 实机(headless profile)
|
|
68
|
+
|
|
69
|
+
`dsh --profile headless --dump-config` 合成树含 `# == dsh-project-mcp-manager` /
|
|
70
|
+
`- id: mcp-project`。插件包是 junction:`link:D:/Projects/Agent/dsh-mcp-project`。
|
|
71
|
+
|
|
72
|
+
临时 git 仓库 `compatprobe`(stdio 探针,`initialize` 带回 `instructions: "hello from probe"`,工具 `probe` → `pong:compat-020`):
|
|
73
|
+
|
|
74
|
+
| 检查 | 结果 |
|
|
75
|
+
|---|---|
|
|
76
|
+
| `maxInstructionBytes: 16` | 子进程收到 `initialize` 与 `notifications/initialized`,**没有** `tools/list`(超限发生在同步工具之前)。`failOnStartupError` 默认 false,诊断仍记 `active` |
|
|
77
|
+
| `maxInstructionBytes: 65536` | 收到 `tools/list`。模型调用 `mcp__compatprobe__probe` → `pong:compat-020` |
|
|
78
|
+
| mcp-resources 协同 | 同一轮里 `list_mcp_resources` 的 `server` 参数接受 `compatprobe`(共享资源工具能看见本插件挂上的服务器) |
|
|
79
|
+
| 单测 | `pnpm test` 六套全绿 |
|
|
80
|
+
|
|
81
|
+
未改本机 `~/.dsh` 的模型设置。headless 使用当前默认模型完成了上述调用。
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 4. 代码改动
|
|
86
|
+
|
|
87
|
+
- `package.json`:`dsh-mcp-client` `^0.2.0-rc.2`,`cordis` `^4.0.4`,版本 0.7.0。
|
|
88
|
+
- `src/registry.ts`:去掉 `agent/session-start`。
|
|
89
|
+
- `src/model.ts`、`src/json-file.ts`、`src/json-write.ts`:透传 `maxInstructionBytes`。
|
|
@@ -24,3 +24,10 @@ the reason rides on a separate `skipReason` field (`env-missing` /
|
|
|
24
24
|
[configuration sources and layers](layers.md)). Values are never
|
|
25
25
|
persisted anywhere by the plugin; the CLI writes `${VAR}` through literally,
|
|
26
26
|
so secrets can live in the environment while configs live in git.
|
|
27
|
+
|
|
28
|
+
From dsh 0.2, the official stdio transport builds the child environment from a
|
|
29
|
+
scrubbed parent (ambient names matching `/KEY|PASSWORD|SECRET|TOKEN/i` and
|
|
30
|
+
ambient `DSH_*` are dropped) and then overlays the configured `env`. A secret
|
|
31
|
+
this plugin interpolates into `env` or `headers` is explicit config and is
|
|
32
|
+
kept. A secret that exists only as an ambient variable, and is not written
|
|
33
|
+
into `env`, is no longer inherited by the child.
|
|
@@ -18,3 +18,8 @@
|
|
|
18
18
|
`plugin-throw`;其它如 `name-taken` / `idle` / `give-up` 见
|
|
19
19
|
[配置来源与分层](layers.zh.md))。插件任何写路径都不落盘展开后的值;
|
|
20
20
|
CLI 写入时 `${VAR}` 原样保留——配置可以进 git,凭据留在环境里。
|
|
21
|
+
|
|
22
|
+
dsh 0.2 起,官方 stdio 传输的子进程环境是「清洗后的父进程环境 + 配置里的
|
|
23
|
+
`env`」。父进程里名字匹配 `/KEY|PASSWORD|SECRET|TOKEN/i` 的变量,以及环境中的
|
|
24
|
+
`DSH_*`,不会继承给子进程。本插件把 `${VAR}` 展开进 `env` / `headers` 的值属于
|
|
25
|
+
显式配置,会保留。只存在于环境、没有写进 `env` 的凭据,子进程再也拿不到。
|
package/docs/guide/format.md
CHANGED
|
@@ -67,7 +67,12 @@ file fail with an explicit error (logged and written to `.dsh/.mcp-diag.json`)
|
|
|
67
67
|
instead of silently mounting the expression text as a literal string. Values
|
|
68
68
|
in `env`/`headers` are otherwise literal, except for `${VAR}` references
|
|
69
69
|
which are interpolated at mount time (see [`${VAR}` expansion](env-expansion.md));
|
|
70
|
-
`disabled` must be `true`/`false`.
|
|
70
|
+
`disabled` must be `true`/`false`. Optional `maxInstructionBytes` (integer ≥ 1)
|
|
71
|
+
is the official cap on attributed server instructions, default 32768 when the
|
|
72
|
+
key is omitted. An oversized instruction rejects that connection inside
|
|
73
|
+
`dsh-mcp-client` (the row still activates when `failOnStartupError` is false,
|
|
74
|
+
then follows the official reconnect loop). `dsh-mcp` has no flag for this
|
|
75
|
+
field; write it in the file. The project file is otherwise a superset
|
|
71
76
|
grammar: `env`/`headers` accept `KEY: null` to delete a key (stripped at
|
|
72
77
|
mount), which the official mcp-client schema rejects — such lines would fail
|
|
73
78
|
if moved back to `cordis.patch.yml`.
|
|
@@ -97,7 +102,7 @@ Follows the ecosystem (Cursor / Claude Code's `mcpServers` shape):
|
|
|
97
102
|
already speaks Streamable HTTP, change `type` to `"http"`; or drop `type`
|
|
98
103
|
and keep `url` (this plugin infers streamable-http). There is no implicit
|
|
99
104
|
fallback. The DSH passthrough keys
|
|
100
|
-
`toolCallTimeoutMs`/`failOnStartupError`/`reconnect`, `enabled: false`
|
|
105
|
+
`toolCallTimeoutMs`/`failOnStartupError`/`maxInstructionBytes`/`reconnect`, `enabled: false`
|
|
101
106
|
(silently skipped, claims no name) and `disabled: true` (claims its name but
|
|
102
107
|
is not mounted).
|
|
103
108
|
- Unknown keys are tolerated and ignored; names must match
|
package/docs/guide/format.zh.md
CHANGED
|
@@ -62,7 +62,11 @@ process.env.GITHUB_TOKEN }`)在项目文件里**不支持**——受管块内
|
|
|
62
62
|
标签会使该文件整体报错跳过(写入 `.dsh/.mcp-diag.json` 并打日志),不会把
|
|
63
63
|
表达式当字面量字符串静默装载。`env`/`headers` 的值其余情况下是字面量,仅
|
|
64
64
|
`${VAR}` 引用会在装载时做串内插值(见 [`${VAR}` 展开](env-expansion.zh.md));
|
|
65
|
-
`disabled` 只能是 `true`/`false
|
|
65
|
+
`disabled` 只能是 `true`/`false`。可选 `maxInstructionBytes`(整数 ≥ 1)是官方对
|
|
66
|
+
「带归属头的服务器 instructions」的字节上限;省略该键时用官方默认 32768。
|
|
67
|
+
超限由 `dsh-mcp-client` 拒绝这一次连接(`failOnStartupError` 为 false 时本插件
|
|
68
|
+
仍把 fiber 标成 active,随后走官方重连)。`dsh-mcp` 没有对应参数,直接写进文件。
|
|
69
|
+
反之项目文件是超集语法:`env`/`headers`
|
|
66
70
|
允许 `KEY: null` 表示删除该键(装载时被剔除),这在官方 mcp-client 校验里会被
|
|
67
71
|
拒绝——把这类行原样挪回 `cordis.patch.yml` 会装载失败。
|
|
68
72
|
|
|
@@ -89,7 +93,7 @@ process.env.GITHUB_TOKEN }`)在项目文件里**不支持**——受管块内
|
|
|
89
93
|
(`dsh-mcp-client`)只支持 `stdio` 与 streamable-http——服务端已支持
|
|
90
94
|
Streamable HTTP 时把 `type` 改为 `"http"`;或删除 `type` 只留 `url`
|
|
91
95
|
(本插件按 streamable-http 推断)。没有隐式回退。DSH 透传键
|
|
92
|
-
`toolCallTimeoutMs`/`failOnStartupError`/`reconnect`、`enabled: false`
|
|
96
|
+
`toolCallTimeoutMs`/`failOnStartupError`/`maxInstructionBytes`/`reconnect`、`enabled: false`
|
|
93
97
|
(静默跳过、不占名)与 `disabled: true`(占名但不装载)。
|
|
94
98
|
- 未知键容忍忽略;名字须匹配 `[A-Za-z0-9_-]{1,32}`;坏条目逐条报错、不影响其余。
|
|
95
99
|
- **JSON 文件由 `dsh-mcp` CLI 独占**:写入保留其他顶层键与键序,但 JSON 没有注释,
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# 发布说明 v0.7.0(适配 dsh 0.2.0-rc.2)
|
|
2
|
+
|
|
3
|
+
[← 返回 README](../README.zh.md) | 相关:[适配记录](../design/adaptation-dsh-0.2.0-rc.2.md) ·
|
|
4
|
+
[v0.6.0 发布说明](v0.6.0.md) ·
|
|
5
|
+
[0.1.6-alpha.2 适配方案](../design/adaptation-dsh-0.1.6-alpha.2.md)
|
|
6
|
+
|
|
7
|
+
**发布日期**:2026-09-30 | **区间**:`v0.6.0 → v0.7.0`
|
|
8
|
+
**宿主**:dsh `0.2.0` 线,从 `0.2.0-rc.2` 起。dsh 0.1.5 继续使用插件 v0.6.0。
|
|
9
|
+
|
|
10
|
+
官方 dsh 仍不发现项目级 MCP 文件、不按会话 cwd 隔离工具、也没有 MCP 专用 CLI。
|
|
11
|
+
v0.7.0 把装载后端对齐到宿主自带的 `@deepseek-ai/dsh-mcp-client@0.2.0-rc.2`,
|
|
12
|
+
并补上这一版新增的配置字段。
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 亮点速览
|
|
17
|
+
|
|
18
|
+
| 主题 | 一句话 |
|
|
19
|
+
|---|---|
|
|
20
|
+
| 依赖下限 | `@deepseek-ai/dsh-mcp-client` 抬到 `^0.2.0-rc.2`;cordis 开发依赖 `^4.0.4` |
|
|
21
|
+
| 会话事件 | 删除已不存在的 `agent/session-start`;补扫由 `agent/created`(含 `source`)承担 |
|
|
22
|
+
| instructions 上限 | 可选透传 `maxInstructionBytes`;缺省不写键,官方默认 32768 |
|
|
23
|
+
| 定位 | 承认官方 profile patch / HMR / resources;本插件留下项目发现、会话隔离、CLI |
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 用户可见变化
|
|
28
|
+
|
|
29
|
+
- 支持矩阵改为 **dsh ≥ 0.2.0-rc.2**(`0.2.0` 元组)。`^0.1.5-rc.1` 解析不到
|
|
30
|
+
`0.2.0-rc.*`,不改范围就会在新宿主里嵌一套旧 client。
|
|
31
|
+
- `.dsh/mcp.yml` 与 JSON 方言可以写 `maxInstructionBytes`(整数 ≥ 1)。省略时
|
|
32
|
+
不把 32768 抄进配置。超限由官方 client 拒绝该次连接。`dsh-mcp` 不增加对应参数。
|
|
33
|
+
- 官方 stdio 会丢掉父进程里名字像凭据的环境变量和 `DSH_*`。写进 `env` 并经
|
|
34
|
+
`${VAR}` 展开的值仍然传给子进程。
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 验证
|
|
39
|
+
|
|
40
|
+
`pnpm test` 六套全绿(model 33 / mcp-file 7 / json-file 13 / json-write 6 /
|
|
41
|
+
registry 46 / cli 21)。headless profile 实机见适配记录。
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# 发布说明 v0.7.1(代码审查整改)
|
|
2
|
+
|
|
3
|
+
[← 返回 README](../README.zh.md) | 相关:[审查记录](../code-review/review-feat-adapt-dsh-0.2.0-rc.2.zh.md) ·
|
|
4
|
+
[v0.7.0 发布说明](v0.7.0.md) ·
|
|
5
|
+
[dsh 0.2.0-rc.2 适配记录](../design/adaptation-dsh-0.2.0-rc.2.md)
|
|
6
|
+
|
|
7
|
+
**发布日期**:2026-09-30 | **区间**:`v0.7.0 → v0.7.1`
|
|
8
|
+
**宿主**:dsh `0.2.0` 线(从 `0.2.0-rc.2` 起),与 v0.7.0 相同;纯补丁版,配置口径与装载语义不变。
|
|
9
|
+
|
|
10
|
+
v0.7.1 只落地 [feat/adapt-dsh-0.2.0-rc.2 代码审查](../code-review/review-feat-adapt-dsh-0.2.0-rc.2.zh.md)
|
|
11
|
+
的意见:一处可靠性修复、一处死代码清理、两条回归测试,以及不改变语义的小重构。
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 亮点速览
|
|
16
|
+
|
|
17
|
+
| 主题 | 一句话 |
|
|
18
|
+
|---|---|
|
|
19
|
+
| 后台任务失败可见 | 所有不 await 的入队统一走 `schedule()`,失败记一条 warn(原先完全静默) |
|
|
20
|
+
| 死导出 | 删除无人引用的 `DEFAULT_MAX_INSTRUCTION_BYTES`,避免与上游默认漂移 |
|
|
21
|
+
| 回归测试 | 覆盖 `agent/created`(`source: "resume"`)事件路径与「连接字段变更必拆连接」的装载计划 |
|
|
22
|
+
| 小重构 | 抽 `enqueueDiag()`、放宽 `enqueue()` 签名;配置指纹的 `stat` 并发发起 |
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 变更明细
|
|
27
|
+
|
|
28
|
+
- **后台入队(审查 S1 / Sonar S9383)**:构造函数的 `agent/created`、`agent/disposed`
|
|
29
|
+
与插件热更补扫三处,加上文件事件 `kick`、宽限卸载 timer、`kickSweep`,全部改走新的
|
|
30
|
+
`schedule()`——`enqueue()` 的返回值不再被丢弃,失败会记一条
|
|
31
|
+
`项目 MCP 后台任务失败:<原因>`。此前这类失败被链路完全吞掉:对账没跑成,日志里
|
|
32
|
+
什么也看不到。诊断落盘(fiber settle 后的 `active` / `failed`)仍走独立的
|
|
33
|
+
`enqueueDiag()`:同样排回对账链,但按最佳努力静默失败。
|
|
34
|
+
- **死代码(审查 B1)**:删掉 `DEFAULT_MAX_INSTRUCTION_BYTES`。「缺省不写键、让官方
|
|
35
|
+
默认值生效」的口径由字段注释与四处输出(官方配置 / 受管行 / view / JSON 条目)的
|
|
36
|
+
测试固定,不需要再在本地留一份 32768。
|
|
37
|
+
- **回归测试(审查 B2、B3)**:新增两条用例——
|
|
38
|
+
`agent/created` 带 `source: "resume"` 时补扫并挂载会话项目,且对被自己项目行遮蔽的
|
|
39
|
+
全局实例应用 deny(项目侧压制展开成精确工具名);`planProjectChanges` 在
|
|
40
|
+
`maxInstructionBytes` 这类连接字段变化时产出 unmount → mount,而 `tools` 变化不拆连接。
|
|
41
|
+
- **小重构(审查 S7503、S9381、S9382)**:`enqueue()` 签名放宽为 `() => T | Promise<T>`,
|
|
42
|
+
`serverView()` / `snapshot()` 去掉只为满足签名的 `async`;`trackMount` 的 fiber settle
|
|
43
|
+
回调改调 `enqueueDiag()`,消掉嵌套 Promise;配置指纹的逐文件 `stat` 改 `Promise.all`
|
|
44
|
+
并发发起(签名仍按排序后的路径逐条拼接,结果与串行一致)。
|
|
45
|
+
|
|
46
|
+
## 验证
|
|
47
|
+
|
|
48
|
+
`tsc --noEmit` 通过;六套测试全绿(model 33 / mcp-file 7 / json-file 13 /
|
|
49
|
+
json-write 6 / registry 48 / cli 21,registry 比 v0.7.0 多两条新用例)。
|
package/lib/json-file.js
CHANGED
|
@@ -82,6 +82,7 @@ export const jsonServerEntrySchema = z.looseObject({
|
|
|
82
82
|
disabled: z.boolean().optional(),
|
|
83
83
|
toolCallTimeoutMs: z.number().int().min(1).optional(),
|
|
84
84
|
failOnStartupError: z.boolean().optional(),
|
|
85
|
+
maxInstructionBytes: z.number().int().min(1).optional(),
|
|
85
86
|
reconnect: jsonReconnectSchema,
|
|
86
87
|
tools: z.object({
|
|
87
88
|
allow: z.array(z.string()).optional(),
|
|
@@ -100,6 +101,8 @@ function passthroughKeys(entry) {
|
|
|
100
101
|
out.toolCallTimeoutMs = entry.toolCallTimeoutMs;
|
|
101
102
|
if (entry.failOnStartupError !== undefined)
|
|
102
103
|
out.failOnStartupError = entry.failOnStartupError;
|
|
104
|
+
if (entry.maxInstructionBytes !== undefined)
|
|
105
|
+
out.maxInstructionBytes = entry.maxInstructionBytes;
|
|
103
106
|
if (entry.reconnect !== undefined)
|
|
104
107
|
out.reconnect = entry.reconnect;
|
|
105
108
|
return out;
|
package/lib/json-write.js
CHANGED
|
@@ -127,7 +127,7 @@ function assignJsonTools(entry, input) {
|
|
|
127
127
|
/**
|
|
128
128
|
* 官方输入 → JSON 条目(Cursor/CC 方言 + DSH 透传键)。
|
|
129
129
|
* 缺省值不落盘(`args: []`、空 `env`/`headers`、空或 "." 的 `cwd`、默认
|
|
130
|
-
* `toolCallTimeoutMs`/`failOnStartupError`/`reconnect`),保持文件简洁可读。
|
|
130
|
+
* `toolCallTimeoutMs`/`failOnStartupError`/`maxInstructionBytes`/`reconnect`),保持文件简洁可读。
|
|
131
131
|
* `${VAR}` 原样保留,装载时才展开——凭据不落盘。
|
|
132
132
|
*/
|
|
133
133
|
export function toJsonEntry(input) {
|
|
@@ -137,6 +137,8 @@ export function toJsonEntry(input) {
|
|
|
137
137
|
entry.toolCallTimeoutMs = input.toolCallTimeoutMs;
|
|
138
138
|
if (input.failOnStartupError !== false)
|
|
139
139
|
entry.failOnStartupError = input.failOnStartupError;
|
|
140
|
+
if (input.maxInstructionBytes !== undefined)
|
|
141
|
+
entry.maxInstructionBytes = input.maxInstructionBytes;
|
|
140
142
|
if (reconnectDiffersFromDefault(input.reconnect))
|
|
141
143
|
entry.reconnect = { ...input.reconnect };
|
|
142
144
|
assignJsonTools(entry, input);
|
package/lib/model.js
CHANGED
|
@@ -202,7 +202,7 @@ const secretMapSchema = z.record(z.string(), z.string().nullable()).optional();
|
|
|
202
202
|
*/
|
|
203
203
|
export const MAX_TIMER_DELAY_MS = 2147483647;
|
|
204
204
|
/**
|
|
205
|
-
* 官方 `@deepseek-ai/dsh-mcp-client` 0.
|
|
205
|
+
* 官方 `@deepseek-ai/dsh-mcp-client` 0.2.0-rc.2 支持的 MCP 传输集合
|
|
206
206
|
* (config.transport 判别联合:`stdio` | `streamable-http`)。本插件不实现
|
|
207
207
|
* 传输,只负责表达;schema / CLI / JSON 读取器 / 报错文案全部从这里派生。
|
|
208
208
|
* 官方新增传输时:常量加值 + 一条 CLI/JSON 别名映射 + 文档 + 测试,不要再
|
|
@@ -271,6 +271,8 @@ export function parseCliTransport(value) {
|
|
|
271
271
|
return { error: unsupportedTransportMessage(value) };
|
|
272
272
|
return { error: `--transport 只支持 stdio|http(别名 streamable-http),收到:${value}` };
|
|
273
273
|
}
|
|
274
|
+
/** 官方可选字段:整数 ≥ 1。缺省不写,让上游默认 32768 生效。 */
|
|
275
|
+
const maxInstructionBytesSchema = z.number().int().min(1).optional();
|
|
274
276
|
const reconnectSchema = z.object({
|
|
275
277
|
enabled: z.boolean().default(DEFAULT_RECONNECT.enabled),
|
|
276
278
|
initialDelayMs: z.number().int().min(1).max(MAX_TIMER_DELAY_MS).default(DEFAULT_RECONNECT.initialDelayMs),
|
|
@@ -286,6 +288,7 @@ export const stdioServerSchema = z.object({
|
|
|
286
288
|
cwd: z.string().default(""),
|
|
287
289
|
toolCallTimeoutMs: z.number().int().min(1).default(DEFAULT_TOOL_CALL_TIMEOUT_MS),
|
|
288
290
|
failOnStartupError: z.boolean().default(false),
|
|
291
|
+
maxInstructionBytes: maxInstructionBytesSchema,
|
|
289
292
|
reconnect: reconnectSchema,
|
|
290
293
|
tools: toolFilterSchema
|
|
291
294
|
});
|
|
@@ -296,6 +299,7 @@ export const httpServerSchema = z.object({
|
|
|
296
299
|
headers: secretMapSchema,
|
|
297
300
|
toolCallTimeoutMs: z.number().int().min(1).default(DEFAULT_TOOL_CALL_TIMEOUT_MS),
|
|
298
301
|
failOnStartupError: z.boolean().default(false),
|
|
302
|
+
maxInstructionBytes: maxInstructionBytesSchema,
|
|
299
303
|
reconnect: reconnectSchema,
|
|
300
304
|
tools: toolFilterSchema
|
|
301
305
|
});
|
|
@@ -462,12 +466,17 @@ function normalizeReconnect(input) {
|
|
|
462
466
|
maxAttempts: input.reconnect.maxAttempts
|
|
463
467
|
};
|
|
464
468
|
}
|
|
469
|
+
/** 用户显式给出才写入;缺省省略,由官方 schema 的 default 生效。 */
|
|
470
|
+
function instructionBytesField(input) {
|
|
471
|
+
return input.maxInstructionBytes === undefined ? {} : { maxInstructionBytes: input.maxInstructionBytes };
|
|
472
|
+
}
|
|
465
473
|
/** 面板输入 → 官方 @deepseek-ai/dsh-mcp-client 配置。 */
|
|
466
474
|
export function toOfficialConfig(input) {
|
|
467
475
|
const common = {
|
|
468
476
|
serverName: input.serverName,
|
|
469
477
|
toolCallTimeoutMs: input.toolCallTimeoutMs,
|
|
470
478
|
failOnStartupError: input.failOnStartupError,
|
|
479
|
+
...instructionBytesField(input),
|
|
471
480
|
reconnect: normalizeReconnect(input)
|
|
472
481
|
};
|
|
473
482
|
if (input.transport === "stdio") {
|
|
@@ -584,6 +593,7 @@ export function patchRowToView(row, scope, effectiveServerName) {
|
|
|
584
593
|
...(tools === undefined ? {} : { tools }),
|
|
585
594
|
toolCallTimeoutMs: asNumber(config.toolCallTimeoutMs, DEFAULT_TOOL_CALL_TIMEOUT_MS),
|
|
586
595
|
failOnStartupError: asBoolean(config.failOnStartupError, false),
|
|
596
|
+
...(typeof config.maxInstructionBytes === "number" ? { maxInstructionBytes: config.maxInstructionBytes } : {}),
|
|
587
597
|
reconnect: reconnectViewOf(config)
|
|
588
598
|
};
|
|
589
599
|
}
|
|
@@ -601,6 +611,7 @@ export function inputFromPatchRow(row) {
|
|
|
601
611
|
serverName,
|
|
602
612
|
toolCallTimeoutMs: asNumber(config.toolCallTimeoutMs, DEFAULT_TOOL_CALL_TIMEOUT_MS),
|
|
603
613
|
failOnStartupError: asBoolean(config.failOnStartupError, false),
|
|
614
|
+
...(typeof config.maxInstructionBytes === "number" ? { maxInstructionBytes: config.maxInstructionBytes } : {}),
|
|
604
615
|
reconnect: {
|
|
605
616
|
enabled: asBoolean(config.reconnect?.enabled, DEFAULT_RECONNECT.enabled),
|
|
606
617
|
initialDelayMs: asNumber(config.reconnect?.initialDelayMs, DEFAULT_RECONNECT.initialDelayMs),
|
package/lib/registry.js
CHANGED
|
@@ -525,10 +525,11 @@ export class ProjectMcpRegistry {
|
|
|
525
525
|
constructor(ctx, providers) {
|
|
526
526
|
this.ctx = ctx;
|
|
527
527
|
this.providers = providers;
|
|
528
|
+
// dsh 0.2 的 agent/created 带 source(startup|resume|clear|compact),覆盖原 session-start 的补扫。
|
|
528
529
|
ctx.on("agent/created", ({ agent }) => {
|
|
529
530
|
if (agent === undefined)
|
|
530
531
|
return;
|
|
531
|
-
this.
|
|
532
|
+
this.schedule(async () => {
|
|
532
533
|
this.agentProjects.set(agent.id, await this.resolveProject(agent));
|
|
533
534
|
await this.reconcileAll();
|
|
534
535
|
});
|
|
@@ -537,21 +538,12 @@ export class ProjectMcpRegistry {
|
|
|
537
538
|
if (agent === undefined)
|
|
538
539
|
return;
|
|
539
540
|
this.releaseAgent(agent);
|
|
540
|
-
this.
|
|
541
|
-
await this.reconcileAll();
|
|
542
|
-
});
|
|
543
|
-
});
|
|
544
|
-
// 会话生命周期开始(含恢复/重挂的会话)也补扫一次,覆盖启动时序缺口。
|
|
545
|
-
ctx.on("agent/session-start", ({ agent }) => {
|
|
546
|
-
if (agent === undefined)
|
|
547
|
-
return;
|
|
548
|
-
this.enqueue(async () => {
|
|
549
|
-
this.agentProjects.set(agent.id, await this.resolveProject(agent));
|
|
541
|
+
this.schedule(async () => {
|
|
550
542
|
await this.reconcileAll();
|
|
551
543
|
});
|
|
552
544
|
});
|
|
553
545
|
// 插件热更重载时已存在的会话也要覆盖。
|
|
554
|
-
this.
|
|
546
|
+
this.schedule(async () => {
|
|
555
547
|
for (const agent of this.liveAgents()) {
|
|
556
548
|
this.agentProjects.set(agent.id, await this.resolveProject(agent));
|
|
557
549
|
}
|
|
@@ -607,14 +599,26 @@ export class ProjectMcpRegistry {
|
|
|
607
599
|
this.chain = run.then(() => undefined, () => undefined);
|
|
608
600
|
return run;
|
|
609
601
|
}
|
|
602
|
+
/**
|
|
603
|
+
* 后台入队(fire-and-forget):所有不 await 的入队都走这里。`enqueue` 的链尾
|
|
604
|
+
* (`this.chain = run.then(...)`)本就替 `run` 挂了 rejection 处理器,所以丢弃
|
|
605
|
+
* 返回值不会炸进程;但那样失败就完全不可见。这里保留返回值并记一条 warn,
|
|
606
|
+
* 让「对账/巡检没跑成」这类问题留得下痕迹。
|
|
607
|
+
* 与 `enqueueDiag` 的分工:诊断落盘是最佳努力,失败只静默(见 enqueueDiag)。
|
|
608
|
+
*/
|
|
609
|
+
schedule(work) {
|
|
610
|
+
void this.enqueue(work).catch((error) => {
|
|
611
|
+
this.ctx.logger.warn(`项目 MCP 后台任务失败:${error instanceof Error ? error.message : String(error)}`);
|
|
612
|
+
});
|
|
613
|
+
}
|
|
610
614
|
kick() {
|
|
611
615
|
if (this.timer !== undefined)
|
|
612
616
|
return;
|
|
613
617
|
this.timer = setTimeout(() => {
|
|
614
618
|
this.timer = undefined;
|
|
615
|
-
this.
|
|
619
|
+
this.schedule(async () => {
|
|
616
620
|
await this.reconcileAll();
|
|
617
|
-
})
|
|
621
|
+
});
|
|
618
622
|
}, 150);
|
|
619
623
|
// 不挡住进程退出:短进程在 150ms 内结束时,已 kick 的对账会被丢掉(有意)。
|
|
620
624
|
this.timer.unref();
|
|
@@ -967,9 +971,9 @@ export class ProjectMcpRegistry {
|
|
|
967
971
|
return;
|
|
968
972
|
this.graceTimer = setTimeout(() => {
|
|
969
973
|
this.graceTimer = undefined;
|
|
970
|
-
this.
|
|
974
|
+
this.schedule(async () => {
|
|
971
975
|
await this.reconcileAll();
|
|
972
|
-
})
|
|
976
|
+
});
|
|
973
977
|
}, delayMs);
|
|
974
978
|
// 宽限 timer 同样不挡住退出(与 kick 的 150ms 防抖同口径)。
|
|
975
979
|
this.graceTimer.unref();
|
|
@@ -1015,8 +1019,11 @@ export class ProjectMcpRegistry {
|
|
|
1015
1019
|
`profile=${profileName ?? ""}`,
|
|
1016
1020
|
`host=${host.join(",")}`
|
|
1017
1021
|
];
|
|
1018
|
-
|
|
1019
|
-
|
|
1022
|
+
// 纯只读 stat 且每轮对账都跑:并发发起,顺序仍按排序后的 paths(Promise.all 保序)。
|
|
1023
|
+
const stats = await Promise.all(files.map((file) => this.statConfigFile(file)));
|
|
1024
|
+
for (let index = 0; index < files.length; index++) {
|
|
1025
|
+
const fp = stats[index];
|
|
1026
|
+
const file = files[index];
|
|
1020
1027
|
parts.push(fp === "missing" ? `${file}:missing` : `${file}:${Math.round(fp.mtimeMs)}:${fp.size}`);
|
|
1021
1028
|
}
|
|
1022
1029
|
return parts.join("\n");
|
|
@@ -1603,23 +1610,27 @@ export class ProjectMcpRegistry {
|
|
|
1603
1610
|
return;
|
|
1604
1611
|
state.phase = "active";
|
|
1605
1612
|
state.error = undefined;
|
|
1606
|
-
|
|
1607
|
-
this.enqueue(async () => {
|
|
1608
|
-
await container.diag({ kind: "active", effectiveName });
|
|
1609
|
-
}).catch(() => { });
|
|
1613
|
+
this.enqueueDiag(container, { kind: "active", effectiveName });
|
|
1610
1614
|
this.kickSweep();
|
|
1611
1615
|
}, (error) => {
|
|
1612
1616
|
if (!container.isCurrent(state))
|
|
1613
1617
|
return;
|
|
1614
1618
|
state.phase = "failed";
|
|
1615
1619
|
state.error = error instanceof Error ? error.message : String(error);
|
|
1616
|
-
this.
|
|
1617
|
-
await container.diag({ kind: "failed", effectiveName, error: state.error });
|
|
1618
|
-
}).catch(() => { });
|
|
1620
|
+
this.enqueueDiag(container, { kind: "failed", effectiveName, error: state.error });
|
|
1619
1621
|
this.ctx.logger.error(`${container.label} "${effectiveName}" 装载失败:${state.error}`);
|
|
1620
1622
|
this.kickSweep();
|
|
1621
1623
|
});
|
|
1622
1624
|
}
|
|
1625
|
+
/**
|
|
1626
|
+
* 诊断写排回 reconcile 链:fiber settle 的回调不在链上,裸写会与对账的
|
|
1627
|
+
* read-modify-write 交叉丢行。诊断是最佳努力——失败静默,不升级成 warn。
|
|
1628
|
+
*/
|
|
1629
|
+
enqueueDiag(container, event) {
|
|
1630
|
+
void this.enqueue(async () => {
|
|
1631
|
+
await container.diag(event);
|
|
1632
|
+
}).catch(() => { });
|
|
1633
|
+
}
|
|
1623
1634
|
async unmountServer(container, rawName, health = "forget") {
|
|
1624
1635
|
const mark = this.healthKey(container.key, rawName);
|
|
1625
1636
|
if (health === "forget")
|
|
@@ -1769,9 +1780,9 @@ export class ProjectMcpRegistry {
|
|
|
1769
1780
|
kickSweep() {
|
|
1770
1781
|
if (this.disposed)
|
|
1771
1782
|
return;
|
|
1772
|
-
this.
|
|
1783
|
+
this.schedule(async () => {
|
|
1773
1784
|
await this.sweepRestrictions();
|
|
1774
|
-
})
|
|
1785
|
+
});
|
|
1775
1786
|
}
|
|
1776
1787
|
async sweepRestrictions() {
|
|
1777
1788
|
if (this.disposed)
|
|
@@ -1994,7 +2005,7 @@ export class ProjectMcpRegistry {
|
|
|
1994
2005
|
}
|
|
1995
2006
|
/** 行级 view;未装载时 phase 按行状态推导。行查找按影子优先序走内存目录。 */
|
|
1996
2007
|
async serverView(projectRoot, rawName) {
|
|
1997
|
-
return this.enqueue(
|
|
2008
|
+
return this.enqueue(() => this.serverViewFromMemory(projectRoot, rawName));
|
|
1998
2009
|
}
|
|
1999
2010
|
serverViewFromMemory(projectRoot, rawName) {
|
|
2000
2011
|
const key = projectKeyOf(projectRoot);
|
|
@@ -2026,7 +2037,7 @@ export class ProjectMcpRegistry {
|
|
|
2026
2037
|
}
|
|
2027
2038
|
/** 内存快照:进 enqueue 与对账互斥,不读盘、不触发对账。要收敛请走 `reload()` / `reconcileNow()`。 */
|
|
2028
2039
|
async snapshot() {
|
|
2029
|
-
return this.enqueue(
|
|
2040
|
+
return this.enqueue(() => this.buildSnapshotFromMemory());
|
|
2030
2041
|
}
|
|
2031
2042
|
pushYmlSnapshot(out, key, entry, files, userPaths) {
|
|
2032
2043
|
const ymlPath = files?.ymlPath ?? projectMcpFile(entry.projectRoot);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-project-mcp-manager",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"packageManager": "pnpm@12.3.4",
|
|
5
5
|
"description": "dsh-project-mcp-manager: per-project and global MCP server loading for DSH. Reads <projectRoot>/.dsh/mcp.yml or .dsh/mcp.json (plus the read-only Claude Code project file .mcp.json), mounts project rows per project and user-layer rows (~/.dsh/mcp.yml, ~/.dsh/mcp.json, ~/.dsh/profiles/<name>/mcp.json) globally as @deepseek-ai/dsh-mcp-client instances with ${VAR} env expansion at mount time, hot-reloads on file change, scopes tool visibility per session, and ships a dsh-mcp CLI that writes either native yml or DSH JSON.",
|
|
6
6
|
"type": "module",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"cordis"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@deepseek-ai/dsh-mcp-client": "^0.
|
|
39
|
+
"@deepseek-ai/dsh-mcp-client": "^0.2.0-rc.2",
|
|
40
40
|
"chokidar": "^5.0.0",
|
|
41
41
|
"yaml": "^2.9.0",
|
|
42
42
|
"zod": "^4.4.3"
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"LICENSE"
|
|
57
57
|
],
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
59
|
+
"@deepseek-ai/cordis": "^4.0.4",
|
|
60
60
|
"@types/node": "^26.2.0",
|
|
61
61
|
"typescript": "^7.0.2"
|
|
62
62
|
}
|