dsh-oc-tui 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -563
- package/bin/mcp-sse-bridge.mjs +499 -499
- package/docs/assets/conversation.png +0 -0
- package/docs/assets/cover.png +0 -0
- package/docs/assets/home.png +0 -0
- package/docs/assets/settings.png +0 -0
- package/docs/dsh-std-/346/216/245/345/205/245/350/257/264/346/230/216.md +566 -0
- package/docs/user-guide.md +616 -0
- package/docs//347/224/250/346/210/267/346/211/213/345/206/214.md +607 -593
- package/dsh-plugin.json +69 -69
- package/lib/boot-block.js +129 -0
- package/lib/diagnostics.js +162 -120
- package/lib/dsh-version.js +161 -0
- package/lib/git-branch.js +157 -157
- package/lib/i18n.js +283 -283
- package/lib/image.js +2 -1
- package/lib/index.js +5183 -4812
- package/lib/locales/ar.js +670 -635
- package/lib/locales/de.js +639 -604
- package/lib/locales/en.js +35 -0
- package/lib/locales/es.js +639 -604
- package/lib/locales/fr.js +639 -604
- package/lib/locales/id.js +641 -606
- package/lib/locales/it.js +639 -604
- package/lib/locales/ja.js +639 -604
- package/lib/locales/ko.js +639 -604
- package/lib/locales/nl.js +639 -604
- package/lib/locales/pl.js +653 -618
- package/lib/locales/pt-BR.js +639 -604
- package/lib/locales/ru.js +653 -618
- package/lib/locales/tr.js +639 -604
- package/lib/locales/vi.js +641 -606
- package/lib/locales/zh-CN.js +640 -605
- package/lib/locales/zh-TW.js +640 -605
- package/lib/markdown.js +101 -27
- package/lib/mcp-monitor.js +189 -0
- package/lib/mcp-skill.js +93 -93
- package/lib/mcp.js +865 -838
- package/lib/model-route.js +66 -0
- package/lib/providers.js +712 -712
- package/lib/screenshot.js +140 -0
- package/lib/splash-opencode.js +29 -26
- package/lib/startup.js +66 -48
- package/lib/term.js +53 -11
- package/lib/themes.js +101 -0
- package/lib/ui.js +685 -443
- package/lib/updates.js +5 -2
- package/lib/web-settings.js +52 -21
- package/package.json +160 -146
- package/skills/mcp-import/SKILL.md +216 -216
|
@@ -1,593 +1,607 @@
|
|
|
1
|
-
# DeepSeek Harness TUI 用户手册
|
|
2
|
-
|
|
3
|
-
`dsh-oc-tui` 是运行在 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(dsh)进程内的**终端界面(TUI)插件**,以 profile app 的形式挂载。它把 dsh 的持久事件流渲染到终端里——流式回复、工具活动行、待办列表、思考块——并把你输入的内容送回 agent。
|
|
4
|
-
|
|
5
|
-
它**不是**独立的 agent 运行时:模型路由、工具执行、授权、命令、会话存储和凭据仍由 dsh 负责,插件只负责终端里的输入与显示。
|
|
6
|
-
|
|
7
|
-
本手册面向**安装与使用**,开发者回路见[第 8 节](#8-开发)。
|
|
8
|
-
|
|
9
|
-
## 目录
|
|
10
|
-
|
|
11
|
-
- [1. 功能特性](#1-功能特性)
|
|
12
|
-
- [2. 安装前准备](#2-安装前准备)
|
|
13
|
-
- [3. 安装](#3-安装)
|
|
14
|
-
- [4. 启动](#4-启动)
|
|
15
|
-
- [5. 使用](#5-使用)
|
|
16
|
-
- [5.1 快捷键](#51-快捷键)
|
|
17
|
-
- [5.2 斜杠命令](#52-斜杠命令)
|
|
18
|
-
- [5.3 交互式提示:授权与提问](#53-交互式提示授权与提问)
|
|
19
|
-
- [5.4 思考强度](#54-思考强度)
|
|
20
|
-
- [5.5 会话统计与上下文仪表](#55-会话统计与上下文仪表)
|
|
21
|
-
- [5.6 图形渲染:图片、表格与 mermaid](#56-图形渲染图片表格与-mermaid)
|
|
22
|
-
- [5.7 设置菜单](#57-设置菜单)
|
|
23
|
-
- [5.7.1 MCP 服务器](#571-mcp-服务器)
|
|
24
|
-
- [5.7.2 界面语言](#572-界面语言)
|
|
25
|
-
- [5.8 程序内更新](#58-程序内更新)
|
|
26
|
-
- [6. 工作原理](#6-工作原理)
|
|
27
|
-
- [7. 故障排查](#7-故障排查)
|
|
28
|
-
- [8. 开发](#8-开发)
|
|
29
|
-
- [9. 已知限制](#9-已知限制)
|
|
30
|
-
- [10. 目录结构](#10-目录结构)
|
|
31
|
-
- [11. 许可证](#11-许可证)
|
|
32
|
-
|
|
33
|
-
## 1. 功能特性
|
|
34
|
-
|
|
35
|
-
| | |
|
|
36
|
-
| --- | --- |
|
|
37
|
-
| **持久会话** | 新建、恢复、列出、删除会话;转录内容从持久事件日志重建,恢复后的会话与离开时完全一致。 |
|
|
38
|
-
| **实时流式** | 回复与思考逐 token 流式渲染;思考内容在独立可折叠框中,流式期间保持折叠。 |
|
|
39
|
-
| **真实图片渲染** | 转录中的图片以真实像素显示——kitty 图形协议、iTerm2 内联图片或 sixel,能力由终端自探测(SSH 下同样有效);不支持任何协议的终端显示真彩半块预览。粘贴的图片、存储的附件与 markdown 图片走同一条管线。见[图形渲染](#56-图形渲染图片表格与-mermaid)。 |
|
|
40
|
-
| **mermaid 图表** | ` ```mermaid ` 围栏经多级 provider 渲染为真实图表——本地 `mmdc`(若安装)优先,其次 mermaid.ink(设置可关),离线退化为高亮源码。 |
|
|
41
|
-
| **完整 Markdown** | 圆角表格、嵌套与任务列表、190+ 语言语法高亮代码、可点击 OSC 8 超链接,由 markdown-it 的 CommonMark + GFM token 流驱动。 |
|
|
42
|
-
|
|
|
43
|
-
| **工具活动** | 一个工具一行:状态标记 + 工具着色的动作(`read` 青、`run` 金、`edit` 亮蓝、`todo` 薄荷)+ 作用对象;点击该行在 `⎿` 槽下展开完整结果。 |
|
|
44
|
-
| **交互式提问** | 模型可以暂停并向你提问——选项列表、多选、自由文本、可滚动的计划评审,全部在终端内完成。 |
|
|
45
|
-
| **内联授权** | `approval/request` 询问用 `y` / `n` 直接回答,无需离开界面。 |
|
|
46
|
-
| **遥测页脚** | 会话统计条:轮次/步数、LLM 与工具耗时、平均首 token 时间(TTFT)、解码吞吐、KV 缓存命中率与输入/输出 token,均由持久事件折叠得出。 |
|
|
47
|
-
| **统计窗口** | 点击统计条或上下文仪表条,或输入 `/stats`,打开会话统计与 token 用量明细窗口。 |
|
|
48
|
-
| **上下文仪表** | 实时上下文占用(`ctx ▓▓░░ 32K/128K 25%`),明细窗口内含按系统提示词/工具/消息拆分的构成占比。 |
|
|
49
|
-
| **思考强度** | `Tab` 循环切换当前模型真实支持的推理等级;`Ctrl+E` 打开滑块。选择按请求应用并持久化。 |
|
|
50
|
-
| **共享设置** | 与 WebUI 相同的 Host 设置命名空间——通用、会话、各 provider 模型配置、凭据——持久化到 `$DSH_HOME/settings.yaml`。 |
|
|
51
|
-
| **17 种界面语言** | TUI 绘制的每一条文案——界面框架、对话区、弹窗、Toast、命令说明——都来自语言表,整界面跟随同一个设置:`Ctrl+P → 语言`,未保存偏好时跟随系统环境。英语、简体中文、繁体中文、日语、韩语、德语、法语、西班牙语、葡萄牙语(巴西)、意大利语、俄语、波兰语、荷兰语、土耳其语、越南语、印尼语、阿拉伯语。见[界面语言](#572-界面语言)。 |
|
|
52
|
-
| **MCP 服务器** | `Ctrl+P → MCP` 页自行管理 MCP 服务器:新增/编辑 stdio、HTTP 或 SSE 服务器、卸载、查看连接状态与挂载上的工具。作用域可按用户或按项目目录;随插件内置的 `mcp-import` skill 可让模型代你导入。MCP 是可选的——没有服务器、连不上、甚至宿主缺少 MCP 客户端,TUI 都照常运行。见[MCP 服务器](#571-mcp-服务器)。 |
|
|
53
|
-
| **程序内更新** | 在 TUI 内检测并切换 `@deepseek-ai/dsh` 与 `dsh-oc-tui` 版本,Windows 上采用延迟安装避免静默损坏。 |
|
|
54
|
-
| **零依赖终端引擎** | raw 模式、备用屏幕、差分单元缓冲、真彩 ANSI、CJK 宽度感知、SGR + 旧式 X10 鼠标解码、IME 光标锚定。 |
|
|
55
|
-
|
|
56
|
-
## 2. 安装前准备
|
|
57
|
-
|
|
58
|
-
| 项目 | 要求 |
|
|
59
|
-
| --- | --- |
|
|
60
|
-
| Node.js | >= 22 |
|
|
61
|
-
| dsh CLI | 已安装 `@deepseek-ai/dsh`,例如 `npm install -g @deepseek-ai/dsh` |
|
|
62
|
-
| pnpm | 已加入 PATH(`dsh plugin` 内部转发给 pnpm) |
|
|
63
|
-
| 终端 | 交互式终端(Windows Terminal / ConPTY、iTerm2、GNOME Terminal 等) |
|
|
64
|
-
| 模型配置 | `$DSH_HOME/settings.yaml` 与 `$DSH_HOME/.credentials.yaml` 中已配置可用的模型路由(与 Web GUI 共用) |
|
|
65
|
-
|
|
66
|
-
```sh
|
|
67
|
-
dsh --version
|
|
68
|
-
pnpm --version
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
**兼容性**:本插件已在 dsh `0.2.1-rc.2`、`0.2.0-rc.2`、`0.1.2-rc.1`(更早是 `0.1.1-rc.2`)上验证;`0.2.1-rc.5` 已按包逐一核对——核心包与 rc.2 内容一致,唯一的展示层改动(思考签名)也已在本插件内处理。受支持的范围以 `engines.dsh`(`>=0.1.1-rc.2 <0.3.0-0`)声明在 `package.json` 里——dsh 0.2.1 起安装门禁优先读它、不再看 peer 列表;范围外的宿主会被拒绝加载,确需使用时可用 `dsh plugin allow-version` 做精确版本豁免。dsh 0.1.2 重命名了部分会话 API——`Session.events` 改为 `snapshotEvents()`——插件会读取宿主实际提供的那个访问器,因此同一份构建可同时服务这两条版本线。dsh 0.2.0 的破坏性改动与「先升 TUI 再升 dsh」见 [5.8 节末尾](#58-程序内更新)的说明。
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
### 3.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
3.
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
dsh --profile tui --
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
dsh
|
|
174
|
-
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
dsh-oc-tui --profile
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
|
214
|
-
|
|
|
215
|
-
| `
|
|
216
|
-
| `Ctrl+
|
|
217
|
-
| `
|
|
218
|
-
| `
|
|
219
|
-
| `
|
|
220
|
-
| `
|
|
221
|
-
| `
|
|
222
|
-
| `
|
|
223
|
-
| `
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
- `
|
|
287
|
-
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
|
315
|
-
|
|
|
316
|
-
|
|
|
317
|
-
|
|
|
318
|
-
|
|
|
319
|
-
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
`
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
dsh
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
```
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
dsh
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
-
|
|
548
|
-
-
|
|
549
|
-
-
|
|
550
|
-
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
lib/
|
|
575
|
-
lib/
|
|
576
|
-
lib/
|
|
577
|
-
lib/
|
|
578
|
-
lib/
|
|
579
|
-
lib/
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
1
|
+
# DeepSeek Harness TUI 用户手册
|
|
2
|
+
|
|
3
|
+
`dsh-oc-tui` 是运行在 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(dsh)进程内的**终端界面(TUI)插件**,以 profile app 的形式挂载。它把 dsh 的持久事件流渲染到终端里——流式回复、工具活动行、待办列表、思考块——并把你输入的内容送回 agent。
|
|
4
|
+
|
|
5
|
+
它**不是**独立的 agent 运行时:模型路由、工具执行、授权、命令、会话存储和凭据仍由 dsh 负责,插件只负责终端里的输入与显示。
|
|
6
|
+
|
|
7
|
+
本手册面向**安装与使用**,开发者回路见[第 8 节](#8-开发)。
|
|
8
|
+
|
|
9
|
+
## 目录
|
|
10
|
+
|
|
11
|
+
- [1. 功能特性](#1-功能特性)
|
|
12
|
+
- [2. 安装前准备](#2-安装前准备)
|
|
13
|
+
- [3. 安装](#3-安装)
|
|
14
|
+
- [4. 启动](#4-启动)
|
|
15
|
+
- [5. 使用](#5-使用)
|
|
16
|
+
- [5.1 快捷键](#51-快捷键)
|
|
17
|
+
- [5.2 斜杠命令](#52-斜杠命令)
|
|
18
|
+
- [5.3 交互式提示:授权与提问](#53-交互式提示授权与提问)
|
|
19
|
+
- [5.4 思考强度](#54-思考强度)
|
|
20
|
+
- [5.5 会话统计与上下文仪表](#55-会话统计与上下文仪表)
|
|
21
|
+
- [5.6 图形渲染:图片、表格与 mermaid](#56-图形渲染图片表格与-mermaid)
|
|
22
|
+
- [5.7 设置菜单](#57-设置菜单)
|
|
23
|
+
- [5.7.1 MCP 服务器](#571-mcp-服务器)
|
|
24
|
+
- [5.7.2 界面语言](#572-界面语言)
|
|
25
|
+
- [5.8 程序内更新](#58-程序内更新)
|
|
26
|
+
- [6. 工作原理](#6-工作原理)
|
|
27
|
+
- [7. 故障排查](#7-故障排查)
|
|
28
|
+
- [8. 开发](#8-开发)
|
|
29
|
+
- [9. 已知限制](#9-已知限制)
|
|
30
|
+
- [10. 目录结构](#10-目录结构)
|
|
31
|
+
- [11. 许可证](#11-许可证)
|
|
32
|
+
|
|
33
|
+
## 1. 功能特性
|
|
34
|
+
|
|
35
|
+
| | |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| **持久会话** | 新建、恢复、列出、删除会话;转录内容从持久事件日志重建,恢复后的会话与离开时完全一致。 |
|
|
38
|
+
| **实时流式** | 回复与思考逐 token 流式渲染;思考内容在独立可折叠框中,流式期间保持折叠。 |
|
|
39
|
+
| **真实图片渲染** | 转录中的图片以真实像素显示——kitty 图形协议、iTerm2 内联图片或 sixel,能力由终端自探测(SSH 下同样有效);不支持任何协议的终端显示真彩半块预览。粘贴的图片、存储的附件与 markdown 图片走同一条管线。见[图形渲染](#56-图形渲染图片表格与-mermaid)。 |
|
|
40
|
+
| **mermaid 图表** | ` ```mermaid ` 围栏经多级 provider 渲染为真实图表——本地 `mmdc`(若安装)优先,其次 mermaid.ink(设置可关),离线退化为高亮源码。 |
|
|
41
|
+
| **完整 Markdown** | 圆角表格、嵌套与任务列表、190+ 语言语法高亮代码、可点击 OSC 8 超链接,由 markdown-it 的 CommonMark + GFM token 流驱动。 |
|
|
42
|
+
| **OpenCode 风格会话** | 用户消息保留原始文字,以蓝色左竖线、浅底和内边距区分。AI 的 Markdown 正文与用户文字对齐,上方是可展开的思考内容,下方显示模型及本轮耗时。连续工具调用紧凑排列,命令输出默认预览 10 行,点击可展开完整结果。正文、代码与图片两侧均保留留白。 |
|
|
43
|
+
| **工具活动** | 一个工具一行:状态标记 + 工具着色的动作(`read` 青、`run` 金、`edit` 亮蓝、`todo` 薄荷)+ 作用对象;点击该行在 `⎿` 槽下展开完整结果。 |
|
|
44
|
+
| **交互式提问** | 模型可以暂停并向你提问——选项列表、多选、自由文本、可滚动的计划评审,全部在终端内完成。 |
|
|
45
|
+
| **内联授权** | `approval/request` 询问用 `y` / `n` 直接回答,无需离开界面。 |
|
|
46
|
+
| **遥测页脚** | 会话统计条:轮次/步数、LLM 与工具耗时、平均首 token 时间(TTFT)、解码吞吐、KV 缓存命中率与输入/输出 token,均由持久事件折叠得出。 |
|
|
47
|
+
| **统计窗口** | 点击统计条或上下文仪表条,或输入 `/stats`,打开会话统计与 token 用量明细窗口。 |
|
|
48
|
+
| **上下文仪表** | 实时上下文占用(`ctx ▓▓░░ 32K/128K 25%`),明细窗口内含按系统提示词/工具/消息拆分的构成占比。 |
|
|
49
|
+
| **思考强度** | `Tab` 循环切换当前模型真实支持的推理等级;`Ctrl+E` 打开滑块。选择按请求应用并持久化。 |
|
|
50
|
+
| **共享设置** | 与 WebUI 相同的 Host 设置命名空间——通用、会话、各 provider 模型配置、凭据——持久化到 `$DSH_HOME/settings.yaml`。 |
|
|
51
|
+
| **17 种界面语言** | TUI 绘制的每一条文案——界面框架、对话区、弹窗、Toast、命令说明——都来自语言表,整界面跟随同一个设置:`Ctrl+P → 语言`,未保存偏好时跟随系统环境。英语、简体中文、繁体中文、日语、韩语、德语、法语、西班牙语、葡萄牙语(巴西)、意大利语、俄语、波兰语、荷兰语、土耳其语、越南语、印尼语、阿拉伯语。见[界面语言](#572-界面语言)。 |
|
|
52
|
+
| **MCP 服务器** | `Ctrl+P → MCP` 页自行管理 MCP 服务器:新增/编辑 stdio、HTTP 或 SSE 服务器、卸载、查看连接状态与挂载上的工具。作用域可按用户或按项目目录;随插件内置的 `mcp-import` skill 可让模型代你导入。MCP 是可选的——没有服务器、连不上、甚至宿主缺少 MCP 客户端,TUI 都照常运行。见[MCP 服务器](#571-mcp-服务器)。 |
|
|
53
|
+
| **程序内更新** | 在 TUI 内检测并切换 `@deepseek-ai/dsh` 与 `dsh-oc-tui` 版本,Windows 上采用延迟安装避免静默损坏。 |
|
|
54
|
+
| **零依赖终端引擎** | raw 模式、备用屏幕、差分单元缓冲、真彩 ANSI、CJK 宽度感知、SGR + 旧式 X10 鼠标解码、IME 光标锚定。 |
|
|
55
|
+
|
|
56
|
+
## 2. 安装前准备
|
|
57
|
+
|
|
58
|
+
| 项目 | 要求 |
|
|
59
|
+
| --- | --- |
|
|
60
|
+
| Node.js | >= 22 |
|
|
61
|
+
| dsh CLI | 已安装 `@deepseek-ai/dsh`,例如 `npm install -g @deepseek-ai/dsh` |
|
|
62
|
+
| pnpm | 已加入 PATH(`dsh plugin` 内部转发给 pnpm) |
|
|
63
|
+
| 终端 | 交互式终端(Windows Terminal / ConPTY、iTerm2、GNOME Terminal 等) |
|
|
64
|
+
| 模型配置 | `$DSH_HOME/settings.yaml` 与 `$DSH_HOME/.credentials.yaml` 中已配置可用的模型路由(与 Web GUI 共用) |
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
dsh --version
|
|
68
|
+
pnpm --version
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**兼容性**:本插件已在 dsh `0.2.1-rc.2`、`0.2.0-rc.2`、`0.1.2-rc.1`(更早是 `0.1.1-rc.2`)上验证;`0.2.1-rc.5` 已按包逐一核对——核心包与 rc.2 内容一致,唯一的展示层改动(思考签名)也已在本插件内处理。受支持的范围以 `engines.dsh`(`>=0.1.1-rc.2 <0.3.0-0`)声明在 `package.json` 里——dsh 0.2.1 起安装门禁优先读它、不再看 peer 列表;范围外的宿主会被拒绝加载,确需使用时可用 `dsh plugin allow-version` 做精确版本豁免。dsh 0.1.2 重命名了部分会话 API——`Session.events` 改为 `snapshotEvents()`——插件会读取宿主实际提供的那个访问器,因此同一份构建可同时服务这两条版本线。dsh 0.2.0 的破坏性改动与「先升 TUI 再升 dsh」见 [5.8 节末尾](#58-程序内更新)的说明。
|
|
72
|
+
|
|
73
|
+
**dsh 版本不匹配时,TUI 会拒绝启动。** 启动时它会读取**实际在跑**的那个 dsh 版本(优先读 `@deepseek-ai/dsh-app-boot` 的 manifest,其次 CLI 包,最后退回 PATH 上的 `dsh`),再对照本包里声明的两份清单:`engines.dsh`(支持范围)与 `dshSupport.tested`(本构建真正跑过的版本)。两者任一不满足,就只画一页全屏提示——当前版本、已验证版本、推荐版本,以及要执行的安装命令——其余全部不做:不建会话、不开设置、不检查更新,唯一接受的输入是 `Esc` / `Ctrl+C`,退出码为 `1`。这一页不会轻易误报:`engines.dsh` 不匹配时,dsh 自己的 preflight 会在插件的行挂载**之前**就把它们禁用,所以实际能看到这页,要么是执行过 `dsh plugin allow-version` 的豁免宿主,要么是落在范围内、但本构建没验证过的版本——`0.2.2-rc.1` 正属后者:界面能起,可每次切模型都抛错。两条出路:装推荐的 dsh 版本,或者在确认新版 dsh-oc-tui 已支持当前 dsh 后更新插件(`npm i -g dsh-oc-tui@latest`)。维护者要拿未发布的宿主做测试时,可用 `DSH_TUI_IGNORE_DSH_VERSION=1` 对当次进程跳过检查。
|
|
74
|
+
|
|
75
|
+
**dsh 0.2.2 改了「怎么选模型」,本构建两条线都跟得上。** 从 `0.2.2-rc.1` 起,一步的路由在提示词组装之前、`agent/pre-step` 之前就固定,`agent/request` 瀑布现在会**拒绝**把 provider / model / 思考强度改成另一个值的监听器——它会抛 `agent/request proposed "…" after step preparation fixed "…"`,那一轮直接失败。选择必须用 `agent.model.select()` 在步与步之间记下来,它会往会话日志里追加一条持久的 `model/selection` 事件。本插件在活的 agent 上探测 `agent.model.select`:存在时,`/model`、`/provider`、思考强度滑块与设置里存的思考等级全部走它,瀑布原样放行;在 `0.2.1` 及更早的线上,agent 没有自己的选择对象,仍由瀑布代劳。同一份构建同时服务两条线,不需要任何配置。另外读取会话路由时改为优先取这条记录下来的选择、其次才是创建时的 options,所以恢复的会话显示的是它**真的会用**的模型。`0.2.2` 的其他部分都无需适配:本插件用到的会话、投影、命令、skill、附件、审批、提问、MCP 客户端与设置接口都没变;dsh 自己把 Node.js 下限提到 `24.9` 只是 dsh 的要求,本插件在 `^22.19` 上照常运行。
|
|
76
|
+
|
|
77
|
+
## 3. 安装
|
|
78
|
+
|
|
79
|
+
### 3.1 从 npm 安装
|
|
80
|
+
|
|
81
|
+
本包已发布到 npm,包名 [`dsh-oc-tui`](https://www.npmjs.com/package/dsh-oc-tui)。装进 `tui` profile:
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
dsh plugin --profile tui add -w dsh-oc-tui
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
也可以把启动器装到全局,这样 `dsh-oc-tui` 命令就在 PATH 上,它等价于 `dsh --profile tui`:
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
npm install -g dsh-oc-tui
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
本插件同时已收录进 [awesome-dsh-plugin](https://awesome-dsh-plugin.com/zh/p/rayafriandion/dsh-oc-tui/) 插件市场(分类:UI 增强)。
|
|
94
|
+
|
|
95
|
+
### 3.2 版本渠道:stable 与 next
|
|
96
|
+
|
|
97
|
+
npm 为这个包提供两条渠道:**`latest`** 是稳定版,**`next`** 是预发布(带 `-pre`、`-rc`、`-alpha`、`-beta` 后缀的版本)。不带 tag 的安装——上面 3.1 的 `dsh plugin … add -w dsh-oc-tui` 和 `npm install -g dsh-oc-tui`——拿到的是最新稳定版,不会是候选版本。从 `0.2.0` 起稳定版已包含完整的视觉体验更新,不需要再走 `@next`。[awesome-dsh-plugin](https://awesome-dsh-plugin.com/zh/p/rayafriandion/dsh-oc-tui/) 市场收录指向同一个包,从那里开始的安装同样落在稳定版渠道上。
|
|
98
|
+
|
|
99
|
+
想用预发布版本,显式指名 tag:`dsh plugin` 会把规格原样交给 pnpm,pnpm 负责解析 dist-tag。
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
dsh plugin --profile tui add -w dsh-oc-tui@next # 最新预发布版
|
|
103
|
+
npm install -g dsh-oc-tui@next
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
本仓库里尚未发布的改动没有任何 dist-tag,只能从打好的 tarball 或检出目录安装(见 3.4「从本地目录或 tarball 安装」):
|
|
107
|
+
|
|
108
|
+
```sh
|
|
109
|
+
npm pack # 生成 dsh-oc-tui-<版本>.tgz
|
|
110
|
+
dsh plugin --profile tui add -w ./dsh-oc-tui-<版本>.tgz
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
本手册描述的是当前源码树,可能领先于已发布版本——手册里写到的功能,只有在对应版本发布到 npm 之后才能从稳定版拿到。
|
|
114
|
+
|
|
115
|
+
### 3.3 一键安装脚本
|
|
116
|
+
|
|
117
|
+
仓库内置 Linux/macOS 与 Windows 安装脚本:检查 Node.js >= 22、确保 pnpm 可用、把插件装进 `tui` profile,加 `--launcher`/`-Launcher` 还会全局安装 `dsh-oc-tui` 启动器。
|
|
118
|
+
|
|
119
|
+
```sh
|
|
120
|
+
# Linux / macOS
|
|
121
|
+
curl -fsSL https://raw.githubusercontent.com/rayafriandion/dsh-oc-tui/main/install.sh | bash
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
```powershell
|
|
125
|
+
# Windows(PowerShell)
|
|
126
|
+
powershell -ExecutionPolicy Bypass -Command "iwr https://raw.githubusercontent.com/rayafriandion/dsh-oc-tui/main/install.ps1 -OutFile install.ps1; & .\install.ps1"
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
在源码目录里也可直接运行 `./install.sh`(Linux/macOS)或 `.\install.ps1`(Windows)。其他选项:`--local`(`-Local`)安装当前源码目录;`--source <spec>`(`-Source <spec>`)指定自定义来源;`--profile <name>`(`-Profile <name>`)指定非默认 profile。
|
|
130
|
+
|
|
131
|
+
### 3.4 从本地目录或 tarball 安装
|
|
132
|
+
|
|
133
|
+
```sh
|
|
134
|
+
npm pack # 生成 dsh-oc-tui-<版本>.tgz
|
|
135
|
+
dsh plugin --profile tui add -w ./dsh-oc-tui-<版本>.tgz
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`dsh plugin` 会把相对路径按你执行命令时所在的目录解析后再转发给 pnpm。
|
|
139
|
+
|
|
140
|
+
### 3.5 为什么必须带 `-w`
|
|
141
|
+
|
|
142
|
+
profile 目录把自己声明为 pnpm workspace 根(`pnpm-workspace.yaml` → `packages: [.]`),因此裸 `add` 会被 pnpm 拒绝并报 `ERR_PNPM_ADDING_TO_ROOT`。加上 `-w` 后依赖写入 profile 自己的 manifest——这正是它应有的位置。之后 `dsh plugin` 会把 `dsh.profile.bundles` 与已安装状态对齐。
|
|
143
|
+
|
|
144
|
+
### 3.6 安装做了什么
|
|
145
|
+
|
|
146
|
+
1. `dsh plugin` 首次使用时初始化 `$DSH_HOME/profiles/tui`(`@deepseek-ai/dsh-base` 加一个空的用户补丁层)。
|
|
147
|
+
2. pnpm 把 `dsh-oc-tui` 装进该 profile 的 `node_modules`。
|
|
148
|
+
3. 因为本包声明了 `dsh.bundle.patch`,dsh 自动把 `dsh-oc-tui` 追加到 `dsh.profile.bundles`。
|
|
149
|
+
4. `dsh --profile tui` 组合 base 层、本 bundle 的行、以及你自己的补丁——无需手动编辑任何配置。
|
|
150
|
+
|
|
151
|
+
### 3.7 验证安装
|
|
152
|
+
|
|
153
|
+
```sh
|
|
154
|
+
dsh --profile tui --dump-config
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
输出中应出现 `# == dsh-oc-tui` 这一层,包含 `tui-startup`、`tui-app` 与 `tool-ask-user`(提问工具)三行——本 bundle 刻意不挂载 agent 预设名册(原因见 5.7 的破坏性更新说明),因此这一层没有预设行。
|
|
158
|
+
|
|
159
|
+
## 4. 启动
|
|
160
|
+
|
|
161
|
+
### 4.1 标准启动
|
|
162
|
+
|
|
163
|
+
```sh
|
|
164
|
+
dsh --profile tui
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
启动后先进入标题界面,**发送第一条消息即创建会话**。常用参数:
|
|
168
|
+
|
|
169
|
+
```sh
|
|
170
|
+
dsh --profile tui --resume <sessionId> # 恢复已保存的会话
|
|
171
|
+
dsh --profile tui --model <modelId> # 新会话默认模型
|
|
172
|
+
dsh --profile tui --provider <route> # 新会话默认 provider 路由
|
|
173
|
+
dsh --profile tui --no-sidebar # 不显示侧边栏
|
|
174
|
+
dsh --profile tui --help # 查看 TUI 自己的参数帮助
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
dsh 启动器只把 `web` 和 `plugin` 硬编码为裸子命令,所以 `--profile tui` 才是正规形态。想要直接敲 `dsh tui`,可以加一行别名:
|
|
178
|
+
|
|
179
|
+
```powershell
|
|
180
|
+
function tui { dsh --profile tui @args } # 写入 PowerShell $PROFILE
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
```bat
|
|
184
|
+
doskey tui=dsh --profile tui $* :: CMD
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### 4.2 便捷启动器 dsh-oc-tui
|
|
188
|
+
|
|
189
|
+
本包附带 `dsh-oc-tui` 命令,等价于 `dsh --profile tui`,但会在启动前检查 `tui` profile 是否已装好本插件;若没有,会直接打印一次性安装命令,而不是进入一个空转的 profile。
|
|
190
|
+
|
|
191
|
+
```sh
|
|
192
|
+
dsh-oc-tui # 启动 tui profile
|
|
193
|
+
dsh-oc-tui --profile mytui # 启动名为 mytui 的 profile
|
|
194
|
+
dsh-oc-tui --help # 启动器帮助
|
|
195
|
+
dsh-oc-tui --version # 启动器版本
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
它优先使用 PATH 中的 `dsh`,找不到时回退到 `npx --yes @deepseek-ai/dsh`。安装到 PATH:`npm install -g dsh-oc-tui`。
|
|
199
|
+
|
|
200
|
+
| 环境变量 | 作用 |
|
|
201
|
+
| --- | --- |
|
|
202
|
+
| `DSH_TUI_PROFILE` | 未指定 `--profile` 时的默认 profile 名(默认 `tui`) |
|
|
203
|
+
| `DSH_TUI_SKIP_CHECK` | 设为 `1` 跳过 profile 预检(高级安装方式使用) |
|
|
204
|
+
|
|
205
|
+
## 5. 使用
|
|
206
|
+
|
|
207
|
+
首页采用 OpenCode 风格的居中布局:单行 DeepSeek 渐变品牌字、简洁输入面板,以及就近显示的设置、思考强度和分支快捷键。进入会话后输入区固定到底部,用户消息用低对比背景区分,宽屏状态集中到右栏。蓝色输入指示和思考等级保持静止,仅实际运行中的活动显示动画。设置弹窗会压暗背景,窄窗口自动改为顶部分类、上下排列的名称与值。本次布局调整沿用现有渲染器和依赖。
|
|
208
|
+
|
|
209
|
+
在 `Ctrl+P → Main → 主题` 可切换配色:默认深蓝色的 DeepSeek Standard,以及 GitHub Dark、Dracula、VS Code Dark+ 和 Nord。选择后立即生效,并会保存以供下次启动使用。
|
|
210
|
+
|
|
211
|
+
### 5.1 快捷键
|
|
212
|
+
|
|
213
|
+
| 按键 | 作用 |
|
|
214
|
+
| --- | --- |
|
|
215
|
+
| `Enter` | 发送消息 |
|
|
216
|
+
| `Ctrl+Enter` / `Shift+Enter` / `Alt+Enter` | 输入换行 |
|
|
217
|
+
| `Ctrl+C` | 清空非空输入框 / 取消进行中的轮次;空闲时连按两次退出 |
|
|
218
|
+
| `Ctrl+P` | 打开设置菜单 |
|
|
219
|
+
| `Ctrl+S` | 将当前 TUI 界面保存为带窗口外框的 PNG 截图 |
|
|
220
|
+
| `Ctrl+E` | 打开/关闭输入框下方的思考强度滑块 |
|
|
221
|
+
| `Ctrl+G` | 空页面:打开 git 分支切换窗口;会话内:提示该功能仅在空页面可用 |
|
|
222
|
+
| `Tab` | 命令建议打开时补全命令,否则循环切换思考强度;设置页面切换分类 |
|
|
223
|
+
| `Ctrl+N` | 新建会话 |
|
|
224
|
+
| `Ctrl+D` | 在 设置 → 管理会话 中删除当前选中的会话(连按两次确认) |
|
|
225
|
+
| `Ctrl+L` | 清空当前转录视图 |
|
|
226
|
+
| `Up` / `Down` | 在多行输入中上下移动光标;位于第一行/最后一行时改为浏览输入历史 |
|
|
227
|
+
| `Shift+Up` / `Shift+Down` | 宽窗口下滚动右侧状态栏(窄窗口下等同于 `Up`/`Down`) |
|
|
228
|
+
| `Left` / `Right` | 在输入框中左右移动光标 |
|
|
229
|
+
| `PgUp` / `PgDn` | 滚动转录区 |
|
|
230
|
+
| `Esc` | 关闭会话统计窗口 / 关闭强度滑块 / 关闭帮助 / 取消授权询问 / 中断正在运行的轮次 / 清空正在输入的提示词 |
|
|
231
|
+
| `Esc Esc` | 空闲且输入框为空时打开 rewind 选择器 |
|
|
232
|
+
| `y` / `n` | 回答界面内的授权询问 |
|
|
233
|
+
|
|
234
|
+
**鼠标**:滚轮滚动页面——会话页滚动转录区,指针悬在右侧状态栏上时滚动状态栏,设置窗口打开时滚动设置窗口。在转录区按住左键拖动可选中文字,随后按右键把所选文字复制到剪贴板。会话页的统计条与上下文仪表条都是点击目标(见 [5.5](#55-会话统计与上下文仪表))。
|
|
235
|
+
|
|
236
|
+
**截图**:按 `Ctrl+S` 将当前可见的 TUI 界面(包括终端内图片)保存为带窗口标题栏和外框的 PNG;右上角会显示保存结果。默认存入用户的「图片」文件夹,也可在 `Ctrl+P → Main → 截图保存位置` 修改;清空该设置即可恢复默认。截图包含当前可见区域,不包含屏幕外的历史内容。
|
|
237
|
+
|
|
238
|
+
### 5.1.1 右侧状态栏(宽窗口)
|
|
239
|
+
|
|
240
|
+
会话内终端宽度 ≥ 140 列时,右侧出现一条状态栏(OpenCode 风格);首页始终保留居中输入布局。底部状态行里的模型、思考强度、上下文占用移到这里**展开显示**,并追加两个来自 dsh 原生数据的栏目——**GOAL**(当前目标、阶段与轮次,`/goal` 设置)与 **SUBAGENTS**(正在运行/累计的子代理列表)。栏内自上而下:
|
|
241
|
+
|
|
242
|
+
- 会话标题(固定在顶部)与可滚动的栏目区:`MODEL`(模型、provider)、`THINKING`(当前思考强度及其可调范围)、`CONTEXT`(占用条、tokens、账单、构成拆分)、`SESSION`(轮次/步数、耗时、速度)、`GOAL`、`SUBAGENTS`;
|
|
243
|
+
- 底部固定显示运行版本(`dsh x.y.z · tui a.b.c`);工作区路径与 git 分支在顶栏右侧,不在这里重复。
|
|
244
|
+
|
|
245
|
+
栏目超出窗口高度时右侧出现滚动条,`Shift+Up`/`Shift+Down` 或在栏上滚动滚轮即可上下滚动;点击 `CONTEXT` 栏等同点击上下文仪表条,可打开会话统计窗口。窄窗口(< 140 列)保持原有单列布局,状态信息仍显示在底部状态行。
|
|
246
|
+
|
|
247
|
+
### 5.2 斜杠命令
|
|
248
|
+
|
|
249
|
+
内建命令:`/help` `/settings` `/new` `/resume <id>` `/model <id>` `/provider <route>` `/rewind` `/branch` `/stats` `/clear` `/cancel` `/quit`(`/exit` 等效)。
|
|
250
|
+
|
|
251
|
+
输入 `/` 会打开命令建议列表,最多显示六行。`↑`/`↓` 选择,`Tab` 或鼠标点击补全,`Esc` 仅收起建议、保留输入。对未输入完整的命令按 `Enter` 会先补全;已经完整输入的命令按 `Enter` 直接执行。
|
|
252
|
+
|
|
253
|
+
**Rewind(回退)**:`Esc Esc`(或 `/rewind`)列出当前会话的提示词。选择"恢复对话"会以所选提示词之前的事件**分叉出一个新会话**,父会话完整留在磁盘上——与 dsh 自身的 `session/fork` 行为一致;选择器默认停在最近一条真实提示词上,因此连按两次 `Enter` 即回退最后一轮。`/rewind <n|last> [conversation|code|both]` 可跳过选择器直接执行。分叉出的新会话从**空 inbox** 开始:切点落在某轮 turn 之前,也会切掉那一轮对 inbox 的认领,因此父会话里排队过的输入(**包括你这次要丢掉的那条提示词**)不会被再次投递,它们仍留在父会话日志里;若有此类输入,结果行会显示 `dropped N inherited pending input`。**恢复文件**是尽力而为且有护栏的:必须在 git 工作区中(否则提示 `files not restored (not a git worktree)` 且不改动任何文件);已跟踪文件用 `HEAD` 覆盖且不触碰索引;只有当日志中该路径的首次写入发生在回退点之后时,才会删除未跟踪文件。所有被覆盖或删除的内容都会先复制到 `$DSH_HOME/rewind-backups/<sessionId>/<时间戳>/`,结果行会给出该目录。由于日志不保存文件内容,已跟踪文件回到的是最近一次提交,而非回退点当时的状态。
|
|
254
|
+
|
|
255
|
+
dsh 的人类命令(`/compact`、`/goal`、`/plan` 等)会转发给 `ctx.commands`,不经过模型轮次执行。**这些命令需要有活动会话**:在标题屏上敲会得到 `/<name>: start a session first` 提示,而不是被静默丢弃。因此想用 `/plan` 进入计划模式,请先随便发一条消息建立会话。
|
|
256
|
+
|
|
257
|
+
**Git 分支切换**:在空页面按 `Ctrl+G`(或输入 `/branch`)打开分支切换窗口——本地分支与远程跟踪分支分两节列出,当前分支带 git 自己的 `*` 标记。`Enter` 检出所选分支:没有对应本地分支的远程分支会经由 git 自带的 DWIM 规则创建跟踪分支(`origin/feature` → `feature`);本地已存在同名分支时则直接切到该分支。`p` 拉取更新(先 `git fetch --all --prune`,再 `git pull --ff-only`——本地已分叉时拒绝合并而不是硬合,因为 TUI 没有解决冲突的界面),`r` 重新读取引用,`Esc` 关闭。每个操作的结果都显示在窗口的副标题行,标题屏上的 `git:` 行会跟随切换更新。检出分支会重写工作区,而本进程的所有会话都扎根在工作区上,因此该窗口**只在空页面提供**:会话内按同样的快捷键或输入同样的命令,只会得到一条指向空页面的提示,不会弹出窗口。工作区不是 git 仓库、或 `PATH` 上没有 `git` 时,窗口会如实提示且不做任何改动。
|
|
258
|
+
|
|
259
|
+
### 5.3 交互式提示:授权与提问
|
|
260
|
+
|
|
261
|
+
**授权询问**:工具需要许可时,输入框区域显示 `Approval · <工具> · y allow / n deny`。`y` 允许一次、`n` 拒绝、`Esc` 取消。插件同时尊重生效的权限预设——自动批准的预设不会弹询问。
|
|
262
|
+
|
|
263
|
+
**模型提问**:模型可以通过 `ask_user_question` 工具直接向你提问。该工具由本 bundle 的 `tool-ask-user` 行声明(`dsh-base` 只挂载 `user-questions` **服务**、不挂载工具,而 TUI 会话是从 base 进程级组合的、不走 agent 预设),并由一个弹窗应答:
|
|
264
|
+
|
|
265
|
+
| 按键 | 作用 |
|
|
266
|
+
| --- | --- |
|
|
267
|
+
| `Up` / `Down` | 在选项间移动(循环) |
|
|
268
|
+
| `Space` | 切换高亮项(多选)或选中它(单选) |
|
|
269
|
+
| `Enter` | 继续:单选会选中并前进;在自由文本行上进入编辑;多选则确认已勾选集合 |
|
|
270
|
+
| 任意可打印字符 | 跳到自由文本行并开始输入 |
|
|
271
|
+
| `PgUp` / `PgDn`、滚轮 | 滚动较长的计划/明细区 |
|
|
272
|
+
| `Esc` | 让出(defer):不在本界面回答;编辑状态下按 `Esc` 先退回选项 |
|
|
273
|
+
| `Ctrl+C` | 仍然取消进行中的轮次,待答问题随之撤回 |
|
|
274
|
+
|
|
275
|
+
问题**一次问一个**(与 WebUI 的 composer 完全一致),答案编码也相同:自由文本答案在单选问题中**替换**已选选项,在多选题中**与已选项并存**。
|
|
276
|
+
|
|
277
|
+
带 `plan-review` 意图的问题(`exit_plan_mode` 发出的那种)会把计划 markdown 渲染在上方可滚动区域,下面是 `Approve` / `Keep planning`。选 `Approve` 会退出计划模式并继续执行;选其它则继续保持计划。
|
|
278
|
+
|
|
279
|
+
`Esc` 让出是刻意设计而非"取消":若没有其它应答者,工具会收到 `no user-questions answerer accepted the request` 报错——这个结果不会被误当成你做出了选择。
|
|
280
|
+
|
|
281
|
+
### 5.4 思考强度
|
|
282
|
+
|
|
283
|
+
输入框右上角显示当前生效的思考强度等级名和 `Tab` 提示,点击该标签可以打开滑块。包括 `max` 在内的所有等级均保持静止显示。
|
|
284
|
+
|
|
285
|
+
- 会话页面按 `Tab` 循环当前模型支持的等级(到最高档后回到最低档),`Shift+Tab` 反向;改动即时保存。
|
|
286
|
+
- `Ctrl+E` 打开输入框下方的滑块:`Tab` 或 `←`/`→` 调整并保存,`Esc` 或 `Ctrl+E` 关闭。
|
|
287
|
+
- 等级来自 provider 适配器实际声明的可选值(`ctx.llm.resolveModelInfo`):布尔型思考模型只显示两端,DeepSeek 的 `Off`/`High`/`Max` 只显示这三档,全档位模型显示它声明的每一级——不会退化成 `none → max` 的一刀切刻度。
|
|
288
|
+
|
|
289
|
+
选择通过 `agent/request` waterfall 应用到该会话的请求,并保存到 `agent-default-model.reasoningEffort`。
|
|
290
|
+
|
|
291
|
+
### 5.5 会话统计与上下文仪表
|
|
292
|
+
|
|
293
|
+
输入框上方一行是**会话统计条**,对应 Web 界面输入框下方的统计行——用空格分组、按同样的顺序列出同一批数字:
|
|
294
|
+
|
|
295
|
+
```
|
|
296
|
+
▤ 1 turn · 2 steps LLM 1.3s · tools 1.2s TTFT avg 400ms · 20.0 tok/s cache 55% in 110 · out 30
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
- `turns` / `steps` 统计**已结束的步**(`step/end`):失败、取消、触顶的步同样计入;`LLM` 是 `step/start` → 组装完成的回复,`tools` 是配对的 `tool/call` → `tool/result`。
|
|
300
|
+
- `TTFT avg` 是每步首 token 延迟的平均值,`tok/s` 是解码吞吐(首 token → 组装完成之间的输出 token)。
|
|
301
|
+
- `cache` 是提示词侧缓存命中率(缓存读取 ÷ 全部计费输入),`in` / `out` 是本次会话累计的计费输入与输出 token。
|
|
302
|
+
- 极窄终端会**整组**丢弃放不下的尾部数字并标出 `…`,不会把某个数字截成两半;完整数字始终在明细窗口里。
|
|
303
|
+
- 会话还没有任何已结束的步、也没有任何 token 计费时,统计条整行隐藏,把该行还给转录区。
|
|
304
|
+
|
|
305
|
+
统计条整行是点击目标:点击它(或点击状态栏右端的上下文仪表条 `ctx ▓▓░░ 32K/128K 25%`,或输入 `/stats`)打开**会话统计窗口**,再次点击、点击别处或按 `Esc` 关闭。窗口把同一个统计条拆成明细行(`usage` / `duration` / `speed` / `tokens` / `cache`),并附上上下文占用读数与按启发式拆分的构成占比——系统提示词、工具、对话消息——对应 WebUI 的 ContextMeter 弹窗。
|
|
306
|
+
|
|
307
|
+
数据来源与 Web 界面一致,优先级为**投影优先、本地折叠兜底**:token-meter 的 `tokenUsage`、`contextPressure`、`contextBreakdown` 投影由 `dsh-base` 挂载;`sessionStats` 投影只有 Web 应用层 bundle 才挂载,因此 TUI 自己按同样的规则折叠持久日志里的 `step` / `chunk` / `message` / `tool` 事件。profile 缺少某个投影时,对应数字自动退回本地折叠而不影响其它功能;两者都不存在时(例如尚无任何事件)该行/该组自动隐藏。
|
|
308
|
+
|
|
309
|
+
### 5.6 图形渲染:图片、表格与 mermaid
|
|
310
|
+
|
|
311
|
+
启动时 TUI 会**探测终端本身**——依次发送 DA1 属性查询、XTVERSION 名称查询、kitty 图形协议查询与单元格像素尺寸查询。这些都是转义序列,由**客户端终端**应答,因此 SSH 远程登录时同样有效(环境变量跨不了 SSH)。
|
|
312
|
+
|
|
313
|
+
| 终端 | 使用的协议 |
|
|
314
|
+
| --- | --- |
|
|
315
|
+
| kitty、Ghostty | kitty graphics(每张图只传一次,滚动时按引用移动,零重传) |
|
|
316
|
+
| WezTerm | kitty graphics 或 iTerm2 内联图片 |
|
|
317
|
+
| iTerm2、Konsole、mintty | iTerm2 内联图片 / sixel |
|
|
318
|
+
| Windows Terminal ≥ 1.22 | sixel |
|
|
319
|
+
| GNOME Terminal、旧版 xterm 等 | 真彩半块预览(`▀`,所有字体都有字形) |
|
|
320
|
+
|
|
321
|
+
**图片来源**:粘贴的图片(字节在手)、恢复/回放会话时经附件服务读回的存储引用、`data:` URL、markdown 独立图片(``),以及工具结果里的图片(如截图)。图片按转录宽度与行数上限缩放(设置里的 Image height cap,默认 20 行);GIF 取首帧。
|
|
322
|
+
|
|
323
|
+
**mermaid**:` ```mermaid ` 围栏经多级 provider 渲染——本地 `mmdc`(mermaid-cli,需自行安装)优先;未安装则走 mermaid.ink 网络服务(10 秒超时、磁盘缓存)。注意 mermaid.ink 会把图表文本发送给第三方服务,隐私敏感时请用 `local` 或 `off`。所有失败都退化为高亮源码块,不会破坏版面。
|
|
324
|
+
|
|
325
|
+
**设置**(Main 标签 → Graphics 分组,保存即生效):
|
|
326
|
+
|
|
327
|
+
| 设置项 | 取值 | 说明 |
|
|
328
|
+
| --- | --- | --- |
|
|
329
|
+
| Graphics rendering | `auto` / `off` | `off` 关闭全部像素渲染 |
|
|
330
|
+
| No-protocol fallback | `halfblock` / `chip` | 无协议终端显示半块像素还是 `[图片]` 占位 |
|
|
331
|
+
| Image height cap (rows) | 10–40 行 | 图片最大高度 |
|
|
332
|
+
| Mermaid rendering | `auto` / `local` / `off` | `local` 不联网;`off` 只显示高亮源码 |
|
|
333
|
+
|
|
334
|
+
**依赖**:渲染为纯 npm 实现——`sharp` 负责解码与缩放(三平台预编译二进制),kitty/iTerm2/sixel 编码器为插件内置。除可选的 `mmdc` 外无需安装任何外部程序。
|
|
335
|
+
|
|
336
|
+
### 5.7 设置菜单
|
|
337
|
+
|
|
338
|
+
按 `Ctrl+P` 打开。菜单覆盖与 WebUI 相同的 Host 设置命名空间,修改通过 `ctx.settings` 持久化:dsh 0.1.x 写入 `$DSH_HOME/settings.yaml`,0.2.0 写入 profile 的 `cordis.patch.yml`。分类在宽弹窗中显示于左侧,窄弹窗中显示于顶部,`Tab`(或鼠标点击)切换,`↑/↓` 移动、`Enter` 打开选项列表、`Esc` 返回,分区标题行不可选中:
|
|
339
|
+
|
|
340
|
+
- **Main**:General(Busy Enter 行为、权限预设)、Sessions(新建会话、管理会话)、System(Provider API 配置提示、更新管理器快捷入口、设置文件路径)、Developer(**上下文详情**)
|
|
341
|
+
- **Developer → 上下文详情**决定转录区要不要画宿主自己的「管道」内容:runtime-context 快照(当前工作目录、文件策略、审批策略那几段)、会话的 system prompt,以及 `system-reminder` 提示。取 `显示`(默认)时它们各自只占一行折叠框——点该行即可展开;取 `隐藏` 时直接从转录区去掉,会话本身不受影响(这些框仍在日志里),改回 `显示` 立刻原样回来。
|
|
342
|
+
- **Model**:默认 provider / model / 思考强度;随后是每个已配置 provider 一组,组内为 API key、Provider URL、Models(`Enter` 打开勾选窗口)、模型行(`Enter` 设为默认)、Add model by id、Remove provider;最后一行是 **Add provider**
|
|
343
|
+
- **MCP**:见 [5.7.1](#571-mcp-服务器)
|
|
344
|
+
- **Update**:见 [5.8](#58-程序内更新)
|
|
345
|
+
|
|
346
|
+
判定规则是「这个 provider 的 profile 能不能解析出来」:能解析就成组显示。整段式 provider(如 DeepSeek,`settingsPath` 为空、profile 就是插件条目自己的 Config)永远存在,所以新装的 TUI 里它的 API key 行一定在——旧版本要求「用户层有覆盖」才显示,结果把唯一自带的 provider 藏了起来,那一版根本无处填 key。已安装但从未启用的目录路由不会出现在分组里,它们只出现在添加流程中。以登录鉴权的路由(DeepSeek Account)不显示 key 行,而是一行「已通过 DeepSeek 账号登录」。
|
|
347
|
+
|
|
348
|
+
**添加服务商**:在 Model 页最后的 **Add provider** 按 `Enter`,进入选择器——首行是**搜索行**(`Enter` 开始输入,逐字收窄下面的列表;路由 ID 与显示名都参与匹配),其后是 **自定义 API — 手工声明端点**,再往下是「已安装的服务商」(适配器自带、但你的配置里还没有 profile 的目录路由)。共 40 余条目录路由,靠这一行才扫得动;「自定义」放在列表之前,因为要找它的人不会想先滚过 40 行。两条路径对应 WebUI 添加卡的两个模式:
|
|
349
|
+
|
|
350
|
+
- **启用已安装的服务商**:只需填 API key(可留空,改走该 provider 自己的环境认证)、可选的端点覆盖;Models 留空就沿用内置目录。保存即写出一条空 profile——对目录路由这就是全部所需。
|
|
351
|
+
- **声明自定义服务商**:必填路由 ID(小写字母开头,仅小写字母、数字与连字符)、端点(http/https)、协议、至少一个模型;可选显示名与 API key。**先填显示名也行**——路由 ID 还空着时会按显示名自动补一个(`Acme Gateway` → `acme-gateway`,去掉开头数字因为它也是凭据名的一部分),补出来的值就显示在那一行里,随时可以改。协议列表由适配器自己的 schema 读出(`openai-completions` / `openai-responses` / `anthropic-messages`),不会被填进它无法实现的取值。
|
|
352
|
+
|
|
353
|
+
表单是草稿:`Enter` 编辑一行、`Esc` 返回、只有 **Save provider** 才落盘。**Models** 行会拿表单里当前的端点与协议(含尚未保存的 key)去问 `/models`,勾选结果写进草稿;端点答不出时用 **Add model by id** 手填。保存顺序是 profile 先写、凭据后写,所以 key 写失败时 provider 已存在,重试不会再建一次。写入位置是 profile 的 `cordis.patch.yml` 里 `llm-pi-ai.providers.<route>`,密钥按 `<ROUTE>_API_KEY` 存进凭据库——和 WebUI 写出来的结构完全一致,两边可以互相接续编辑。
|
|
354
|
+
|
|
355
|
+
**粘贴**:对话框开着时,`Ctrl+V`(终端自己的粘贴,以括号粘贴序列送达)落在**当前正在编辑的字段**上;没有打开字段时,它会直接打开所选行的编辑器并把内容填进去。粘贴不会溜进被对话框遮住的输入框——那是这条路径曾经的问题:粘 API key 时文本进了会话提示词,回车就会当消息发出去。单行字段会把多行粘贴折成一行(密钥额外去掉换行,`sk-a⏎sk-b` 拼成 `sk-ask-b`);图片粘贴在文本字段里被忽略,因为它没有文本形式,而对话框后面的输入框也看不见。
|
|
356
|
+
|
|
357
|
+
**Models 自动获取**:在某个 provider 的 **Models** 行按 `Enter`,TUI 调用 `ctx.llm.discoverModels` 获取该 provider 的完整模型目录(内置路由直接取内置目录,自定义路由则请求其端点),弹出勾选窗口用 `[x]`/`[ ]` 选择(`Enter` 切换、`Esc` 返回)。选中的模型保存到该 provider 的 `models` 配置;在列出的模型上按 `Enter` 可把它设为默认模型。目录里没有的模型用同一组下方的 **Add model by id** 直接补一行。
|
|
358
|
+
|
|
359
|
+
**模型条目的增删改**:勾选窗口里的每一行右侧会带上该模型已知的容量(如 `256K · 32K`),行上:
|
|
360
|
+
|
|
361
|
+
- `Enter` 切换是否属于该 provider(勾上即写入 `models`);
|
|
362
|
+
- `e` 打开这一条的编辑器——模型 ID(新增时可选)、显示名、上下文窗口、最大输出 tokens、输入类型(纯文本 / 文本 + 图像)。容量可以写 `256K`、`1M`,留空表示沿用路由默认值;保存后按位置替换该行,不会多出一条。
|
|
363
|
+
- `Del` 把它从该 provider 移除(首按提示、再按确认)。删掉最后一条会把 `models` 整个 unset,目录路由因此回到「沿用内置目录」;手写路由没有目录可退,adapter 会拒绝这次写入并把原因显示出来。
|
|
364
|
+
|
|
365
|
+
窗口底部还有 **Refresh catalog**(重新问一次端点,适合端点刚起来的情况)与 **Add model by id**(端点不报这个模型时手填,同上也能用 `e` 补容量)。未保存的 provider(添加表单里的 Models 行打开的窗口)用同一套键,改动只落在草稿里,**Save provider** 才写盘。
|
|
366
|
+
|
|
367
|
+
**拉取失败会说明原因**:端点的拒绝(`…/models answered 401; check the API key`、`could not reach …`、`pi-ai protocol "…" has no model listing`)会作为窗口第一行的告警显示,而不是只留一句「没有模型」。「没填 key 就点获取」是最常见的 401 来源——现填的 key 即使还没保存也会带上去试探,所以填了就能过。
|
|
368
|
+
|
|
369
|
+
**选择与全选**:窗口第一行是整体的勾选开关,右侧显示 `已选/总数`:
|
|
370
|
+
|
|
371
|
+
- 手写路由第一次拉取成功时**默认全选**(它没有内置目录可继承,`models` 必须显式列出),全选开关就是撤回到空的快捷方式;
|
|
372
|
+
- 目录路由则刻意**默认不选**——`models` 留空表示「沿用适配器目录」,adapter 升级后自动跟随;一旦写死列表就冻结在当天;
|
|
373
|
+
- `Enter`(或用鼠标点该行)切换一行,`Enter` 在开关行上等于一键全选 / 全部取消。
|
|
374
|
+
|
|
375
|
+
**默认 agent 预设** 只有在 profile 挂载了预设名册时才会出现——选项列表就是那份名册,而本插件刻意不挂载(见 5.7),所以默认的 `tui` profile 里这一行是「没有」而不是「空白」。若某一套 profile 确实挂载了名册,请注意 TUI 会话始终从进程级 base 组合生成,该默认值只在按预设创建会话时生效。
|
|
376
|
+
|
|
377
|
+
WebUI 专属选项(`ui-theme` 外观、WebUI 的 `locale` 语言)不在 TUI 中显示,因为它们在终端里没有效果;TUI 自己的**语言**行是另一个设置,见 [5.7.2](#572-界面语言)。
|
|
378
|
+
|
|
379
|
+
**第三方插件的设置页分区(目前尚不支持)**:`@dsh-std` 生态里有 `ui.dsh/v1alpha1` 的 `ContributionHost` / `UiContribution` 协议,本意是让第三方插件往宿主的设置面追加只读分区(`host-rendered` 模式,即宿主自己渲染对方给的数据)。TUI **目前不托管**这类贡献,所以设置页只显示上面列出的内置分区:本插件的 `@dsh-std` facet 无法注册贡献宿主——adapter 对 facet 提交的实现有强制校验(必须有 `handle` 函数,字段名必须是 `protocol`),而协议里的 `UiContributionProvider` 两条都不满足,提交它会让 adapter 在挂载时回滚整个 profile;真正的注册入口是 adapter 的实例方法 `registerUiContributionProvider`,facet 拿不到 adapter 实例。需要宿主自己执行第三方 JS 的 `local-module` 模式则永久不在计划内(TUI 无沙箱,且协议说明没有同一 page realm 的 TUI 不需要实现它)。另需注意:本插件的 facet 在当前上游下**一条协议 support 都不暂存**——Community v0.15 清单无法声明 supports,而 lifecycle 要求先声明才能暂存——所以它不只是不托管贡献宿主,Presentation 与 CommandRuntime 同样处于休眠状态。详见 [dsh-std 接入说明](dsh-std-接入说明.md) 开头的「阻断性发现」。
|
|
380
|
+
|
|
381
|
+
### 5.7.1 MCP 服务器
|
|
382
|
+
|
|
383
|
+
`Ctrl+P → MCP` 是 TUI 自己的 MCP 管理页:安装(新增/编辑)、卸载、查看连接状态。工具经由宿主 `dsh` 的 MCP 客户端挂到**当前会话的 agent 上**,所以列表页只在有会话时才显示实时状态;标题界面无 agent,仍可查看配置但不会连接。
|
|
384
|
+
|
|
385
|
+
**安装/编辑**:`Enter` 选中某个服务器进入编辑;`Add MCP server` 行新增。表单字段:
|
|
386
|
+
|
|
387
|
+
| 字段 | 说明 |
|
|
388
|
+
| --- | --- |
|
|
389
|
+
| Name | 工具命名空间,1–32 个字母、数字、`-` 或 `_`;编辑时不可改(改名等于删旧建新) |
|
|
390
|
+
| Type | `Local command`(本地子进程,stdio)/ `HTTP`(Streamable HTTP)/ `SSE`(旧版 HTTP+SSE) |
|
|
391
|
+
| Timeout (ms) | 单次工具调用或资源请求的超时,默认 `30000` |
|
|
392
|
+
| Command / Arguments / Environment (JSON) | 本地命令专用;Arguments 按 shell 习惯分词(引号可分组),也可以直接粘 JSON 数组;Environment 是 JSON 对象,值可以是字符串、数字或布尔;本地命令的工作目录取当前会话目录 |
|
|
393
|
+
| URL / Headers (JSON) | `HTTP` 与 `SSE` 专用;Headers 是 JSON 对象,`{"Authorization":"Bearer …"}` 最常见 |
|
|
394
|
+
| Scope | `User`(`$DSH_HOME/mcp.json`,对所有会话生效)或 `Path`(`<路径>/.dsh/mcp.json`,只对工作目录在该路径之下的会话生效),选 Path 时下方出现 Path 行填写目录 |
|
|
395
|
+
| Enabled | `off` 保留配置但不连接 |
|
|
396
|
+
|
|
397
|
+
`Save` 保存并立即挂载。**卸载**:在服务器行按 `Delete`(或 `Backspace`)出现 y/n 确认,确认后删除配置并断开连接。状态行的含义:`● connected` 已连接但读不到工具表,`● N tools` 已连接并列出注册上的工具,`… connecting` 正在连接,`⚠ <原因>` 连接失败,`○ disabled` 已停用,`○ not connected` 尚未连接。某台服务器的工具名以缩进行列在该行下方,供一眼确认挂上了什么;列表下方的 `Config files` 行列出本次读取的每个配置文件及它是否存在——这是排查「这台服务器为什么在这里/为什么没出现」的答案。
|
|
398
|
+
|
|
399
|
+
**作用域属于文件,不是记录里的字段。** 某个会话的实际服务器列表 = 用户文件 + 从会话工作目录逐级向上到文件系统根途中遇到的每个 `<目录>/.dsh/mcp.json`;同名时**更近的文件胜出**。编辑时切换 Scope 会把这条记录搬到另一个文件。配置文件就是普通 JSON:
|
|
400
|
+
|
|
401
|
+
```json
|
|
402
|
+
{
|
|
403
|
+
"version": 1,
|
|
404
|
+
"servers": {
|
|
405
|
+
"github": {
|
|
406
|
+
"type": "stdio",
|
|
407
|
+
"command": "npx",
|
|
408
|
+
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
409
|
+
"env": { "GITHUB_TOKEN": "…" },
|
|
410
|
+
"timeoutMs": 30000,
|
|
411
|
+
"enabled": true
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
TUI 在 MCP 页打开期间持续重读这些文件并挂载变化的部分,所以在别处手改配置——或者让模型通过随插件内置的 **`mcp-import` skill** 导入——都能不重启会话直接生效。该 skill 会教模型如何替你新增、修复、停用或删除服务器。
|
|
418
|
+
|
|
419
|
+
**存储与安全**:环境变量与 Headers 在这些文件里是**明文**(MCP 页的 `Secrets` 行也这么写),需要凭据保密时请自行保管这些文件;本页不提供凭据保险库,也不支持 OAuth。
|
|
420
|
+
|
|
421
|
+
**MCP 完全是可选的**:一台都没配也能照常使用 TUI;某个服务器连不上、宿主缺少 MCP 客户端、甚至某个配置文件 JSON 坏掉,都只在一行显示 `⚠`,会话、输入、其余功能都不受影响。
|
|
422
|
+
|
|
423
|
+
**关于 SSE**:宿主的 MCP 客户端只支持 stdio 与 Streamable HTTP,所以 `SSE` 类型是用随插件附带的 `bin/mcp-sse-bridge.mjs`(零依赖的 stdio↔legacy-SSE 代理)当子进程跑的,宿主的工具桥接、重连策略与单次调用超时照常生效。
|
|
424
|
+
|
|
425
|
+
### 5.7.2 界面语言
|
|
426
|
+
|
|
427
|
+
TUI 绘制的每一条用户可见文案都在渲染时从语言表里取:标题界面、顶栏、侧边栏、对话区的各类标签、工具行、输入框、状态行与右侧状态栏、设置页的框架与选项值、帮助浮层、回退选择器、统计窗口、提问与授权弹窗、Toast 提示,以及 `/help` 里的命令说明。语言只有一处设置:**`Ctrl+P` → Main → 语言**,共 17 种语言加一个「跟随系统」,各自用本语言书写(`简体中文`、`日本語`、`Português (Brasil)`、`العربية`……)。选中后立即重绘,不需要重启。选择存在 dsh 自己的设置里:dsh 0.2.0 上写进 profile 的 `cordis.patch.yml`,也就是 `tui-app` 行的 `locale` 字段;0.1.x 上写进 `$DSH_HOME/settings.yaml` 的 `tui-locale.preference`。「跟随系统」不写任何值,所以之后系统语言变了也会跟着变。
|
|
428
|
+
|
|
429
|
+
支持的语言:英语、简体中文、繁体中文、日语、韩语、德语、法语、西班牙语、葡萄牙语(巴西)、意大利语、俄语、波兰语、荷兰语、土耳其语、越南语、印尼语、阿拉伯语。
|
|
430
|
+
|
|
431
|
+
选「跟随系统」(默认)时,启动按下面的顺序取第一个命中的值:
|
|
432
|
+
|
|
433
|
+
1. `DSH_TUI_LOCALE`
|
|
434
|
+
2. `LANGUAGE`
|
|
435
|
+
3. `LC_ALL` / `LC_MESSAGES` / `LANG`
|
|
436
|
+
4. 操作系统语言(Windows 上取显示语言)
|
|
437
|
+
5. `en`
|
|
438
|
+
|
|
439
|
+
取值可以是 POSIX 形式(`de_DE.UTF-8`)、BCP 47(`pt-BR`)或裸语言码(`zh`、`fr`),大小写不敏感;别名只在确实存在对应语言表时才映射(`zh`/`zh-Hans` → `zh-CN`,`zh-Hant`/`zh-HK` → `zh-TW`,`pt`/`pt-PT` → `pt-BR`,`in` → `id`)。没有语言表的语言(例如挪威语)直接回退到英语,而不是映射到一个并不相近的邻居。`DSH_TUI_LOCALE=en` 同时锁定 `--help` 的文字——那段帮助在读取设置文件之前就已打印。
|
|
440
|
+
|
|
441
|
+
英语是源语言表:它定义键集合,其他语言必须全部覆盖(测试会双向校验),缺少的键回退到英语而不是显示原始键名。复数走 `Intl.PluralRules`,所以俄语、阿拉伯语能用上完整的 CLDR 形式,而英语、中文只用它们真正需要的几种。产品与协议标识(`DeepSeek Harness`、`dsh`、`MCP`、`stdio`、`Ctrl+P`、`Tab`、`Esc`、`Enter`、`git`、`npm`……)在任何语言下都保持原样。
|
|
442
|
+
|
|
443
|
+
新增一种语言只需一个文件:`lib/locales/<id>.js` 导出扁平的 `{ 'area.key': 'text' }` 对象,并在 `lib/i18n.js` 的 `LOCALES` 里加一项;`npm test` 会核对键覆盖、占位符一致性与复数形式。
|
|
444
|
+
|
|
445
|
+
### 5.8 程序内更新
|
|
446
|
+
|
|
447
|
+
`Ctrl+P → Update` 页面负责检测并切换 dsh 与 TUI 自身的版本,所有检查与安装都通过 `npm` / `dsh plugin`(即 pnpm)执行,因此会尊重你配置的 registry 与镜像。状态行**只以稳定版为目标**:
|
|
448
|
+
|
|
449
|
+
- `Update available → x.y.z`:有更新稳定版(金色高亮)
|
|
450
|
+
- `Up to date`:已是最新
|
|
451
|
+
- `No stable release — pick from Versions`:registry 上还没有稳定版,不会主动提示,需自行从版本列表选择
|
|
452
|
+
- `Install damaged — reinstall below`:全局 dsh 安装处于新旧混杂的损坏状态,需重装
|
|
453
|
+
|
|
454
|
+
`Enter` 打开某个包的 **Versions** 完整版本列表(新→旧),`[latest]`(绿)、`[next]`(青)、`(installed)`(浅蓝)等标识区分频道与当前版本;选中任意版本(含 rc/alpha)后按 `Enter` 出现 y/n 确认(文案含目标版本号)。`Check now` 重新拉取 registry;`Startup check` 开关启动后 2 秒的静默稳定版检查。
|
|
455
|
+
|
|
456
|
+
**更新分两步:先下载,再重启生效。** 确认后 TUI 自己把 tarball 下载到 `$DSH_HOME/updates`,界面上有实时字节进度条(`Esc` 随时取消),落盘前按 registry 上的 sha512 校验完整性;下载完成后再问一次「重启即应用」,确认后 TUI 先派生一个独立安装进程、自己退出,该子进程等本进程消失才执行安装(dsh 走 `npm install -g <tarball>`,TUI 走 `dsh plugin … add -w <tarball>`),校验磁盘实际版本,然后带着原来的参数和工作目录把 dsh 重新拉起来。因此:
|
|
457
|
+
|
|
458
|
+
- 版本列表会打 `[cached]`(该版本 tarball 已在磁盘上,回退/重试都不需要重新下载)和 `[staged]`(等待重启应用的那个版本)标记;
|
|
459
|
+
- Update 页面对下载未应用的版本会多出 **Restart to apply x.y.z**(直接 `Enter` 重启应用)与 **Discard downloaded x.y.z**(丢弃)两行,且只有 tarball 确实还在磁盘上时才会出现——上次下载后崩溃也不会留下一个假入口;
|
|
460
|
+
- 安装结果写入 `$DSH_HOME/tui-dsh-install.json`,下次打开 Update 页自动读取并清除;已损坏的安装会被标出(Status 行 `Install damaged — reinstall below`),而不是报一个虚假的成功。
|
|
461
|
+
|
|
462
|
+
**为什么更新绝不在 TUI 运行期间安装**:给一个正在被 `dsh` 进程加载的包做全局安装,可能**静默**留下新旧混杂的损坏安装——Windows 上运行中的进程锁着内存映射的原生 DLL,npm 替换目录失败却仍以 0 退出(2026-09-04 就是这样把 dsh 弄坏的)。改成「下载 → 重启应用」之后,这台戏在任何平台都不再有窗口期:应用进程会等本进程消失才动手,且 TUI 在确认重启前会检查是否有别的 dsh 进程在跑(有就拒绝)。残留窗口只有一个:该检查发生在确认**之前**,之后又开起来的 `dsh web` 仍可能撞上安装。
|
|
463
|
+
|
|
464
|
+
**dsh 0.2.0 是破坏性更新——先升 TUI,再升 dsh。** 从 `0.2.0-rc.1` 起,预设相关包被拆开:原来的名册提供方 `@deepseek-ai/dsh-agent-presets`(自带预设)改名为 `@deepseek-ai/dsh-agent-preset-registry`,而新的 `@deepseek-ai/dsh-agent-preset` 只是**声明式**的预设行——它注入注册表提供的服务,自己不会激活。`0.1.5` 以下的 TUI 引用的还是旧名,于是 dsh 每次启动都会打印一段墙一样的不兼容报告:
|
|
465
|
+
|
|
466
|
+
```
|
|
467
|
+
dsh: disabling profile plugin row "agent-presets": Plugin @deepseek-ai/dsh-agent-presets@0.1.1-rc.2 is
|
|
468
|
+
incompatible with dsh 0.2.0-rc.2: peerDependencies {…}. Running it may cause crashes or data loss.
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
TUI 仍然能启动,但 Settings → Default preset 不再有名册可选(没有人提供名册时该行直接隐藏)。把 TUI 更到 `0.1.5` 或更高,这段报告就消失:本 bundle **根本不挂载名册行**——因为没有任何一个包名能在两条 dsh 线上同时成立:旧名在 0.2.0 上会触发上面的报告,单数名永远不会激活,注册表名册在没有主机声明预设时激活出来也是空的。需要名册的 dsh 0.2.0 profile 应当自己挂载注册表并声明预设(`dsh-web-app` 正是这么做的)。两个方向都不影响会话数据。
|
|
472
|
+
|
|
473
|
+
**dsh 0.2.1 升级注意。** `--from-default-profile` 重建一个**已有自定义配置**时会替换该配置及其插件和设置——tui profile 正是自定义配置,重建之后需要重新 `dsh plugin --profile tui add dsh-oc-tui` 并重设 TUI 选项(会话数据不受影响)。另外 API Key 读取优先级有调整:Web/桌面端(含 TUI 这类 profile 应用)优先使用已保存的凭据,headless 改用环境变量和 `.env`;TUI 设置页显示的凭据检测状态就是宿主实际使用的状态,无需额外操作。
|
|
474
|
+
|
|
475
|
+
## 6. 工作原理
|
|
476
|
+
|
|
477
|
+
- 插件是用 `tui` profile 加载的 Cordis 函数插件。`lib/startup.js` 解析本应用的命令行参数并提供 `tuiStartup` 服务;`lib/index.js` 拥有 UI 主循环。
|
|
478
|
+
- `lib/term.js` 是零依赖终端引擎:raw 模式、备用屏幕、差分单元缓冲、按键解码(真彩 ANSI、CJK 宽度感知)、终端应答安全解码与图形协议发射(图像槽位、OSC 8 超链接)。它把隐藏的终端光标停在输入光标处,使系统 IME 的候选窗锚定在输入框内;同时理解 SGR 与旧式 X10 两种鼠标编码,滚轮/点击字节不会漏进输入文本。
|
|
479
|
+
- `lib/caps.js` 在启动时并行探测终端能力(DA1 / XTVERSION / kitty 图形 / 单元格像素尺寸),应答由客户端终端发出,SSH 下同样有效。
|
|
480
|
+
- `lib/image.js` 是图像管线:`sharp` 解码缩放后按探测到的协议编码——kitty(传输一次按引用放置)、iTerm2 内联、sixel(256 色量化)或 ANSI 半块回退;负载按内容哈希 LRU 缓存。
|
|
481
|
+
- `lib/mermaid.js` 是 mermaid 的多级 provider 链:本地 `mmdc`(若在 PATH)→ mermaid.ink(10 秒超时、磁盘缓存)→ 失败由调用方回退到高亮源码块。
|
|
482
|
+
- `lib/ui.js` 是响应式视图模型与渲染器(DeepSeek 蓝白主题、OpenCode 风格会话、会话栏、转录区、多行输入框、命令建议、会话统计条、状态栏)。转录行按块缓存,每帧只实体化可见窗口,流式绘制合并,活动块按短节流重绘——因此渲染成本有界,输出速度不随历史增长而下降。思考内容折叠以保持转录可读,运行中的工具与思考块用流动 spinner 提示。
|
|
483
|
+
- `lib/metrics.js` 把持久的 step/chunk/message/tool 事件折叠为整场会话的轮次/步数、耗时、TTFT、吞吐、缓存命中与计费 token(与 Web 界面的 `sessionStats` / `tokenUsage` 投影同规则),并在 profile 提供投影时以投影值为准。
|
|
484
|
+
- `lib/interrupt.js` 管理 stdin 与 `SIGINT` 共用的清空/取消/二次退出状态机。
|
|
485
|
+
- `lib/markdown.js` 由 markdown-it 的 CommonMark + GFM token 流把模型输出渲染为带样式的行:圆角表格、嵌套/任务列表、highlight.js 语法高亮代码、OSC 8 可点击链接,以及 mermaid/图片围栏的特殊行。
|
|
486
|
+
- `lib/updates.js` 隔离 Update 页面的全部 npm/pnpm 交互——registry 查询、无依赖 semver 比较、dsh 安装探测、异步安装——一律走 `child_process.spawn`,从不使用 `spawnSync`。
|
|
487
|
+
- 会话通过 `ctx.agents` 创建/恢复,转录由持久日志重建并由 `session/event` 实时驱动(含 `assistant/chunk`),模型默认值来自 `ctx.agentDefaultModel`,授权询问在内联应答 `approval/request` waterfall。
|
|
488
|
+
- `ask_user_question` 通过 `user-questions/request` waterfall 应答:这是一个按 agent 作用域分发的 Cordis waterfall,弹窗要么返回答案、要么用 `next()` 委托。请求中止时以普通错误拒绝,让服务自己报出 `ASK_ABORTED`;发给其它 agent 的请求原样委托。
|
|
489
|
+
|
|
490
|
+
## 7. 故障排查
|
|
491
|
+
|
|
492
|
+
| 现象 | 原因与处理 |
|
|
493
|
+
| --- | --- |
|
|
494
|
+
| `pnpm failed in profile directory` / `ERR_PNPM_ADDING_TO_ROOT` | profile 是 pnpm workspace 根,`add`/`remove` 要加 `-w`。 |
|
|
495
|
+
| 安装时报 `ENOENT: … dsh-oc-tui-<版本>.tgz` | profile 仍引用你已删除的 tarball。先 `dsh plugin --profile tui remove -w dsh-oc-tui`,再重新 add。 |
|
|
496
|
+
| `pnpm not found on PATH` | 安装 pnpm(`npm install -g pnpm`)后重试。 |
|
|
497
|
+
| `--dump-config` 里没有 TUI 层 | 安装未完成或包名拼写不一致;重跑 add 并检查 `dsh.profile.bundles`。 |
|
|
498
|
+
| 启动后立刻退出或没有界面 | stdin/stdout 必须都是 TTY,不要重定向或管道;再确认模型路由与凭据文件就绪。 |
|
|
499
|
+
| `--resume` 或 管理会话 不可用 | 两者都需要共享的 `sessionQuery` 服务;确保 `dsh.profile.bundles` 第一项仍是 `@deepseek-ai/dsh-base`。 |
|
|
500
|
+
| `--resume` 报 `no agent factory registered` | 与 agent-loop 行的启动竞态;当前构建会重试。旧构建可先启动、再用 `/resume <id>`。 |
|
|
501
|
+
| 更新 dsh 后启动报 loader 错误(`State`、`./internal`) | 全局 dsh 处于新旧混杂状态:关闭所有 dsh 进程后 `npm install -g @deepseek-ai/dsh@<版本>`。 |
|
|
502
|
+
| 每次启动都打印 `incompatible with dsh <版本>` 的不兼容墙 | 宿主版本落在声明的 `engines.dsh` 范围之外。升级本插件、把 dsh 固定在受支持的版本,或授予精确版本豁免(拒绝信息里会直接给出命令):`dsh plugin --profile tui allow-version dsh-oc-tui@<版本> --dsh-version <版本> --accept-risk`。 |
|
|
503
|
+
| 改了源码不生效 | profile 里装的是 tarball 副本,需要重新打包再安装(见第 8 节)。 |
|
|
504
|
+
|
|
505
|
+
## 8. 开发
|
|
506
|
+
|
|
507
|
+
```sh
|
|
508
|
+
npm run check # 对 lib/、bin/ 做 node --check
|
|
509
|
+
npm test # 独立冒烟测试(不需要 dsh)
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
**安装即构建,所以顺序是:改源码 → 打包 → 重新安装。** profile 里装的是本插件的 **tarball** 副本,而 profile 的热更新监视的是 profile 目录、不是插件目录——改这个检出不会影响任何东西,除非重新打包并重装:
|
|
513
|
+
|
|
514
|
+
```sh
|
|
515
|
+
dsh plugin --profile tui remove -w dsh-oc-tui # 先摘掉旧依赖
|
|
516
|
+
Remove-Item .\*.tgz # 再删掉旧 tarball
|
|
517
|
+
npm pack
|
|
518
|
+
dsh plugin --profile tui add -w .\dsh-oc-tui-<版本>.tgz
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
**顺序不能颠倒**:pnpm 在 add 时会解析 profile 现有的 `file:` 依赖,指向已删除 tarball 会让整个安装以 `ENOENT` 中止。
|
|
522
|
+
|
|
523
|
+
装完要**逐文件哈希核对**(版本号本身证明不了任何事):
|
|
524
|
+
|
|
525
|
+
```powershell
|
|
526
|
+
foreach ($rel in @('lib\index.js','lib\ui.js','lib\util.js','lib\term.js','lib\metrics.js',
|
|
527
|
+
'lib\interrupt.js','lib\web-settings.js','lib\updates.js','lib\markdown.js',
|
|
528
|
+
'lib\startup.js','bin\dsh-oc-tui.js','cordis.patch.yml')) {
|
|
529
|
+
$a = (Get-FileHash ".\$rel").Hash
|
|
530
|
+
$b = (Get-FileHash "$env:USERPROFILE\.dsh\profiles\tui\node_modules\dsh-oc-tui\$rel").Hash
|
|
531
|
+
if ($a -ne $b) { "DIFFERS: $rel" }
|
|
532
|
+
}
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
然后必须**真正跑起来**:只到标题屏不算验证——会话开启路径才是宿主 API 断裂暴露的地方,所以要发一条消息。`--resume` 要**单独测**,它是 apply 期路径,可能输掉一个其它路径不会遇到的启动竞态。
|
|
536
|
+
|
|
537
|
+
### 8.1 零安装开发引导
|
|
538
|
+
|
|
539
|
+
想跳过打包,可以让 profile 直接引用本检出的绝对路径:
|
|
540
|
+
|
|
541
|
+
```sh
|
|
542
|
+
dsh --profile tui --dump-config # 先初始化 base profile
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
```yaml
|
|
546
|
+
# $DSH_HOME/profiles/tui/cordis.patch.yml
|
|
547
|
+
- insert:
|
|
548
|
+
- id: tui-startup
|
|
549
|
+
name: 'file:///path/to/dsh-oc-tui/lib/startup.js'
|
|
550
|
+
- id: tui-app
|
|
551
|
+
name: 'file:///path/to/dsh-oc-tui/lib/index.js'
|
|
552
|
+
config:
|
|
553
|
+
sidebar: true
|
|
554
|
+
showReasoning: true
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
插件对 dsh 各包的 import 会通过 `$DSH_HOME/profiles/node_modules` 共享回退解析,因此无需在插件目录里安装依赖。
|
|
558
|
+
|
|
559
|
+
## 9. 已知限制
|
|
560
|
+
|
|
561
|
+
- 零依赖终端引擎尚未暴露 IME 组字;图片附件已支持:bracketed paste 的原始图片字节、`data:image/...;base64,...` 数据 URL、本地图片路径或图片 URL,均会成为附件并按[图形渲染](#56-图形渲染图片表格与-mermaid)显示,粘贴无法识别的文本时会向终端请求剪贴板(OSC 52)。
|
|
562
|
+
- 图形渲染:图片顶部行滚出转录窗口时显示空白占位,直到整图重新可见(kitty 无法把锚点放到屏幕外);GIF 仅取首帧;sixel/iTerm2 载荷在图片行移动时会重发——本地无感,慢速 SSH 链路上有节流兜底。
|
|
563
|
+
- 插件不支持热重载:profile 的 HMR 根是 profile 目录,运行中的 TUI 保持它启动时的那份副本。
|
|
564
|
+
- `dsh tui` 作为裸子命令需要 shell 别名——原版启动器只硬编码了 `web` 与 `plugin`。
|
|
565
|
+
- dsh 的人类斜杠命令需要活动会话;标题屏上会提示先建立会话。
|
|
566
|
+
- git 分支切换需要 `PATH` 上有 `git`、且工作区是 git 仓库;否则会如实提示且不做任何改动。它是空页面功能:会话已打开时,`Ctrl+G` 与 `/branch` 只会提示回到空页面。
|
|
567
|
+
- `Esc` 让出问题不会取消工具调用,而是委托;没有其它应答者时该工具调用会失败。WebUI composer 支持的**逐题跳过**尚未实现。
|
|
568
|
+
- `--resume`、设置 → 管理会话、会话统计条与上下文仪表依赖 `@deepseek-ai/dsh-base` 挂载的服务(`sessionQuery`、`sessionProjections`);手工搭建的 profile 需自行提供。`sessionStats` 投影只由 Web 应用层 bundle 挂载,缺少时 TUI 自行从会话日志折叠同样的数字。
|
|
569
|
+
- Windows 上的延迟 dsh 安装只等待**调度它的那个 TUI**,不是机器上所有 dsh 进程;执行前请关掉其它 TUI 窗口(以及 `dsh web`)。
|
|
570
|
+
|
|
571
|
+
## 10. 目录结构
|
|
572
|
+
|
|
573
|
+
```
|
|
574
|
+
lib/index.js 插件入口:agents、事件、输入、命令、授权、用户提问
|
|
575
|
+
lib/startup.js 命令行参数提供者(tuiStartup 服务)
|
|
576
|
+
lib/term.js 终端引擎(raw 模式、屏幕、按键解码、图像槽位与 OSC 8 发射)
|
|
577
|
+
lib/caps.js 终端能力探测(DA1 / XTVERSION / kitty 图形 / 单元格尺寸)
|
|
578
|
+
lib/image.js 图像管线(解码缩放 + halfblock/sixel/kitty/iTerm2 编码器)
|
|
579
|
+
lib/mermaid.js mermaid 多级 provider 链(mmdc → mermaid.ink → 高亮回退),只在内置引擎不认的语法上启用
|
|
580
|
+
lib/mermaid-ascii.js mermaid 原生制表符 art(制表符排版,优先于图像路径)
|
|
581
|
+
lib/ui.js 响应式视图模型 + 渲染器(会话面板,含问答弹窗)
|
|
582
|
+
lib/splash-opencode.js 标题屏艺术(OpenCode 式排版 + DeepSeek 渐变标识)
|
|
583
|
+
lib/metrics.js 整场会话统计 + token 用量折叠(Web 统计条 / tokenUsage 投影同规则)
|
|
584
|
+
lib/rewind.js rewind 选择器:从事件日志分叉会话 + 有 fenced 的文件回滚
|
|
585
|
+
lib/git-branch.js git 分支切换:本地/远程分支列表、检出、仅快进拉取(走 git CLI,限工作区内)
|
|
586
|
+
lib/interrupt.js Ctrl+C 生命周期状态机
|
|
587
|
+
lib/web-settings.js WebUI 设置投影(含 tui-graphics 命名空间)
|
|
588
|
+
lib/updates.js 程序内更新(npm registry + 安装)
|
|
589
|
+
lib/markdown.js markdown-it token 流 -> 带样式文本行(表格/嵌套列表/高亮/链接)
|
|
590
|
+
lib/util.js 文本/显示工具
|
|
591
|
+
lib/bridge.js 活体 TUI 注册表(@dsh-std facet 的转发目标)
|
|
592
|
+
lib/facet.js @dsh-std facet 入口(互操作外壳,不启动 TUI)
|
|
593
|
+
lib/std/ @dsh-std 协议适配(adapt、presentation、commands、command-list)
|
|
594
|
+
bin/dsh-oc-tui.js 便捷启动器
|
|
595
|
+
bin/apply-update.cjs 独立应用进程:等 TUI 退出、安装暂存 tarball、重启 dsh
|
|
596
|
+
install.sh 一键安装脚本(Linux/macOS)
|
|
597
|
+
install.ps1 一键安装脚本(Windows)
|
|
598
|
+
dsh-plugin.json @dsh-std 组件清单(仅用于发现与预检)
|
|
599
|
+
cordis.patch.yml bundle 补丁层(TUI 行、提问工具;刻意不含预设名册行,注释里写了原因)
|
|
600
|
+
docs/用户手册.md 本手册
|
|
601
|
+
docs/dsh-std-接入说明.md @dsh-std 接入范围与约束
|
|
602
|
+
tests/smoke.test.mjs 独立冒烟测试
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
## 11. 许可证
|
|
606
|
+
|
|
607
|
+
[LGPL-3.0-or-later](../LICENSE)
|