dsh-ssh-tui 0.1.0 → 0.1.2
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 +262 -0
- package/README.md +163 -219
- package/lib/tui.js +66 -2
- package/lib/tui.js.map +1 -1
- package/lib/types/tui.d.ts +5 -0
- package/package.json +2 -2
- package/README.zh-CN.md +0 -206
package/README.en.md
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# dsh-ssh-tui
|
|
2
|
+
|
|
3
|
+
An SSH-friendly interactive terminal (TUI) plugin for [DeepSeek
|
|
4
|
+
Harness](https://github.com/deepseek-ai/deepseek-harness). It renders the agent
|
|
5
|
+
session as a plain-ANSI chat transcript, streams model output, shows tool calls,
|
|
6
|
+
answers approvals and `ask_user_question` prompts from the keyboard, and lets
|
|
7
|
+
you resume persisted sessions. No browser, no mouse, no heavy terminal
|
|
8
|
+
framework — designed for slow/remote SSH links.
|
|
9
|
+
|
|
10
|
+
中文部署指南:[README.md](README.md)
|
|
11
|
+
|
|
12
|
+
## Requirements
|
|
13
|
+
|
|
14
|
+
- Node.js >= 22.19
|
|
15
|
+
- `@deepseek-ai/dsh` CLI: `npm i -g @deepseek-ai/dsh`
|
|
16
|
+
- pnpm (used by `dsh plugin` to manage profile dependencies)
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
git clone https://github.com/cyjyyd/dsh-ssh-tui.git
|
|
22
|
+
cd dsh-ssh-tui
|
|
23
|
+
bash scripts/install.sh # installs into the `tui` profile
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Or manually:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
npm install --no-audit --no-fund
|
|
30
|
+
npm run build
|
|
31
|
+
dsh plugin --profile tui add "link:$(pwd)"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Or install the published npm package directly (requires `@deepseek-ai/dsh` and
|
|
35
|
+
`pnpm`, no local clone needed):
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
dsh plugin --profile tui add dsh-ssh-tui
|
|
39
|
+
# or from a repo checkout: bash scripts/install-npm.sh
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Set `DEEPSEEK_API_KEY` (or a `$DSH_HOME/settings.yaml` / `.env` with the
|
|
43
|
+
credentials), then start:
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
dsh --profile tui
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Verify and uninstall:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
bash scripts/verify.sh
|
|
53
|
+
bash scripts/uninstall.sh
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## First-launch setup
|
|
57
|
+
|
|
58
|
+
On first launch (when no API key is configured) the TUI opens a setup wizard:
|
|
59
|
+
|
|
60
|
+
1. choose a provider template, matching the official Models page:
|
|
61
|
+
- DeepSeek official;
|
|
62
|
+
- OpenCode Go (`opencode.ai/zen/go/v1`, Responses protocol);
|
|
63
|
+
- custom OpenAI-compatible gateway (Completions);
|
|
64
|
+
- custom OpenAI Responses gateway;
|
|
65
|
+
- Anthropic Messages-compatible gateway;
|
|
66
|
+
2. for custom providers, enter a lowercase Provider ID (permanent), base URL,
|
|
67
|
+
API key (masked while typing), and one or more model IDs — each step has a
|
|
68
|
+
sensible template default. On the models step, press `Ctrl+F` to fetch the
|
|
69
|
+
current model list straight from the provider endpoint;
|
|
70
|
+
3. confirm and save.
|
|
71
|
+
|
|
72
|
+
The wizard writes the key to `~/.dsh/.credentials.yaml` when no environment
|
|
73
|
+
variable shadows it; if the machine injects `DEEPSEEK_API_KEY` from
|
|
74
|
+
`/etc/profile.d` or similar, it writes `~/.dsh/env.sh` (sourced by
|
|
75
|
+
`~/.profile` / `~/.bashrc` / `~/.zshenv` / `~/.zshrc` automatically,
|
|
76
|
+
idempotently) so your
|
|
77
|
+
value wins on the next launch. On Windows it runs `setx` and writes
|
|
78
|
+
`%USERPROFILE%\.dsh\env.cmd` as a fallback. Custom gateway base URLs are saved
|
|
79
|
+
to `$DSH_HOME/settings.yaml` as an `llm-pi-ai.providers.<id>` route (the same
|
|
80
|
+
shape the official custom-provider form writes). After saving a custom
|
|
81
|
+
provider, exit and launch with:
|
|
82
|
+
|
|
83
|
+
The wizard also remembers the selected provider/model in
|
|
84
|
+
`agent-default-model` (the same settings memory the official Models page
|
|
85
|
+
uses), so after setup you can just run:
|
|
86
|
+
|
|
87
|
+
```sh
|
|
88
|
+
dsh --profile tui
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`--provider <id> --model <id>` remains available as a temporary override.
|
|
92
|
+
|
|
93
|
+
You can reopen the wizard at any time with:
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
/setup
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Cross-platform support
|
|
100
|
+
|
|
101
|
+
The plugin runs on Linux, macOS, and Windows (Node ≥ 22.19):
|
|
102
|
+
|
|
103
|
+
- Linux/macOS: same command as above; the wizard persists credentials in
|
|
104
|
+
`~/.dsh/.credentials.yaml`, or `~/.dsh/env.sh` when a system-injected
|
|
105
|
+
environment variable must be overridden.
|
|
106
|
+
- Windows (PowerShell or Windows Terminal): install with the same npm/dsh
|
|
107
|
+
commands — `dsh` is on PATH via npm's global bin. The wizard stores the key
|
|
108
|
+
through the dsh credential store, or runs `setx` (plus `env.cmd`) when an
|
|
109
|
+
environment variable shadows the store. Agent shell tools automatically use
|
|
110
|
+
PowerShell on Windows (the harness disables bash there).
|
|
111
|
+
- Legacy Windows consoles without VT support: set `DSH_TUI_NO_ALT_SCREEN=1`
|
|
112
|
+
(and `--no-color` if needed) to skip the alternate-screen escape sequences.
|
|
113
|
+
- Keyboard input accepts both `\x7f` and `\x08` backspace, and both `\r` /
|
|
114
|
+
`\r\n` line endings.
|
|
115
|
+
|
|
116
|
+
## Usage
|
|
117
|
+
|
|
118
|
+
| Key | Action |
|
|
119
|
+
| --- | --- |
|
|
120
|
+
| `Enter` | send the message; while the agent is running, steers it |
|
|
121
|
+
| `Tab` | complete the highlighted slash command |
|
|
122
|
+
| `↑` / `↓` | navigate slash-command suggestions (or input history) |
|
|
123
|
+
| `Esc` / `Ctrl+C` | cancel the running turn |
|
|
124
|
+
| `Ctrl+D` | exit |
|
|
125
|
+
| `Ctrl+L` | redraw |
|
|
126
|
+
| `Ctrl+T` | fold/unfold the input box (display-only; submission keeps the full text) |
|
|
127
|
+
| `↑` / `↓` | input history |
|
|
128
|
+
| `y` / `n` / `Esc` | answer an approval prompt |
|
|
129
|
+
| `1..9` + `Enter` | answer an `ask_user_question` dialog |
|
|
130
|
+
|
|
131
|
+
Type `/` to see slash-command suggestions — the panel merges the TUI's own
|
|
132
|
+
commands with every command the harness registers (`/goal`, `/plan`,
|
|
133
|
+
`/compact`, `/permission`, `/feedback`, ...). `Tab` completes, `Enter` runs.
|
|
134
|
+
`/help` lists everything.
|
|
135
|
+
|
|
136
|
+
`/model` opens a two-step selector: pick a model from the current provider's
|
|
137
|
+
catalog, then pick its reasoning effort (`off` / `high` / `max` when the
|
|
138
|
+
provider exposes them). The change applies to the next request without
|
|
139
|
+
changing the provider, updates the header/status line, and is remembered in
|
|
140
|
+
`agent-default-model` for future launches.
|
|
141
|
+
|
|
142
|
+
For OpenCode and other third-party providers, `/model` queries the provider's
|
|
143
|
+
endpoint (`GET {baseURL}/models`) for a live model list, falling back to the
|
|
144
|
+
configured catalog when the endpoint cannot be reached. Picking a model that
|
|
145
|
+
is not stored in the provider profile automatically adds it to
|
|
146
|
+
`llm-pi-ai.providers.<id>.models` so the harness can serve it.
|
|
147
|
+
|
|
148
|
+
`/usage` (alias `/quota`) works when the current provider is an OpenCode
|
|
149
|
+
source and keeps the two billing models distinct:
|
|
150
|
+
|
|
151
|
+
- **OpenCode Go** queries the official quota endpoint and shows rolling
|
|
152
|
+
5-hour / weekly / monthly usage percentages, limit state, and reset times;
|
|
153
|
+
- **OpenCode Zen** is metered per API bill and has no fixed quota, so the TUI
|
|
154
|
+
points to `https://opencode.ai/zen` for balance/billing and shows the
|
|
155
|
+
session token usage it has recorded instead of inventing a quota.
|
|
156
|
+
|
|
157
|
+
The startup screen shows the official DeepSeek whale logo (rendered from the
|
|
158
|
+
harness favicon) in the DeepSeek brand color, with the wordmark below it. The
|
|
159
|
+
logo scales to the terminal width — a 52-column variant on wide terminals,
|
|
160
|
+
down to a compact variant on narrow ones — so it never looks squeezed. A
|
|
161
|
+
horizontal rule separates the workspace (transcript, reasoning, tool cards)
|
|
162
|
+
from the input area.
|
|
163
|
+
|
|
164
|
+
Model reasoning blocks are collapsed by default: while thinking a compact
|
|
165
|
+
`▸ 思考中 ⠹ · N 字 · Ns` line with a spinner replaces the raw stream, and
|
|
166
|
+
after the turn each block collapses to a `▸ 已思考 · N 行` summary without
|
|
167
|
+
its content. The thinking block can be expanded live while streaming to watch
|
|
168
|
+
the raw reasoning as it arrives. Assistant replies render in bold white with
|
|
169
|
+
terminal markdown support: heading levels (H1 enlarged/underlined, H2
|
|
170
|
+
underlined, H3 colored), bold, italic, inline code, fenced code blocks,
|
|
171
|
+
lists, quotes, and links all get ANSI styling while remaining
|
|
172
|
+
width-wrapped for the terminal. Reasoning and tool cards are
|
|
173
|
+
each expandable/collapsible independently — `Ctrl+N` / `Ctrl+P` move the
|
|
174
|
+
selection highlight between them, `Ctrl+R` expands/collapses all blocks at once
|
|
175
|
+
(individual blocks use `↑`/`↓` + `Enter`), and `Esc` drops the selection. With
|
|
176
|
+
the input box empty, `↑`/`↓` move the selection and `Enter` toggles the
|
|
177
|
+
selected block directly. Clicking a reasoning or tool header in the transcript
|
|
178
|
+
also toggles it.
|
|
179
|
+
|
|
180
|
+
The transcript is scrollable: `PgUp`/`PgDn` or the mouse wheel move back
|
|
181
|
+
through earlier reasoning blocks and tool calls, a `↑ 已回看 N 行` indicator
|
|
182
|
+
shows the scroll position, and `Esc` (or sending a message) returns to the
|
|
183
|
+
live bottom.
|
|
184
|
+
|
|
185
|
+
The terminal window title mirrors the session state while unfocused: an
|
|
186
|
+
animated spinner plus `运行中 · 工具 N` while working, `✓ 已完成` for a few
|
|
187
|
+
seconds after completion, and `待命` when idle. A terminal bell rings on
|
|
188
|
+
completion (`DSH_TUI_NO_BELL=1` disables it).
|
|
189
|
+
|
|
190
|
+
Tool calls render as compact cards instead of raw argument JSON. A colored
|
|
191
|
+
dot leads each card — yellow while running, green on success, red on failure
|
|
192
|
+
(a shell command with a non-zero exit or signal also turns red, with a
|
|
193
|
+
`[退出码 N]` / `[信号 X]` suffix). Shell tools show the command as
|
|
194
|
+
`$ command`, file mutations (`edit` / `write` / `str_replace_editor`) render
|
|
195
|
+
the applied change git-style: a path header, `-` lines on a light-red
|
|
196
|
+
background, `+` lines on a light-green background, and a `└ +N -M · K file(s)`
|
|
197
|
+
footer. File-mutation diffs are shown in full (never collapsed to a `… more`
|
|
198
|
+
line) and their cards start expanded. Other tools show a short argument
|
|
199
|
+
summary and start collapsed to a single line (the command, truncated with
|
|
200
|
+
`…` when long); expand to reveal output or the result body. Expanded generic
|
|
201
|
+
calls convert their JSON arguments and JSON results into readable indented
|
|
202
|
+
content — key/value fields, bullet lists, and multiline blocks for
|
|
203
|
+
code/content — instead of raw JSON text.
|
|
204
|
+
|
|
205
|
+
A web-aligned session stats line sits below the input box: turn/step counts,
|
|
206
|
+
model and tool wall time, first-token latency, tokens/second, cache-hit
|
|
207
|
+
percentage, and billed input/output tokens (`输入 12.3K · 输出 1.2K`), updated
|
|
208
|
+
as the session progresses.
|
|
209
|
+
|
|
210
|
+
While a turn is waiting on the provider, the status line shows
|
|
211
|
+
`等待响应 Ns`; if nothing arrives for 60s a warning appears and `Esc` /
|
|
212
|
+
`Ctrl+C` cancels the turn. Follow-ups sent while a turn is running are
|
|
213
|
+
acknowledged immediately (`⚡ … 排队 N`) and take effect at the next step
|
|
214
|
+
boundary, so the UI never looks frozen. Long-running work is not
|
|
215
|
+
misclassified: while tools are executing the status shows `工具执行中 N`,
|
|
216
|
+
and while subagents are running it shows `子代理执行中 N` (no
|
|
217
|
+
`等待响应`/stall warning). Subagent start/end, child assistant output, child
|
|
218
|
+
tool calls/results, approvals, and `ask_user_question` prompts are all
|
|
219
|
+
rendered with a `[子代理 …]` label; `/subagents` lists active runs.
|
|
220
|
+
|
|
221
|
+
`/mode` opens the agent-mode picker backed by dsh's official preset roster:
|
|
222
|
+
标准模式 (standard), PTC 模式 (code), 极简模式 (minimal), 创造模式 (cordis),
|
|
223
|
+
plus any locally authored presets. On a session that has not produced work
|
|
224
|
+
the switch applies immediately; otherwise it is remembered as the default for
|
|
225
|
+
the next launch. The active mode is shown in the header/status line.
|
|
226
|
+
|
|
227
|
+
`/resume` switches the running TUI to a past session. With no argument it
|
|
228
|
+
opens a picker of recent sessions (excluding subagents), labeled by the user's
|
|
229
|
+
first message with a time/cwd description; `/resume <session-id>` switches
|
|
230
|
+
directly. Switching is refused while a turn is running.
|
|
231
|
+
|
|
232
|
+
```sh
|
|
233
|
+
dsh --profile tui --model deepseek-v4-flash
|
|
234
|
+
dsh --profile tui --no-color
|
|
235
|
+
dsh --profile tui --resume <session-id>
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
`dsh --profile tui` starts a fresh session directly in the main interface.
|
|
239
|
+
`dsh --profile tui --resume` (or `dsh --profile tui resume`) opens the
|
|
240
|
+
history-session picker before the main interface; `dsh --profile tui --resume
|
|
241
|
+
<session-id>` (or `dsh --profile tui resume <session-id>`) skips the picker
|
|
242
|
+
and resumes directly. `dsh --profile tui --new` explicitly starts fresh
|
|
243
|
+
without the picker. The in-app `/resume` command remains available for
|
|
244
|
+
switching while running.
|
|
245
|
+
|
|
246
|
+
## Development
|
|
247
|
+
|
|
248
|
+
```sh
|
|
249
|
+
npm install
|
|
250
|
+
npm run build
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Privacy
|
|
254
|
+
|
|
255
|
+
All sessions, credentials, and settings live under `$DSH_HOME` (default
|
|
256
|
+
`~/.dsh`) — never inside this repository. `.gitignore` excludes
|
|
257
|
+
`node_modules/`, build output, `.env*`, keys, session logs, and local state, so
|
|
258
|
+
cloning or uploading the repo never carries user sessions or secrets.
|
|
259
|
+
|
|
260
|
+
## License
|
|
261
|
+
|
|
262
|
+
MIT
|