dsh-acp-enhanced 0.6.0 → 0.9.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-zh.md +244 -52
- package/README.md +271 -54
- package/cordis.patch.yml +54 -4
- package/lib/codec.js +114 -0
- package/lib/index.js +564 -292
- package/package.json +37 -29
- package/scripts/acp-doctor.mjs +351 -0
- package/scripts/dsh-acp-zed.sh +164 -26
- package/scripts/init-acp-home.sh +335 -0
- package/scripts/lib/dsh-version.mjs +118 -0
package/README-zh.md
CHANGED
|
@@ -13,11 +13,14 @@ ACP 线上。
|
|
|
13
13
|
### 输出与遥测
|
|
14
14
|
|
|
15
15
|
- **块级流式 + 推理流式**:文本块与思考过程实时到达(`agent_message_chunk` /
|
|
16
|
-
`agent_thought_chunk
|
|
16
|
+
`agent_thought_chunk`),取消/重试不留半截输出。在 acp-enhanced 行设置
|
|
17
|
+
`streamDeltas: true` 可切换为**逐 token 流式**——回复边生成边渲染(75ms 合并一次
|
|
18
|
+
上线),代价是中途重试无法收回已发出的半截文本,会以可见的
|
|
19
|
+
`_[stream interrupted — retrying]_` 标记隔开(默认关闭)
|
|
17
20
|
- **完整遥测**:上下文用量环 + 缓存命中率 / TPS / 输入-输出-推理 token / 工具耗时 /
|
|
18
21
|
轮次计数(`usage_update._meta` 携带全量明细)
|
|
19
|
-
- **图片支持(多模态)**:当 dsh
|
|
20
|
-
|
|
22
|
+
- **图片支持(多模态)**:当 dsh 组合挂载了附件存储(`dsh-base` 默认装配
|
|
23
|
+
`dsh-attachment-local`)时,会声明 `promptCapabilities.image` 并把粘贴/
|
|
21
24
|
上传的图片持久化进 harness 附件存储——支持视觉的模型(如 `deepseek-v4-flash-vision-exp`)
|
|
22
25
|
可按线序原生读取,图文交替不乱序。旧版栈(无附件存储)自动降级:不声明 image、
|
|
23
26
|
收到图片 prompt 明确报错。
|
|
@@ -58,8 +61,10 @@ ACP 线上。
|
|
|
58
61
|
|
|
59
62
|
### 会话
|
|
60
63
|
|
|
61
|
-
- **恢复与归档**:`session/load` 恢复历史线程(完整回放);`session/list`
|
|
62
|
-
|
|
64
|
+
- **恢复与归档**:`session/load` 恢复历史线程(完整回放);`session/list` 列出线程
|
|
65
|
+
归档(带标题、按更新时间排序);`session/close` 释放内存中的会话记录,之后的
|
|
66
|
+
`session/load` 会从持久化日志完整恢复;标题实时推送。`session/delete` **有意不广播**——
|
|
67
|
+
harness 未声明公开的持久化删除接口(见「兼容性」)
|
|
63
68
|
- **多根工作区**:`sessionCapabilities.additionalDirectories` 已声明,Zed 不再提示
|
|
64
69
|
"This agent doesn't currently support multi-root workspaces",而是把所有工作区根
|
|
65
70
|
通过 `session/new` / `session/load` 传入。所有根都会写进系统提示词并在
|
|
@@ -72,7 +77,9 @@ ACP 线上。
|
|
|
72
77
|
(列表以等宽代码块排版,一眼全见),其余(`/compact` `/goal` `/permission`
|
|
73
78
|
`/plan`…)直通 harness 命令注册表,全部**不经过模型 turn** 即时执行。所有
|
|
74
79
|
userInvocable 技能也会作为命令广播,`/ask-matt`、`/code-review`、`/tdd` 等能被
|
|
75
|
-
编辑器放行到达桥,技能正文按 dsh-tool-skill
|
|
80
|
+
编辑器放行到达桥,技能正文按 dsh-tool-skill 的用户调用方式注入消息。斜杠命令
|
|
81
|
+
旁粘贴的图片会作为命令附件随行(例如 `/goal` 目标的参考截图),与 Web 端
|
|
82
|
+
composer 的提交方式一致
|
|
76
83
|
|
|
77
84
|
### MCP
|
|
78
85
|
|
|
@@ -89,6 +96,9 @@ ACP 线上。
|
|
|
89
96
|
|
|
90
97
|
## 快速开始
|
|
91
98
|
|
|
99
|
+
**需要 `dsh ≥ 0.1.5-rc.2`**(`npm install -g @deepseek-ai/dsh@0.1.5-rc.2`):本桥只对应
|
|
100
|
+
一条已声明的 harness API 线,不在运行期探测更老的代际。
|
|
101
|
+
|
|
92
102
|
本包遵循 dsh 官方插件规范(声明了 `dsh.bundle`),安装与官方组合包一致:**一条命令**
|
|
93
103
|
完成,自动初始化 profile、安装包、追加 bundle 层,全程无需手写 profile YAML。
|
|
94
104
|
|
|
@@ -181,44 +191,31 @@ Zed 会热重载设置。打开 **AI Agent 面板**(`Cmd+Shift+A`)→ agent
|
|
|
181
191
|
本地验证(无需 Zed):
|
|
182
192
|
|
|
183
193
|
```sh
|
|
184
|
-
node scripts/acp-
|
|
194
|
+
node <pkg>/scripts/acp-doctor.mjs # bundle + 版本、peer 范围,并真实启动一次
|
|
195
|
+
node scripts/acp-client.mjs # 仅限仓库检出:完整 ACP 端到端,期望 ALL CHECKS PASSED
|
|
185
196
|
DSH_ACP_PROVIDER=... DSH_ACP_MODEL=... node scripts/acp-client.mjs # 自定义路由时再传
|
|
186
197
|
```
|
|
187
198
|
|
|
188
|
-
###
|
|
199
|
+
### Web 搜索
|
|
189
200
|
|
|
190
|
-
|
|
191
|
-
|
|
201
|
+
bridge 自身不携带、也不推荐任何搜索 provider:模型侧 `web_search` 工具走 `web`
|
|
202
|
+
seam 的 `searchProvider`,往 profile 里挂任意 `ctx.web` provider 即可——带
|
|
203
|
+
`dsh.bundle` 的包用 `dsh plugin --profile acp-enhanced add <package>` 安装,普通包
|
|
204
|
+
走用户层 `insert` 挂载(见下节)。你的 dsh 部署里有哪些 provider 是 profile 层的
|
|
205
|
+
事,与 bridge 无关。
|
|
192
206
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
- id: web
|
|
199
|
-
config:
|
|
200
|
-
searchProvider: openai-responses # 子包注册在 ctx.web 上的搜索 provider id(固定值)
|
|
201
|
-
|
|
202
|
-
- insert:
|
|
203
|
-
- id: web-search-openrouter
|
|
204
|
-
name: 'dsh-web-search-openrouter'
|
|
205
|
-
config:
|
|
206
|
-
enabled: true
|
|
207
|
-
baseURL: http://<gateway-host>:<port>/v1
|
|
208
|
-
model: <your-model-id>
|
|
209
|
-
apiKeyEnv: <KEY_ENV_NAME>
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
> ⚠️ `searchProvider` 必须**精确等于** `openai-responses`——这是
|
|
213
|
-
> `dsh-web-search-openrouter` 注册在 `ctx.web` 上的搜索 provider id,**不是**网关的
|
|
214
|
-
> LLM provider id(即上面 `DSH_ACP_PROVIDER` 填的那个)。web 插件按 id 精确匹配,
|
|
215
|
-
> 填错时配置期不会报错,直到首次搜索才抛 `WEB_PROVIDER_CONFIGURED_MISSING`。
|
|
207
|
+
代价要说清楚:provider bundle 位于**每个 ACP 线程的启动路径**上,一旦加载失败整个
|
|
208
|
+
profile 都会挂掉,Zed 侧表现为无输出的卡死。若插件只是新增模型侧工具,优先放进 preset
|
|
209
|
+
composition(见[保持 profile 最小化](#保持-profile-最小化));而必须配置宿主 `web` 行的
|
|
210
|
+
provider 只能待在宿主组合(即 profile)里——那就明确接受这一风险,并在每次改动后重跑
|
|
211
|
+
doctor。
|
|
216
212
|
|
|
217
213
|
### 管理 profile 的插件
|
|
218
214
|
|
|
219
|
-
dsh-acp-enhanced 跑在**独立的 profile** 里——`acp-enhanced
|
|
220
|
-
`~/.dsh/profiles/acp-enhanced
|
|
221
|
-
|
|
215
|
+
dsh-acp-enhanced 跑在**独立的 profile** 里——`acp-enhanced`,位于
|
|
216
|
+
`~/.dsh/profiles/acp-enhanced/`,与 `dsh web` 同处一个 dsh home。被隔离的是**组合**
|
|
217
|
+
本身,所以在
|
|
218
|
+
这里增删改插件不会影响 web 侧的配置,而凭据、设置、会话与 preset 仍是共享的。
|
|
222
219
|
|
|
223
220
|
profile 的插件树由三层组合而成,后层修补前层:
|
|
224
221
|
|
|
@@ -226,8 +223,8 @@ profile 的插件树由三层组合而成,后层修补前层:
|
|
|
226
223
|
`@deepseek-ai/dsh-base` 在前,随后是每个声明了 `dsh.bundle` 的已安装包(如
|
|
227
224
|
`dsh-acp-enhanced`),按数组顺序排列。
|
|
228
225
|
2. **用户层**:`~/.dsh/profiles/acp-enhanced/cordis.patch.yml`——按 id 定位的行配置
|
|
229
|
-
覆写、`disabled: true` 行禁用,以及 `insert` 挂载(无 `dsh.bundle`
|
|
230
|
-
|
|
226
|
+
覆写、`disabled: true` 行禁用,以及 `insert` 挂载(无 `dsh.bundle` 的包——如手工
|
|
227
|
+
挂载的自写 provider——就靠它装配)。
|
|
231
228
|
3. **临时覆盖**:`dsh --profile acp-enhanced --patch extra.yml`。
|
|
232
229
|
|
|
233
230
|
调整插件集:
|
|
@@ -252,25 +249,201 @@ dsh --profile acp-enhanced --dump-config # 查看组合后的完整
|
|
|
252
249
|
```
|
|
253
250
|
|
|
254
251
|
- **无 `dsh.bundle` 的包自身不会装配**——它只作为普通依赖安装(带一次性警告),需要
|
|
255
|
-
|
|
256
|
-
|
|
252
|
+
自己在用户层 `insert` 挂载;要改已有行的配置,用 `- id: <行>` + `config:` 覆写——
|
|
253
|
+
patch 条目是整行替换、不做合并。
|
|
257
254
|
|
|
258
255
|
改动在**下一个**进程生效:Zed 为每个 agent 线程拉起一个全新的
|
|
259
256
|
`dsh --profile acp-enhanced`,编辑 profile 后新开 agent 线程(或重启 Zed)即可。
|
|
260
257
|
|
|
261
|
-
|
|
258
|
+
#### 保持 profile 最小化
|
|
259
|
+
|
|
260
|
+
profile 是一个**单一故障域**:`cordis-plugin-loader` 会等待每个条目,并把第一个 reject
|
|
261
|
+
原样抛出,因此只要有一行加载失败,整棵插件树就会中止——进程甚至可能先正常应答 ACP
|
|
262
|
+
`initialize` 再立刻退出,客户端只会表现为无输出的卡死,而不是报错。
|
|
263
|
+
|
|
264
|
+
把 `dsh.profile.bundles` 控制在这两行以内,它们的版本不可能与启动它的 CLI 不匹配:
|
|
265
|
+
|
|
266
|
+
```json
|
|
267
|
+
"bundles": ["@deepseek-ai/dsh-base", "dsh-acp-enhanced"]
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
`@deepseek-ai/dsh-base` 随 CLI 一起发布,版本天然等同于启动它的 CLI;其他任何 bundle 都是
|
|
271
|
+
第三方,其依赖闭包可能漂移。额外插件请挂到「坏了只废掉一个 preset」的位置:
|
|
272
|
+
|
|
273
|
+
- **只新增模型侧工具/命令的插件** → 把行写进某个 preset composition。用户 preset 放在
|
|
274
|
+
`$DSH_HOME/.agent-presets/<id>/`(组合写 `agent.cordis.yml`,选择器里的名称写
|
|
275
|
+
`preset.yml`);roster 会自动发现,ACP 的 `agent_preset` 下拉也会列出。组合加载失败的
|
|
276
|
+
preset 只会被标记为 broken 并从列表里剔除,不会拖垮进程。
|
|
277
|
+
- **需要配置宿主服务的插件**(例如要覆写宿主 `web` 行 `searchProvider` 的搜索 provider)
|
|
278
|
+
→ 它属于宿主组合,也就是 profile。这是有意的取舍:接受启动路径上的风险,并在每次改动
|
|
279
|
+
后重跑 doctor。
|
|
280
|
+
|
|
281
|
+
改动后先验证再信任:
|
|
262
282
|
|
|
263
|
-
|
|
283
|
+
```sh
|
|
284
|
+
node <pkg>/scripts/acp-doctor.mjs # bundle 与版本、peer 范围,并真实启动一次
|
|
285
|
+
dsh --profile acp-enhanced --dump-config # 每一行来自哪一层
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## 兼容性
|
|
289
|
+
|
|
290
|
+
同一个桥只对应**一条** harness API 线:**dsh ≥ 0.1.5-rc.2**(peer 范围
|
|
291
|
+
`^0.1.5-rc.2 || ^0.1.6-alpha.1`)。该范围内的**两条线**每次 CI 都会做真实启动验证——握手、
|
|
292
|
+
profile settle 与真实 `session/new`——另有跨代链接检查。桥只消费 harness **已声明**的表面:
|
|
293
|
+
`docs/capability-seams.md` 里的服务、`docs/event-producer-consumer.md` 里的事件、以及已发布包的导出。
|
|
294
|
+
`scripts/api-surface-check.mjs` 会对其他一切报错(CI 的阻塞步骤),
|
|
295
|
+
运行期也不再有任何代际探测——没有版本开关,没有鸭子类型探测服务形状。
|
|
296
|
+
|
|
297
|
+
### 支持策略
|
|
298
|
+
|
|
299
|
+
| 桥版本 | 支持的 dsh 线 | 变化 |
|
|
300
|
+
|---|---|---|
|
|
301
|
+
| **0.9.x** | `^0.1.5-rc.2 \|\| ^0.1.6-alpha.1` | 只消费已声明表面;下限 0.1.5-rc.2;移除 `session/delete` |
|
|
302
|
+
| 0.8.x | `^0.1.0-rc.6 … ^0.1.6-alpha.1`(未发布) | 0.1.3+ 实时 seam;0.1.5 持久化 handle API |
|
|
303
|
+
| 0.7.x 及更早 | ≤ 0.1.2-rc.1 | 运行期同时探测两代 |
|
|
304
|
+
|
|
305
|
+
这张表背后的规则:
|
|
306
|
+
|
|
307
|
+
- **新的 dsh API 线对应一次新的桥发布,而不是把运行期探测写得更宽。** 0.7.x 正是靠探测吞下
|
|
308
|
+
0.1.1 → 0.1.5,也正是它悄悄腐烂的原因。
|
|
309
|
+
- **下限只随桥的 minor 移动,且绝不静默**:CLI 低于范围时启动器会在启动前告警,doctor 会以
|
|
310
|
+
`RESULT FAIL — CLI too old` 停下。
|
|
311
|
+
- **放弃某条线的方式是发布一个明确这么说的桥**;旧线留在 `feat/dsh-0.1.3-plus-support` 分支上,
|
|
312
|
+
供无法迁移的用户使用。
|
|
313
|
+
- **在下一条线发布之前就盯住它**:定时 `canary` workflow 会安装 `alpha` dist-tag 并跑表面守卫、
|
|
314
|
+
链接检查与启动冒烟,因此破坏性变更表现为 canary 变红,而不是用户侧故障。
|
|
315
|
+
|
|
316
|
+
### 0.9.0 的破坏性变更
|
|
317
|
+
|
|
318
|
+
| 变更 | 影响 | 中招了怎么办 |
|
|
319
|
+
|---|---|---|
|
|
320
|
+
| 下限提升到 dsh **≥ 0.1.5-rc.2** | 更老的宿主在挂载期就以具名错误失败,而不是静默降级 | 升级 CLI(`npm install -g @deepseek-ai/dsh@0.1.5-rc.2`),或留在 `feat/dsh-0.1.3-plus-support` 分支(≤ 0.1.2-rc.1) |
|
|
321
|
+
| **移除 `session/delete`** | 不再广播该能力,也永不删除已持久化的会话——harness 未声明公开的持久化删除接口 | 文件仍在 `$DSH_HOME/sessions/<slug>/<id>/`,确有需要请手工删除。上游已有 issue 追踪公开删除 API |
|
|
322
|
+
| 启动器**不再改写 `DSH_HOME`** | ACP profile 在启动器所处的 home 中启动(`${DSH_HOME:-$HOME/.dsh}`),与 `dsh web` 共享凭据、设置、会话与 preset | 之前用的是隐式隔离的 `~/.dsh-acp`?在 Zed 的 `agent_servers.env` 里显式指回它(`"DSH_HOME": "<home>/.dsh-acp"`),或迁回共享 home |
|
|
323
|
+
| `assistant/chunk` seam 移除 | 实时流只剩 `agent/assistant-stream`(下限已覆盖该代) | 升级 CLI;完全不发流的宿主仍由已提交的 `assistant/message` 兜底 |
|
|
324
|
+
|
|
325
|
+
### 从已发布的 ≤ 0.7.0 升级
|
|
326
|
+
|
|
327
|
+
npm 上的 `latest` 是 **0.7.0**,属于 0.1.3 之前的 API 线,因此桥和 CLI **必须一起动**——只升一半,
|
|
328
|
+
两种顺序都会坏:
|
|
329
|
+
|
|
330
|
+
| 顺序 | 结果 |
|
|
264
331
|
|---|---|
|
|
265
|
-
| `
|
|
266
|
-
|
|
|
267
|
-
|
|
|
268
|
-
|
|
269
|
-
|
|
332
|
+
| 先升 CLI,桥留在 0.7.0 | profile 能启动、`initialize` 也成功,但**每个 `session/new` 都失败**(Internal error:`tool-subagent: modelSelectionSettings requires … in the Host scope`)。我们无法给出任何提示——那份桥代码已经装好了;而且 0.7.0 既没有 `agent/assistant-stream` seam 也没有 `assistant/message` 兜底,回复同样渲染不出来 |
|
|
333
|
+
| 先升桥,CLI 留在旧版 | profile 在加载期就死(`… subpath './model-selection-settings' is not defined by "exports"`)。启动器会在它**之前**向 stderr 告警,`scripts/acp-doctor.mjs` 则以 `RESULT FAIL — CLI too old` 直接停下 |
|
|
334
|
+
| 两者一起升 | 受支持的状态 |
|
|
335
|
+
|
|
336
|
+
升级清单:
|
|
337
|
+
|
|
338
|
+
1. `npm install -g @deepseek-ai/dsh@0.1.5-rc.2`(或上面 peer 范围内的任意版本)。
|
|
339
|
+
2. `dsh plugin --profile acp-enhanced add dsh-acp-enhanced@0.9.0`。升级桥是显式动作:profile 里的依赖
|
|
340
|
+
是对 0.x 的 caret,所以 `dsh plugin update` **不会**自行把你带到新的 minor。
|
|
341
|
+
3. 以前是从检出目录启动、或设过 `DSH_PATH`?旧启动器会自行切到 `~/.dsh-acp`,现在不会了。请在 Zed 的
|
|
342
|
+
`agent_servers.env` 里设 `DSH_HOME=<那个 home>`,或在默认 home 里重建 profile。启动器若在那里
|
|
343
|
+
发现 profile,会主动提示。
|
|
344
|
+
4. 以前照旧 README 在 profile 用户层里塞过 `subagent-model-selection-settings`?把它删掉:现在由桥的
|
|
345
|
+
patch 提供该行,重复 id 会让启动中止。`scripts/init-acp-home.sh` 会自动清理;启动器会告警,doctor
|
|
346
|
+
会点名该 id。
|
|
347
|
+
5. 确认 profile 里的第三方 bundle 支持 0.1.5(`dsh-free-search` ≥ 0.4.24 已验证)——profile 是单一故障域。
|
|
348
|
+
6. 重启 Zed(或新开一个 agent 线程);先用 `node <pkg>/scripts/acp-doctor.mjs` 验证整条链路(它现在连
|
|
349
|
+
开线程都会实测)。
|
|
350
|
+
|
|
351
|
+
### 一个 home 只跑一个 CLI 代际
|
|
352
|
+
|
|
353
|
+
`$DSH_HOME/profiles/node_modules` 是同 home 下所有 profile 共享的**同一个**依赖闭包,
|
|
354
|
+
dsh 每次启动都会把它 heal 成最后启动的那个 CLI。因此:
|
|
355
|
+
|
|
356
|
+
> 这是 **0.1.5 线**的行为。到 0.1.6-alpha.2,这个共享闭包已完全不存在(harness 从 CLI 自身
|
|
357
|
+
> 的安装位置解析;profile 的 `node_modules` 只放外部插件),所以启动器的漂移检查是「按线」的,
|
|
358
|
+
> 路径消失时会静默跳过。
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
- **不要让两个 CLI 代际同时跑在一个 home 下。** 第二次启动会在第一个进程运行期间翻转闭包,
|
|
363
|
+
那个进程随后会惰性地解析到不匹配的模块。启动器会把闭包里的 `dsh-agent` 版本与即将启动的
|
|
364
|
+
CLI 对比,不一致时向 **stderr** 告警——遇到这种启动后,请重启该 home 下其他 dsh 进程
|
|
365
|
+
(`dsh web` 等)。
|
|
366
|
+
- **逃生阀是 CLI,不是 home。** 用 `DSH_PATH=<dsh>`(或下面的仓库锁定)指定启动哪个 dsh:
|
|
367
|
+
启动器只决定*用哪个 dsh*,绝不决定*用哪个 home*。
|
|
368
|
+
|
|
369
|
+
当前解析结果随时可查:
|
|
370
|
+
|
|
371
|
+
```sh
|
|
372
|
+
node scripts/compat-check.mjs # 仅限仓库检出:分别安装 0.1.5-rc.2 与 0.1.6-alpha.2 两套,逐一导入本桥
|
|
373
|
+
node <pkg>/scripts/acp-doctor.mjs # CLI 与闭包版本、bundle 列表,并真实启动一次(随包发布)
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### 开发检出:仓库锁定 CLI + 共享 home
|
|
377
|
+
|
|
378
|
+
启动器**从检出目录**(`link:` 安装)运行时,按以下顺序解析 dsh CLI:
|
|
379
|
+
|
|
380
|
+
1. `$DSH_PATH` —— 显式指定的 dsh 二进制,或其 `node_modules/.bin/dsh` 内含 dsh 的目录
|
|
381
|
+
2. 仓库锁定的 CLI —— `<repo>/node_modules/.bin/dsh`(本包的 `@deepseek-ai/dsh`
|
|
382
|
+
devDependency,当前 0.1.5-rc.2)
|
|
383
|
+
3. 全局兜底 —— PATH / npx 缓存 / npm 前缀 里的 `dsh`(未 `pnpm install` 的全新检出退化为它)
|
|
384
|
+
|
|
385
|
+
命中任何一个,profile `acp-enhanced` 都在**启动器所处的 home**(`${DSH_HOME:-$HOME/.dsh}`)中启动。
|
|
386
|
+
home 永不被改写。若想让桥跑在自己的依赖闭包上,请另建一个 home 并显式指过去:
|
|
387
|
+
|
|
388
|
+
```sh
|
|
389
|
+
DSH_ACP_HOME=~/.dsh-acp scripts/init-acp-home.sh # 可选、幂等:创建并填充一个独立 home
|
|
390
|
+
# 然后在 Zed 的 agent_servers env 里: "DSH_HOME": "/Users/you/.dsh-acp"
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
独立 home 是明确的可选项,不是默认值:profile 必须存在于启动器实际使用的 home 里,否则启动器
|
|
394
|
+
会以 127 退出,并打印出创建它的那条 `dsh plugin … add link:` 命令。`init-acp-home.sh` 会逐字移植旧
|
|
395
|
+
profile 的用户层行、复制凭据/设置、关闭 DeepSeek 插件清单上报,并从用户层清掉遗留的
|
|
396
|
+
`subagent-model-selection-settings` 行——该宿主行现在由 bridge 的 bundle patch 插入,再留一份会以
|
|
397
|
+
`duplicate loader entry id` 中止启动。
|
|
398
|
+
|
|
399
|
+
两种 home 都把会话持久化在 `$DSH_HOME/sessions/<slug>/<id>/session.jsonl.zstd`;默认不在 home 之间
|
|
400
|
+
拷贝任何东西,因为默认 home 的目录里还有全部 web profile 会话。迁移既有环境时请加
|
|
401
|
+
`--copy-sessions`(或直接执行脚本打印的 `rsync`)。
|
|
402
|
+
|
|
403
|
+
## 故障排查
|
|
404
|
+
|
|
405
|
+
先跑 doctor:它会完全按 Zed 的方式启动一次 profile,并指出失败层、出问题的 bundle 与修法。
|
|
406
|
+
|
|
407
|
+
```sh
|
|
408
|
+
node <pkg>/scripts/acp-doctor.mjs # 已安装副本
|
|
409
|
+
node scripts/acp-doctor.mjs # 仓库检出(npm run doctor)
|
|
410
|
+
node <pkg>/scripts/acp-doctor.mjs --profile <name> --home <dsh-home> --timeout 60000
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
它会打印 CLI 与版本、home、profile、每个 bundle 及其版本、支持的 peer 范围与共享闭包版本,
|
|
414
|
+
然后把启动失败归入三层之一:
|
|
415
|
+
|
|
416
|
+
| 层 | `dsh` stderr 里的特征 | 含义 | 修法 |
|
|
417
|
+
|---|---|---|---|
|
|
418
|
+
| **link-time** | `does not provide an export named …`、`SyntaxError: The requested module …` | 启动的 CLI 闭包无法满足本桥的某个 import | 见 doctor 的 `LAYER link-time`:对齐代次——重启该 home 下其他 dsh 进程(共享闭包会愈合到最后启动的那个 CLI),或用 `DSH_PATH=<匹配的 dsh>` 锁定本启动器 |
|
|
419
|
+
| **mount-time** | `failed to apply loader entry …`、`… requires … in the Host scope`、`duplicate loader entry id: …` | loader 拒绝了某一个条目并向上抛出,整棵插件树因此中止 | doctor 会打印 `SUBJECT <条目> (<模块>)`——补装缺失模块、在用户层禁用该行(`- id: <条目>` + `disabled: true`),或把 `dsh.profile.bundles` 收敛为 `@deepseek-ai/dsh-base` + `dsh-acp-enhanced`;若为重复 id,请从用户层删除该行(它归 bundle patch 所有) |
|
|
420
|
+
| **run-time** | 握手成功后出现 `… is not a function` | 桥调用到了该 CLI 代次不提供的 harness 服务方法 | `npm install -g @deepseek-ai/dsh@<支持范围内的版本>`(见[兼容性](#兼容性)) |
|
|
421
|
+
|
|
422
|
+
启动器在 Zed 启动过程中会把同样三类特征翻译到 **stderr**(stdout 是 ACP 协议线),
|
|
423
|
+
所以 agent 日志里已经带有失败层与修法。
|
|
424
|
+
|
|
425
|
+
| 症状 | 定位 | 处理 |
|
|
426
|
+
|---|---|---|
|
|
427
|
+
| Zed 卡死无输出、线程始终不应答 | `node <pkg>/scripts/acp-doctor.mjs` | 会打印 `BOOT FAILED` 与 `LAYER`/`SUBJECT`/`FIX`,照 `FIX` 做即可。先应答 `initialize` 再立刻退出的 profile 也会被如实报出 |
|
|
428
|
+
| `exec: dsh: not found`(status 127) | `which dsh` | 用随附 `dsh-acp-zed.sh` 启动器(自定位 node/dsh),或安装 CLI |
|
|
429
|
+
| `no API key for provider route "xxx"` | `ls -l $DSH_HOME/.credentials.yaml` | 写入 `~/.dsh/.credentials.yaml`,或在 agent_servers 里设 `env.DEEPSEEK_API_KEY` |
|
|
430
|
+
| `SyntaxError: … 'PresetMountError'` | agent 日志里的桥版本 | 你在 0.1.5 宿主上跑 0.9.0 之前的桥副本——升级本包 |
|
|
431
|
+
| `modelSelectionSettings requires … in the Host scope` | `dsh --profile acp-enhanced --dump-config \| grep subagent-model-selection` | `standard` preset 需要的宿主行缺失——该行由 bridge 的 bundle patch 提供,请重装/升级 bridge(`dsh plugin --profile acp-enhanced add dsh-acp-enhanced`),并检查用户层没有把它 `disabled: true` |
|
|
432
|
+
| `duplicate loader entry id: <行>` | doctor 会打印 `LAYER mount-time` 与该 id | 两层都插了同一行。请从 profile 用户层(`$DSH_HOME/profiles/acp-enhanced/cordis.patch.yml`)删掉它——这类宿主行归 bundle patch 所有;`scripts/init-acp-home.sh` 会自动清掉遗留的 `subagent-model-selection-settings` 副本 |
|
|
433
|
+
| 宿主升级后旧线程变空白 | `ls $DSH_HOME/sessions` | 会话存放在 `$DSH_HOME/sessions/<slug>/`;把旧 home 的历史拷进来(`scripts/init-acp-home.sh --copy-sessions`)即可继续 |
|
|
434
|
+
| 无法切换模型 | `ACP_DEBUG=1 dsh --profile acp-enhanced`,然后尝试切换 | 携带的 `reasoning_effort` 在目标模型上不受支持:本桥按模型记住上次使用的强度(随 profile 持久化),会回退到该模型默认值而不是让切换失败。另检查路由是否真实——幽灵 provider 会被过滤,只广播 `config.provider` 的模型 |
|
|
435
|
+
| 上下文用量不显示 | 线程里执行 `/status` | 选到了不可路由的"幽灵 provider";确认 profile 的 provider 指向真实路由 |
|
|
436
|
+
| 轮次以 usage 结束但**面板没有回复文本**(空白) | `ACP_DEBUG=1`,看是否有 `agent/assistant-stream frame=chunk` | 0.9.0 起唯一的实时 seam 是 `agent/assistant-stream` 帧,某个 step 完全没有上线文本时由已提交的 `assistant/message` 兜底。有帧却无文本 = 客户端渲染问题;完全没有帧 = 正在走兜底路径(桥太旧就升级) |
|
|
437
|
+
| 改了插件却不生效 | profile `cordis.patch.yml` 的 mtime | 改动只在**下一个**进程生效:新开 agent 线程(或重启 Zed) |
|
|
438
|
+
| 需要详细诊断 | — | `ACP_DEBUG=1`(stderr 生命周期 trace)与 `ACP_LOG=/tmp/acp.jsonl`(逐事件 JSONL,带耗时) |
|
|
270
439
|
|
|
271
440
|
## 开发
|
|
272
441
|
|
|
273
442
|
```sh
|
|
443
|
+
pnpm install # 安装开发依赖(仓库锁定 CLI 与测试脚本)
|
|
444
|
+
node scripts/compat-check.mjs # 支持线上的链接检查(0.1.5-rc.2 / 0.1.6-alpha.2 临时安装)
|
|
445
|
+
node scripts/api-surface-check.mjs # 公开表面守卫:不得使用未声明的 harness API(CI 阻塞步骤)
|
|
446
|
+
node scripts/pack-check.mjs # 包完整性:入口文件、权限位、所引用文件是否都随包发布(CI 阻塞步骤)
|
|
274
447
|
node scripts/acp-client.mjs # 端到端冒烟(需要 API key)
|
|
275
448
|
node scripts/acp-client-tools.mjs # 客户端工具测试(模拟 Zed 的 fs/terminal/elicitation/plan)
|
|
276
449
|
node scripts/acp-mcp-test.mjs # MCP 挂载测试(无模型调用)
|
|
@@ -278,15 +451,34 @@ node scripts/acp-smoke-keyless.mjs # keyless 冒烟(CI 用)
|
|
|
278
451
|
node scripts/acp-resume-test.mjs # 会话恢复测试
|
|
279
452
|
node scripts/codec-image-test.mjs # 图片编解码单元测试(无网络,假 store)
|
|
280
453
|
node scripts/terminal-codec-test.mjs # 终端卡片编解码单元测试(无网络)
|
|
454
|
+
node scripts/replay-order-test.mjs # 重放/回退的分块顺序:思考块先于它产出的回复(无网络)
|
|
281
455
|
node scripts/acp-image-e2e.mjs # 图片能力端到端(vision 模型段需 API key)
|
|
456
|
+
node scripts/acp-message-fallback-test.mjs # 实时 seam + assistant/message 回退:seam 确实触发且回复恰好到达一次
|
|
457
|
+
node scripts/acp-launcher-test.mjs # 启动器契约:home 不被改写、代次漂移告警、启动失败翻译
|
|
458
|
+
node scripts/acp-doctor.mjs # 真实启动一次 profile,指出失败层与出问题的 bundle
|
|
459
|
+
scripts/init-acp-home.sh # 可选:引导**独立** home(启动器不会自行切过去)
|
|
282
460
|
```
|
|
283
461
|
|
|
462
|
+
harness 包的 devDependency 与锁定的 `@deepseek-ai/dsh` CLI 声明相同的 range(如
|
|
463
|
+
`^0.1.5-rc.2`),让仓库依赖树与全新 CLI 安装解析出同一个连贯家族——在此用精确 patch
|
|
464
|
+
锁定、与 CLI 的 range 闭包混存会得到分裂闭包(同名包两个版本),profile 启动时报
|
|
465
|
+
export-not-found。改这些锁定后务必整体重建 lockfile(`rm -rf node_modules pnpm-lock.yaml
|
|
466
|
+
&& pnpm install`):原地增量安装既会留下污染 profile heal 的残留 store 条目,还会保留
|
|
467
|
+
lockfile 里的陈旧 peer 解析——从 0.1.2-alpha.2 原地升到 0.1.2-rc.1 时,rc.1 各包的
|
|
468
|
+
snapshot 里仍挂着 `dsh-session-persistence@0.1.2-alpha.3`(旧代 peer),boot 与
|
|
469
|
+
session/new 全部通过,直到第一个 turn 才以 `TypeError: Cannot read properties of
|
|
470
|
+
undefined (reading 'length')`(PersistenceCoordinator)崩掉。`pnpm-workspace.yaml` 放行
|
|
471
|
+
了 CLI 闭包的构建脚本(node-pty prebuild、koffi)——仓库 CLI 启动 profile 时它们就是
|
|
472
|
+
运行时依赖。
|
|
473
|
+
|
|
284
474
|
## 已知限制
|
|
285
475
|
|
|
286
|
-
不支持音频附件(不声明 audio
|
|
287
|
-
prompt。MCP 支持 stdio
|
|
288
|
-
|
|
289
|
-
|
|
476
|
+
不支持音频附件(不声明 audio 能力)、文本默认按块粒度流式(`streamDeltas: true`
|
|
477
|
+
可切换为逐 token 流式,见「特性」)、每会话同时一个 in-flight prompt。MCP 支持 stdio
|
|
478
|
+
与 streamable HTTP(不声明 legacy SSE / `acp` 传输)。
|
|
479
|
+
`session/fork` / `session/resume` 未实现(不声明能力,合规客户端
|
|
480
|
+
不会调用)。`session/delete` 同样不广播:harness 未声明公开的持久化删除接口,因此本桥
|
|
481
|
+
永不删除已持久化的会话(见「兼容性」)。
|
|
290
482
|
|
|
291
483
|
多根工作区已声明、模型可见所有根,但 dsh 沙箱策略每会话只解析**一个可写根**(主
|
|
292
484
|
`cwd`,即 `session.header.cwd`),本地沙箱也只为该根开放写权限。读操作在所有根均可
|
|
@@ -296,7 +488,7 @@ prompt。MCP 支持 stdio 与 streamable HTTP(不声明 legacy SSE / `acp` 传
|
|
|
296
488
|
|
|
297
489
|
Agent 预设接管了模型侧相关行:自带 `cordis.patch.yml` 会禁用 preset 拥有的 dsh-base
|
|
298
490
|
行(tool-bash/fs/subagent/todo/web/…——与官方 dsh-web-app/tui 清单逐行一致,仅少
|
|
299
|
-
`hmr
|
|
491
|
+
`hmr`;清单保持跨代通用:某一代没有的行会被 patch applier 告警并跳过),并挂载 `agent-presets` 名册(默认 `standard`;`code`/`minimal`/`cordis`
|
|
300
492
|
随 dsh CLI 附带,`~/.dsh/.agent-presets` 下的自定义预设目录自动收录)。bundle 自带
|
|
301
493
|
patch 会自动装配(package.json `dsh.bundle.patch`)——**不要**把它复制进 profile
|
|
302
494
|
的用户层 `cordis.patch.yml`,否则 loader 在启动时因重复 entry id 拒绝装配。**升级**
|