dsh-ssh-tui 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -1,12 +1,13 @@
1
1
  # dsh-ssh-tui
2
2
 
3
3
  A DeepSeek Harness terminal for jump hosts, headless servers, and high-latency
4
- SSH. Plain ANSI and incremental redraws. No browser, no Ink/React skin.
4
+ SSH. Plain ANSI and incremental redraws. No browser required.
5
5
 
6
6
  中文部署指南:[README.md](README.md)
7
7
 
8
- Who it is for: a keyboard-only SSH session on a remote box. Who it is not for:
9
- a local desktop TUI with many themes that lane already has a clear winner.
8
+ If you mostly work over SSH a jump host, a test box, a keyboard-only
9
+ session — start here. A local desktop terminal with themes and layout
10
+ you already like can stay as it is.
10
11
 
11
12
  ## Official headless vs this TUI
12
13
 
@@ -27,6 +28,19 @@ own card, the plan strip pinned above the input.
27
28
 
28
29
  Singles: [headless stdout](docs/screenshots/headless.png) · [dsh-ssh-tui](docs/screenshots/workspace.png)
29
30
 
31
+ ## Still visible on a slow SSH pipe
32
+
33
+ Same task, replayed at **2 kB/s** through the real incremental painter
34
+ (88×30, one `stdout.write` per frame). Official headless on that pipe
35
+ would stay blank until the final markdown. Here reasoning, the edit
36
+ diff, subagent cards, and the plan strip appear as the bytes arrive.
37
+
38
+ ![Same task replayed at 2 kB/s SSH](docs/screenshots/slow-link.gif)
39
+
40
+ Reproducible, no model in the loop: `npm run screenshots:slow` writes
41
+ `docs/screenshots/slow-link.json`. This capture is 14 paints, about
42
+ **15.5 KB**, **7.6 s** at 2 kB/s. Byte ledger for this event sequence.
43
+
30
44
  ## Requirements
31
45
 
32
46
  - Node.js >= 22.19
@@ -35,6 +49,26 @@ Singles: [headless stdout](docs/screenshots/headless.png) · [dsh-ssh-tui](docs/
35
49
 
36
50
  ## Install
37
51
 
52
+ On a remote box with `dsh` and pnpm already installed (no clone):
53
+
54
+ ```sh
55
+ dsh plugin --profile tui add dsh-ssh-tui
56
+ # optional: reuse a SuperGrok / grok-bridge token already on the machine
57
+ dsh plugin --profile tui add github:cyjyyd/dsh-llm-xai-oauth
58
+ dsh plugin --profile headless add github:cyjyyd/dsh-llm-xai-oauth
59
+ ```
60
+
61
+ Smoke the route before opening the TUI. The TUI exits immediately without a TTY:
62
+
63
+ ```sh
64
+ dsh --profile headless "Reply with exactly: tui-install-ok. Do not use tools."
65
+ dsh --profile tui
66
+ ```
67
+
68
+ From a checkout: `bash scripts/smoke-headless.sh` (prints an outcome summary, never a token).
69
+
70
+ From git:
71
+
38
72
  ```sh
39
73
  git clone https://github.com/cyjyyd/dsh-ssh-tui.git
40
74
  cd dsh-ssh-tui
@@ -49,14 +83,6 @@ npm run build
49
83
  dsh plugin --profile tui add "link:$(pwd)"
50
84
  ```
51
85
 
52
- Or install the published npm package directly (requires `@deepseek-ai/dsh` and
53
- `pnpm`, no local clone needed):
54
-
55
- ```sh
56
- dsh plugin --profile tui add dsh-ssh-tui
57
- # or from a repo checkout: bash scripts/install-npm.sh
58
- ```
59
-
60
86
  For the optional **智能路由模式 (routing-suite)** mode, also run:
61
87
 
62
88
  ```sh
@@ -151,7 +177,7 @@ The plugin runs on Linux, macOS, and Windows (Node ≥ 22.19):
151
177
  | `Ctrl+R` | expand or collapse all cards |
152
178
  | `Ctrl+T` | fold the input box (display-only) |
153
179
  | `Alt+1` / `2` / `3` / `4` | jump to latest thinking / plan / subagent / reply |
154
- | `/find [kind] query` | search cards (`thinking` `plan` `subagent` `reply`). `Ctrl+/` or `Alt+/` opens it |
180
+ | `/find [kind] query` | search and jump to the full matching message (`thinking` `plan` `subagent` `reply`). `Ctrl+/` or `Alt+/` opens it |
155
181
  | `Ctrl+G` / `Alt+N` | next search hit; `Alt+P` previous |
156
182
  | `Esc` | drop selection → scroll to bottom → cancel the running turn |
157
183
  | `Ctrl+C` | cancel the running turn; exit when idle |
@@ -195,7 +221,9 @@ into the parent stream.
195
221
  The plan strip pins only the **latest incomplete plan**. When the model
196
222
  opens a new plan in the same turn, the previous one archives into the
197
223
  scrolling transcript and the dock shows the new one. A finished plan says
198
- 「计划任务已全部完成」, not 「计划模式已关闭」. The `/` menu and
224
+ 「计划任务已全部完成」, not 「计划模式已关闭」. If a turn ends with open todos, the strip says 「本轮未收尾」, stops
225
+ spinning, and sends one follow-up asking the model to `todo_write` the
226
+ real statuses. The `/` menu and
199
227
  approval/question dialogs yield that bottom space. `exit_plan_mode` is
200
228
  markdown. `ask_user_question` still opens a dialog and leaves a collapsed
201
229
  `提问用户` card. `/goal` is a collapsed `目标` card. `/find thinking foo`
@@ -309,12 +337,10 @@ switching while running.
309
337
  ## Jump-host / proxied SSH
310
338
 
311
339
  Each paint is one `stdout.write` of dirty rows only, so a jump host or
312
- corporate proxy does not see one SSH packet per line. Default cadence is
313
- about 120 ms. On high-RTT paths raise it:
314
-
315
- ```sh
316
- export DSH_TUI_PAINT_MS=250 # 40–1000; higher = fewer packets, choppier stream
317
- ```
340
+ corporate proxy does not see one SSH packet per line. Local ttys use 80 ms.
341
+ Over SSH the TUI probes CSI 6n once and picks 80 / 160 / 250 / 400 ms from
342
+ the round-trip. `DSH_TUI_PAINT_MS` always wins (40–1000). `/status` and the
343
+ footer show the active tier.
318
344
 
319
345
  ## Development
320
346
 
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # dsh-ssh-tui
2
2
 
3
3
  给跳板机、无桌面服务器、高延迟 SSH 用的 DeepSeek Harness 终端。纯 ANSI、增量重绘,
4
- 不需要浏览器,也不需要 Ink / React 那套皮肤。
4
+ 不需要浏览器。
5
5
 
6
6
  English: [README.en.md](README.en.md)
7
7
 
8
- 适合谁:SSH 直连的远程机器、慢链路、只有键盘的会话。不适合谁:本机想要多主题、
9
- 官网级交互的桌面终端——那条赛道已经有明确赢家。
8
+ 如果你主要在 SSH 里写代码——公司跳板、测试机、只有键盘的会话——可以从这里开始。
9
+ 本机桌面终端若更在意主题和布局,也可以继续用你已经习惯的界面。
10
10
 
11
11
  SuperGrok / X Premium 订阅走配套插件 [dsh-llm-xai-oauth](https://github.com/cyjyyd/dsh-llm-xai-oauth),复用本机 grok-bridge token,不需要 xAI API Key。
12
12
 
@@ -23,6 +23,14 @@ SuperGrok / X Premium 订阅走配套插件 [dsh-llm-xai-oauth](https://github.c
23
23
 
24
24
  单独看:[headless stdout](docs/screenshots/headless.png) · [dsh-ssh-tui](docs/screenshots/workspace.png)
25
25
 
26
+ ## 弱网 SSH 上过程还在
27
+
28
+ 同一条任务,按 **2 kB/s** 限速回放真实增量绘制(88×30,一帧一次 `stdout.write`)。官方 headless 这条链路上只会在全部结束后突然打出最终 Markdown;这里思考、`edit` diff、子代理卡和计划条是随着字节到达逐步出现的。
29
+
30
+ ![2 kB/s SSH 上回放同一任务](docs/screenshots/slow-link.gif)
31
+
32
+ 协议(可复现,不靠模型估):`npm run screenshots:slow` → `docs/screenshots/slow-link.json`。这次回放 14 次绘制、约 **15.5 KB**,在 2 kB/s 上大约 **7.6 s** 画完。数字是这条固定事件序的 stdout 字节账。
33
+
26
34
  ## 功能一览
27
35
 
28
36
  - 纯终端渲染,无需浏览器/鼠标/重量级终端框架,适合慢速或远程 SSH;
@@ -53,7 +61,25 @@ SuperGrok / X Premium 订阅走配套插件 [dsh-llm-xai-oauth](https://github.c
53
61
 
54
62
  ## 部署指南
55
63
 
56
- ### 方式一:一键脚本(推荐)
64
+ 远程机器最短路径(已有 `dsh` 和 pnpm,无需 clone):
65
+
66
+ ```bash
67
+ dsh plugin --profile tui add dsh-ssh-tui
68
+ # 可选:本机已有 SuperGrok / grok-bridge token 时
69
+ dsh plugin --profile tui add github:cyjyyd/dsh-llm-xai-oauth
70
+ dsh plugin --profile headless add github:cyjyyd/dsh-llm-xai-oauth
71
+ ```
72
+
73
+ 先确认链路再开 TUI(无 TTY 时 TUI 会直接退出):
74
+
75
+ ```bash
76
+ dsh --profile headless "Reply with exactly: tui-install-ok. Do not use tools."
77
+ dsh --profile tui # 必须在真实终端 / SSH 会话里
78
+ ```
79
+
80
+ 仓库内也可:`bash scripts/smoke-headless.sh`(记录出口摘要,不打印 token)。
81
+
82
+ ### 方式一:从 git clone 安装
57
83
 
58
84
  ```bash
59
85
  git clone https://github.com/cyjyyd/dsh-ssh-tui.git
@@ -79,14 +105,10 @@ npm run build
79
105
  dsh plugin --profile tui add "link:$(pwd)"
80
106
  ```
81
107
 
82
- ### 方式三:npm 安装(发布后)
83
-
84
- 前置要求:已全局安装 `@deepseek-ai/dsh`(`npm i -g @deepseek-ai/dsh`)且有 pnpm。
108
+ ### 方式三:指定其它 profile 的 npm 安装
85
109
 
86
110
  ```bash
87
- dsh plugin --profile tui add dsh-ssh-tui
88
- # 或在仓库内快捷执行:bash scripts/install-npm.sh
89
- # 指定其它 profile:bash scripts/install-npm.sh work
111
+ bash scripts/install-npm.sh work
90
112
  ```
91
113
 
92
114
  `dsh plugin add` 会从 npm 拉取包、写入 profile 依赖,并自动把 `dsh-ssh-tui`
@@ -132,7 +154,7 @@ dsh --profile tui --no-color
132
154
  | `Ctrl+R` | 全部展开或全部收起 |
133
155
  | `Ctrl+T` | 折叠输入框(只影响显示) |
134
156
  | `Alt+1` / `2` / `3` / `4` | 跳到最新思考 / 计划 / 子代理 / 回复 |
135
- | `/find [类] 关键字` | 搜索卡片。类:`思考` `计划` `子代理` `回复`。`Ctrl+/` 或 `Alt+/` 打开 |
157
+ | `/find [类] 关键字` | 搜索并跳到该条完整消息(反色高亮)。类:`思考` `计划` `子代理` `回复`。`Ctrl+/` 或 `Alt+/` 打开 |
136
158
  | `Ctrl+G` / `Alt+N` | 下一条搜索结果;`Alt+P` 上一条 |
137
159
  | 鼠标左键 | 点击卡片标题展开/收起 |
138
160
  | `PgUp` / `PgDn`、滚轮 | 转录回看 |
@@ -171,7 +193,9 @@ SuperGrok / X Premium 走本机 OAuth,不需要填 Key。`/status` 和底栏
171
193
 
172
194
  计划条只钉**最新一条未完成的计划**。同一轮次里模型再开新计划时,旧计划归档进
173
195
  工作区随转录上滚,底栏换成新计划。任务全部完成后计划条会说「计划任务已全部完成」,
174
- 不再误报「计划模式已关闭」。打开 `/` 命令选单或批准/提问对话框时,计划条让出底栏。
196
+ 不再误报「计划模式已关闭」。一轮结束时若待办仍是进行中/待处理,计划条改成「本轮未收尾」并停止转圈,
197
+ 同时自动追问模型补一次 `todo_write`(同一列表只问一次,不改会话里的旧状态)。
198
+ 打开 `/` 命令选单或批准/提问对话框时,计划条让出底栏。
175
199
  `exit_plan_mode` 按 markdown 渲染。`ask_user_question` 仍弹对话框,并留下折叠的
176
200
  `提问用户` 卡片。`/goal` 是折叠的 `目标` 卡片。`/find 思考 padAnsi` 或 `Alt+1..4`
177
201
  可跳到对应类别的最新卡片。
@@ -274,10 +298,7 @@ npm run build
274
298
  - **标题栏或铃声不生效**:确认终端支持 OSC 0 与 BEL;铃声可用
275
299
  `DSH_TUI_NO_BELL=1` 关闭。
276
300
  - **滚轮误触取消**:已加入转义序列缓冲,网络拆包也不会把 `ESC` 当取消。
277
- - **跳板机 / 多层代理 SSH 发画**:每一帧只发脏行,并且拼成一次 `stdout.write`,避免一行一个 SSH 包。默认约 120 ms 合一帧。穿透代理、RTT 很大时:
278
- ```bash
279
- export DSH_TUI_PAINT_MS=250 # 40–1000;越大越省链路,流式字越顿
280
- ```
301
+ - **跳板机 / 多层代理 SSH 发画**:每一帧只发脏行,并且拼成一次 `stdout.write`。本机 80 ms;SSH 启动时用 CSI 6n 测往返,按 RTT 选 80/160/250/400 ms。`DSH_TUI_PAINT_MS` 始终优先(40–1000)。`/status` 和底栏显示当前档。
281
302
 
282
303
  ## License
283
304
 
package/cordis.patch.yml CHANGED
@@ -81,4 +81,4 @@
81
81
  maxToolOutputLines: 6
82
82
  color: !!js ctx.sshTuiStartup.noColor !== true
83
83
  # Jump-host SSH: coalesce token ticks into one stdout write per frame.
84
- paintIntervalMs: !!js Number.parseInt(process.env.DSH_TUI_PAINT_MS ?? '120', 10) || 120
84
+ paintIntervalMs: !!js Number.parseInt(process.env.DSH_TUI_PAINT_MS ?? '160', 10) || 160
Binary file