dsh-ssh-tui 0.3.4 → 0.3.6

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
@@ -9,6 +9,17 @@ If you mostly work over SSH — a jump host, a test box, a keyboard-only
9
9
  session — start here. A local desktop terminal with themes and layout
10
10
  you already like can stay as it is.
11
11
 
12
+ Install with the official CLI (no clone):
13
+
14
+ ```sh
15
+ dsh plugin --profile tui add dsh-ssh-tui
16
+ dsh --profile tui
17
+ ```
18
+
19
+ Current `dsh` requires `--profile` (`dsh plugin add …` errors without it).
20
+ Swap `tui` for another profile name. The same command updates. Remove with
21
+ `dsh plugin --profile tui remove dsh-ssh-tui`.
22
+
12
23
  ## Official headless vs this TUI
13
24
 
14
25
  There is no shipped TUI. The default terminal entry on a remote box is
@@ -49,11 +60,14 @@ Reproducible, no model in the loop: `npm run screenshots:slow` writes
49
60
 
50
61
  ## Install
51
62
 
52
- On a remote box with `dsh` and pnpm already installed (no clone):
63
+ The recommended install is the command at the top of this README:
64
+ `dsh plugin --profile tui add dsh-ssh-tui`. The CLI pulls npm, writes the
65
+ profile dependency, and appends this package to `dsh.profile.bundles`
66
+ because the manifest declares `dsh.bundle`.
67
+
68
+ Optional: reuse a SuperGrok / grok-bridge token already on the machine:
53
69
 
54
70
  ```sh
55
- dsh plugin --profile tui add dsh-ssh-tui
56
- # optional: reuse a SuperGrok / grok-bridge token already on the machine
57
71
  dsh plugin --profile tui add github:cyjyyd/dsh-llm-xai-oauth
58
72
  dsh plugin --profile headless add github:cyjyyd/dsh-llm-xai-oauth
59
73
  ```
@@ -67,6 +81,31 @@ dsh --profile tui
67
81
 
68
82
  From a checkout: `bash scripts/smoke-headless.sh` (prints an outcome summary, never a token).
69
83
 
84
+ ### Survive an SSH drop (tmux)
85
+
86
+ A slow-link-friendly painter is not the same as surviving a disconnect.
87
+ Closing the laptop or an idle jump host kills the TTY process. Put the TUI
88
+ in tmux so SSH is only the display:
89
+
90
+ ```sh
91
+ tmux new -s dsh -- dsh --profile tui
92
+ # after reconnecting
93
+ tmux attach -t dsh
94
+ ```
95
+
96
+ A second TUI on the same `sessionId` is refused (it would steal stdin and
97
+ approvals) and prints `tmux attach`. Locks live under `$DSH_HOME/tui-locks/`;
98
+ a leftover file from a crash is stolen if the pid is dead.
99
+ `DSH_TUI_NO_SESSION_LOCK=1` skips this.
100
+
101
+ On start the TUI checks npm for a newer `dsh-ssh-tui` and **notifies only**:
102
+
103
+ ```text
104
+ 发现新版本 dsh-ssh-tui 0.3.5(当前 0.3.4)。更新:dsh plugin --profile tui add dsh-ssh-tui
105
+ ```
106
+
107
+ Set `DSH_TUI_NO_UPDATE_CHECK=1` to skip. `/status` also shows the plugin version.
108
+
70
109
  From git:
71
110
 
72
111
  ```sh
@@ -187,17 +226,18 @@ The plugin runs on Linux, macOS, and Windows (Node ≥ 22.19):
187
226
  | `1..9` + `Enter` | answer an `ask_user_question` dialog |
188
227
 
189
228
  Type `/` to see slash-command suggestions — the panel merges the TUI's own
190
- commands (`/find`, `/model`, `/help`, ...) with every command the harness
229
+ commands (`/find`, `/model`, `/provider`, `/help`, ...) with every command the harness
191
230
  registers (`/goal`, `/plan`, `/compact`, `/permission`, `/feedback`, ...).
192
231
  `/compact` shows a spinning 「压缩上下文」 card and footer until it
193
232
  finishes, then the tokens recovered. `Tab` completes, `Enter` runs.
194
233
  `/help` lists everything.
195
234
 
196
- `/model` lists models for the **current** provider first. On SuperGrok that
197
- is `grok-4.6` / `grok-4.5` plus reasoning effort (`xhigh` on 4.6). Switching
198
- to DeepSeek or OpenCode is an explicit “change provider” step. `/setup` is
199
- only for API-key providers; SuperGrok / X Premium uses local OAuth and does
200
- not need a key. `/status` and the footer show the same route.
235
+ `/model` lists models for the **current** provider only. On SuperGrok that
236
+ is `grok-4.6` / `grok-4.5` plus reasoning effort (`xhigh` on 4.6). `/provider`
237
+ switches provider, then model; it takes effect on the **next request** — no
238
+ restart. Each provider’s last model and effort is remembered. `/setup` adds
239
+ or updates one API-key provider without wiping the others. SuperGrok / X
240
+ Premium uses local OAuth and does not need a key.
201
241
 
202
242
  For OpenCode and other third-party providers, `/model` queries the provider's
203
243
  endpoint (`GET {baseURL}/models`) for a live model list, falling back to the
@@ -236,17 +276,20 @@ Interrupted streaming output keeps the already-generated prefix and is marked
236
276
  system messages. Harness slash commands that accept image attachments are
237
277
  labelled `(images ok)` in the command list and completion hints.
238
278
 
239
- `/usage` (alias `/quota`) follows the **current** provider:
279
+ `/usage` (alias `/balance`; `/quota` still works) follows the **current** provider:
240
280
 
281
+ - **DeepSeek official** `GET {baseURL}/user/balance`;
282
+ - **OpenAI Completions gateways** probe `/user/balance` and `credit_grants`;
241
283
  - **SuperGrok** reads `GET cli-chat-proxy.grok.com/v1/billing` (weekly remaining %);
242
284
  - **OpenCode Go** reads the official `/v1/usage` windows (5-hour / week / month);
243
285
  - **OpenCode Zen** is metered — the TUI points at `https://opencode.ai/zen`.
244
286
 
245
- Quota is fetched at startup. Recheck cadence follows the tightest window:
246
- every 10 turns for a 5-hour cap (every 4 when near a threshold), every 50
247
- for weekly (every 10 when near), every 80 for monthly (every 20 when near).
248
- Crossing 50% / 25% / 10% / 5% remaining posts a ⚠ planning reminder. The
249
- footer shows the tightest window.
287
+ OpenCode Go / SuperGrok quota is fetched silently at start and on a
288
+ window-based cadence; the footer shows remaining %. A transcript line
289
+ appears only when remaining crosses 50% / 25% / 10% / 5%. `/usage` or
290
+ `/balance` still prints the full snapshot. Cadence: every 10 turns for a
291
+ 5-hour cap (every 4 when near), every 50 for weekly (every 10 when near),
292
+ every 80 for monthly (every 20 when near).
250
293
 
251
294
  The startup screen shows the official DeepSeek whale logo (rendered from the
252
295
  harness favicon) in the DeepSeek brand color, with the wordmark below it. The
@@ -344,8 +387,12 @@ switching while running.
344
387
  Each paint is one `stdout.write` of dirty rows only, so a jump host or
345
388
  corporate proxy does not see one SSH packet per line. Local ttys use 80 ms.
346
389
  Over SSH the TUI probes CSI 6n once and picks 80 / 160 / 250 / 400 ms from
347
- the round-trip. `DSH_TUI_PAINT_MS` always wins (40–1000). `/status` and the
348
- footer show the active tier.
390
+ the round-trip. `DSH_TUI_PAINT_MS` always wins (40–1000). The stats line
391
+ starts with `SSH ●●●○ 90ms` (1 pip red, 2 yellow, 3+ green). The probe
392
+ does not write into the transcript.
393
+
394
+ SSH disconnect still kills a TUI that is not inside tmux. Do not start a
395
+ second copy of the same session from another window.
349
396
 
350
397
  ## Development
351
398
 
package/README.md CHANGED
@@ -10,6 +10,15 @@ English: [README.en.md](README.en.md)
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
 
13
+ 安装(官方 CLI,无需 clone):
14
+
15
+ ```bash
16
+ dsh plugin --profile tui add dsh-ssh-tui
17
+ dsh --profile tui
18
+ ```
19
+
20
+ 当前 `dsh` 必须带 `--profile`(`dsh plugin add …` 会报缺选项)。装进别的 profile 把 `tui` 换成那个名字即可。更新同一条命令。卸载:`dsh plugin --profile tui remove dsh-ssh-tui`。
21
+
13
22
  ## 官方 headless 和这个 TUI
14
23
 
15
24
  官方没有预置 TUI。远程机器上的默认终端入口是 `dsh --profile headless`:跑完一个任务,把**最后一条助手回复**打到 stdout 就退出。思考、工具调用、子代理、计划都在会话日志里,终端上看不到。
@@ -42,8 +51,8 @@ SuperGrok / X Premium 订阅走配套插件 [dsh-llm-xai-oauth](https://github.c
42
51
  编辑工具 git 风格 diff(`-` 浅红底 / `+` 浅绿底 / 文件统计,编辑卡片默认展开且
43
52
  diff 内容不截断)、JSON 参数与结果自动转可读内容;
44
53
  - 转录区滚动回看(`PgUp`/`PgDn`、鼠标滚轮),点击思考/工具标题行直接展开收起;
45
- - 输入框下方会话统计行:轮次/步数、模型与工具耗时、TTFT、tok/s、缓存命中率、
46
- 输入/输出 token(与 web 端口径一致);
54
+ - 输入框下方两行底栏:第一行链路芯片 + 按宽度丢组的会话数字(轮次、入/出 token、速度);
55
+ 第二行只留一个活动词(运行中 / 工具 N / 子代理 N / 压缩中…),身份收到右侧;
47
56
  - 历史会话启动选择器:`dsh --profile tui --resume`(或 `resume`)先选会话再进入;
48
57
  - 终端窗口标题栏:运行中旋转图标 + `运行中 · 工具 N`,完成后 `✓ 已完成`,并响
49
58
  一声终端铃(`DSH_TUI_NO_BELL=1` 关闭);
@@ -61,11 +70,11 @@ SuperGrok / X Premium 订阅走配套插件 [dsh-llm-xai-oauth](https://github.c
61
70
 
62
71
  ## 部署指南
63
72
 
64
- 远程机器最短路径(已有 `dsh` pnpm,无需 clone):
73
+ 推荐安装就是文首那条 `dsh plugin --profile tui add dsh-ssh-tui`。CLI 会从 npm 拉包、写入 profile 依赖,并把本插件加入 `dsh.profile.bundles`(因为包内声明了 `dsh.bundle`)。
74
+
75
+ 可选:本机已有 SuperGrok / grok-bridge token 时再装配套 OAuth:
65
76
 
66
77
  ```bash
67
- dsh plugin --profile tui add dsh-ssh-tui
68
- # 可选:本机已有 SuperGrok / grok-bridge token 时
69
78
  dsh plugin --profile tui add github:cyjyyd/dsh-llm-xai-oauth
70
79
  dsh plugin --profile headless add github:cyjyyd/dsh-llm-xai-oauth
71
80
  ```
@@ -77,6 +86,29 @@ dsh --profile headless "Reply with exactly: tui-install-ok. Do not use tools."
77
86
  dsh --profile tui # 必须在真实终端 / SSH 会话里
78
87
  ```
79
88
 
89
+ ### SSH 断线后续跑(tmux)
90
+
91
+ 弱网友好不等于断线后还能跑。合盖、跳板 idle、换网会杀掉当前 TTY 上的进程。
92
+ 把 TUI 放进 tmux,断 SSH 只丢显示器,不丢 Agent:
93
+
94
+ ```bash
95
+ tmux new -s dsh -- dsh --profile tui
96
+ # 断线后重新 SSH 进来
97
+ tmux attach -t dsh
98
+ ```
99
+
100
+ 同一 `sessionId` 不能开第二份 TUI(会抢 stdin 和审批)。第二份启动会退出并提示
101
+ `tmux attach`。锁在 `$DSH_HOME/tui-locks/`;进程异常退出后残留锁会在下次启动时
102
+ 核对 pid,已死则自动接管。调试可设 `DSH_TUI_NO_SESSION_LOCK=1`。
103
+
104
+ 启动时会查一次 npm 上的 `dsh-ssh-tui` 最新版,有更新只提示、不自动升级:
105
+
106
+ ```text
107
+ 发现新版本 dsh-ssh-tui 0.3.5(当前 0.3.4)。更新:dsh plugin --profile tui add dsh-ssh-tui
108
+ ```
109
+
110
+ `DSH_TUI_NO_UPDATE_CHECK=1` 可关掉。`/status` 里也能看到当前插件版本。
111
+
80
112
  仓库内也可:`bash scripts/smoke-headless.sh`(记录出口摘要,不打印 token)。
81
113
 
82
114
  ### 方式一:从 git clone 安装
@@ -105,15 +137,14 @@ npm run build
105
137
  dsh plugin --profile tui add "link:$(pwd)"
106
138
  ```
107
139
 
108
- ### 方式三:指定其它 profile 的 npm 安装
140
+ ### 方式三:指定其它 profile
109
141
 
110
142
  ```bash
143
+ dsh plugin --profile work add dsh-ssh-tui
144
+ # 或仓库脚本
111
145
  bash scripts/install-npm.sh work
112
146
  ```
113
147
 
114
- `dsh plugin add` 会从 npm 拉取包、写入 profile 依赖,并自动把 `dsh-ssh-tui`
115
- 加入该 profile 的 `dsh.profile.bundles`。
116
-
117
148
  ### 智能路由模式(dsh-routing-suite)
118
149
 
119
150
  需要“智能路由模式”时,安装 `dsh-routing-suite` 并注册其 preset:
@@ -163,18 +194,18 @@ dsh --profile tui --no-color
163
194
  | `Ctrl+D` | 退出 |
164
195
  | `Ctrl+L` | 重绘整个画面 |
165
196
 
166
- 斜杠命令:`/help`、`/find`、`/model`、`/submodel`、`/subeffort`、`/mode`、`/resume`、
167
- `/status`、`/subagents`、`/usage`(`/quota` 同义)、`/setup`、`/clear`,
197
+ 斜杠命令:`/help`、`/find`、`/model`、`/provider`、`/submodel`、`/subeffort`、`/mode`、`/resume`、
198
+ `/status`、`/subagents`、`/usage`(`/balance` 同义)、`/setup`、`/clear`,
168
199
  以及 harness 自带命令(`/goal`、`/plan`、`/compact` 等)。`/compact` 进行中会显示
169
200
  「压缩上下文」卡片和底栏转圈,结束时写出回收的 token 数。模型请求失败会显示重试
170
201
  进度;会话标题由模型生成后写到窗口标题。harness 命令若声明
171
202
  支持图片附件,会在命令列表和补全提示中标注“可附图”。
172
203
 
173
- `/model` 默认列出**当前提供商**的模型。已经在 SuperGrok 时,直接选
174
- `grok-4.6` / `grok-4.5` 和思考强度(`grok-4.6` 含 `xhigh`);要换 DeepSeek
175
- OpenCode 再选「更换提供商」。`/setup` 只用于配置 API Key 提供商,
176
- SuperGrok / X Premium 走本机 OAuth,不需要填 Key。`/status` 和底栏同样
177
- 显示这条路由。
204
+ `/model` 只换**当前提供商**的模型和思考强度。已经在 SuperGrok 时,直接选
205
+ `grok-4.6` / `grok-4.5`(`grok-4.6` 含 `xhigh`)。要换 DeepSeek / OpenCode /
206
+ 其它路由用 `/provider`:先选提供商,再选模型,**下一步请求生效,不用重启**。
207
+ 每个提供商上次的模型和思考强度会分开记住。`/setup` 只新增或更新当前这条
208
+ API Key 提供商,不会冲掉其它路由。SuperGrok / X Premium 走本机 OAuth,不需要填 Key。
178
209
 
179
210
  子代理默认跟随父会话的提供方,并尽量选同一家的轻量模型:DeepSeek 用
180
211
  `deepseek-v4-flash` / `deepseek-v4-flash-vision-exp`,xAI 用 `grok-4.5`。
@@ -202,13 +233,15 @@ SuperGrok / X Premium 走本机 OAuth,不需要填 Key。`/status` 和底栏
202
233
  `提问用户` 卡片。`/goal` 是折叠的 `目标` 卡片。`/find 思考 padAnsi` 或 `Alt+1..4`
203
234
  可跳到对应类别的最新卡片。
204
235
 
205
- `/usage`(`/quota` 同义)按**当前提供商**查额度:
236
+ `/usage`(`/balance` 同义,旧名 `/quota` 仍可用)按**当前提供商**查额度或余额:
206
237
 
238
+ - **DeepSeek 官方**:`GET {baseURL}/user/balance`(文档接口),显示可用/赠送/充值余额;
239
+ - **OpenAI Completions 兼容网关**:按配置的 base URL 探测 `/user/balance`、`/dashboard/billing/credit_grants` 等;
207
240
  - **SuperGrok**:`GET cli-chat-proxy.grok.com/v1/billing`,显示本周剩余%;
208
241
  - **OpenCode Go**:官方 `/v1/usage`,滚动 5 小时 / 本周 / 本月剩余%;
209
242
  - **OpenCode Zen**:按量计费、没有固定额度,提示到 `https://opencode.ai/zen`。
210
243
 
211
- 启动时查一次。之后按最紧窗口调查询:5 小时额度每 10 轮(接近阈值改 4 轮),周额度每 50 轮(接近改 10 轮),月额度每 80 轮(接近改 20 轮)。剩余跨过 50% / 25% / 10% / 5% 时用 ⚠ 提示合理规划。底栏显示最紧窗口的剩余百分比。
244
+ OpenCode Go / SuperGrok 启动和运行中都静默查询,底栏只显示剩余%;跨过 50% / 25% / 10% / 5% 才往工作区打 ⚠。`/usage` 或 `/balance` 仍打印完整结果。查询节奏按最紧窗口:5 小时额度每 10 轮(接近改 4 轮),周额度每 50 轮(接近改 10 轮),月额度每 80 轮(接近改 20 轮)。
212
245
 
213
246
  ## 配置
214
247
 
@@ -228,7 +261,9 @@ ssh-tui-subagent:
228
261
  ```
229
262
 
230
263
  `/model`、`/mode`、`/submodel` 与 `/subeffort` 的修改会写回这里,
231
- web 端与 TUI 共用同一份设置。
264
+ web 端与 TUI 共用同一份设置。`/model` 换提供商后**下一步请求生效**,不必重启。
265
+ 每个提供商上次的模型和思考强度记在 `ssh-tui-routes` 里,切回 SuperGrok / 官方 / Go 时会预填。
266
+ `/setup` 只更新当前这条提供商(模型列表会合并),不会删掉其它路由的 Key 和模型。
232
267
 
233
268
  对 OpenCode 和其他第三方提供商,`/model` 会先调用提供商的端点
234
269
  (`GET {baseURL}/models`)获取实时模型列表;端点不可达时回退到已配置的
@@ -278,10 +313,12 @@ bash scripts/uninstall.sh work # 指定 profile
278
313
  ## 开发与目录结构
279
314
 
280
315
  ```text
281
- src/index.ts 插件入口:启动选择器、会话创建/恢复/切换
316
+ src/index.ts 插件入口:启动选择器、会话创建/恢复/切换、session lock
282
317
  src/startup.ts 命令行参数解析(--resume / --new / --model ...)
283
318
  src/picker.ts 启动历史会话选择器
284
319
  src/session-list.ts 历史会话扫描与标签(共享给 /resume)
320
+ src/session-lock.ts 同会话防双开
321
+ src/update-check.ts npm 最新版提示(不自动升级)
285
322
  src/tui.ts 终端渲染、交互、统计、标题/铃声
286
323
  cordis.patch.yml dsh bundle patch(挂载 TUI 与 agent-presets)
287
324
  scripts/ 安装 / 卸载 / 验证脚本
@@ -301,7 +338,9 @@ npm run build
301
338
  - **标题栏或铃声不生效**:确认终端支持 OSC 0 与 BEL;铃声可用
302
339
  `DSH_TUI_NO_BELL=1` 关闭。
303
340
  - **滚轮误触取消**:已加入转义序列缓冲,网络拆包也不会把 `ESC` 当取消。
304
- - **跳板机 / 多层代理 SSH 发画**:每一帧只发脏行,并且拼成一次 `stdout.write`。本机 80 ms;SSH 启动时用 CSI 6n 测往返,按 RTT 选 80/160/250/400 ms。`DSH_TUI_PAINT_MS` 始终优先(40–1000)。`/status` 和底栏显示当前档。
341
+ - **跳板机 / 多层代理 SSH 发画**:每一帧只发脏行,并且拼成一次 `stdout.write`。本机 80 ms;SSH 启动时用 CSI 6n 测往返,按 RTT 选 80/160/250/400 ms。`DSH_TUI_PAINT_MS` 始终优先(40–1000)。统计行最左是 `SSH ●●●○ 90ms`(一格红、两格黄、三格及以上绿)。探测不写进转录。
342
+ - **SSH 断了任务也没了**:用 tmux 开 TUI(见上文)。不要在另一个 SSH 窗口再开同一会话。
343
+ - **提示会话已在 pid 运行**:那份 TUI 还活着。`tmux attach -t dsh`;确认进程已死再删 `$DSH_HOME/tui-locks/` 对应文件。
305
344
 
306
345
  ## License
307
346
 
package/lib/index.js CHANGED
@@ -12,6 +12,8 @@ import { showSessionPicker } from './picker.js';
12
12
  import { mountTui } from './tui.js';
13
13
  import { defaultReasoningEffort } from './reasoning.js';
14
14
  import { createSubagentSelection } from './subagent-model.js';
15
+ import { acquireSessionLock, releaseSessionLock, sessionLockDisabled } from './session-lock.js';
16
+ import { installRouteMemory } from './route-memory.js';
15
17
  export const name = 'ssh-tui';
16
18
  /** Core services required before the terminal channel can drive an agent. */
17
19
  export const inject = ['agents', 'agentDefaultModel'];
@@ -26,11 +28,27 @@ export function apply(ctx, config) {
26
28
  throw new Error('dsh-ssh-tui: both stdin and stdout must be TTYs; use a terminal/SSH session');
27
29
  }
28
30
  const subagentSelection = createSubagentSelection(ctx);
31
+ installRouteMemory(ctx);
29
32
  ctx.effect(() => {
30
33
  let disposed = false;
31
34
  let switching = false;
32
35
  let handle;
33
36
  let controller;
37
+ let sessionLockPathHeld;
38
+ const dropSessionLock = async () => {
39
+ const path = sessionLockPathHeld;
40
+ sessionLockPathHeld = undefined;
41
+ if (path !== undefined)
42
+ await releaseSessionLock(path);
43
+ };
44
+ const takeSessionLock = async (sessionId) => {
45
+ if (sessionLockDisabled())
46
+ return;
47
+ const { path } = await acquireSessionLock(sessionId, {
48
+ tty: process.env.SSH_TTY ?? process.env.TTY,
49
+ });
50
+ sessionLockPathHeld = path;
51
+ };
34
52
  // An explicit in-process change (/setup or /model) wins over launch-time
35
53
  // CLI overrides for every session created or resumed later in this process.
36
54
  let liveSelection;
@@ -106,11 +124,19 @@ export function apply(ctx, config) {
106
124
  installModelSelection(agentCtx, selectionRef);
107
125
  await agentPresets?.mount(agentCtx);
108
126
  };
109
- handle = resume
110
- ? await agents.resume({ resumeSessionId: sessionId, agentOptions, setup })
111
- : await agents.create({ sessionId, meta: { cwd: process.cwd() }, agentOptions, setup });
127
+ await takeSessionLock(String(sessionId));
128
+ try {
129
+ handle = resume
130
+ ? await agents.resume({ resumeSessionId: sessionId, agentOptions, setup })
131
+ : await agents.create({ sessionId, meta: { cwd: process.cwd() }, agentOptions, setup });
132
+ }
133
+ catch (error) {
134
+ await dropSessionLock();
135
+ throw error;
136
+ }
112
137
  if (disposed) {
113
138
  await handle.dispose();
139
+ await dropSessionLock();
114
140
  return;
115
141
  }
116
142
  const presetId = agentPresets?.composedPreset(handle.agent.ctx) ?? agentPresets?.defaultId;
@@ -157,6 +183,7 @@ export function apply(ctx, config) {
157
183
  await handle.dispose();
158
184
  handle = undefined;
159
185
  }
186
+ await dropSessionLock();
160
187
  await start(SessionId(target), true);
161
188
  }
162
189
  catch (error) {
@@ -206,7 +233,10 @@ export function apply(ctx, config) {
206
233
  await start(SessionId(config.sessionId), config.resume === true);
207
234
  };
208
235
  void boot().catch((error) => {
209
- process.stderr.write(`dsh-ssh-tui: session "${bootingSessionId}" failed to start: ${errorChain(error)}\n`);
236
+ const detail = error instanceof Error && error.name === 'SessionLockHeldError'
237
+ ? error.message
238
+ : errorChain(error);
239
+ process.stderr.write(`dsh-ssh-tui: session "${bootingSessionId}" failed to start:\n${detail}\n`);
210
240
  const exit = ctx.get('appExit');
211
241
  if (exit !== undefined)
212
242
  exit(1);
@@ -218,6 +248,7 @@ export function apply(ctx, config) {
218
248
  pickerAbort.abort();
219
249
  await controller?.dispose();
220
250
  await handle?.dispose();
251
+ await dropSessionLock();
221
252
  };
222
253
  }, 'ssh-tui');
223
254
  }
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Remember the last model/effort per provider so /model and /setup can switch
3
+ * routes without wiping the previous provider's choice.
4
+ */
5
+ import z from '@deepseek-ai/schemastery';
6
+ import { installSettingsSection, settingsNamespace } from '@deepseek-ai/dsh-settings';
7
+ export const ROUTE_MEMORY_NAMESPACE = settingsNamespace('ssh-tui-routes');
8
+ /** Settings schema for `$DSH_HOME/settings.yaml` under ssh-tui-routes. */
9
+ export const ROUTE_MEMORY_SCHEMA = z.object({
10
+ providers: z.dict(z.object({
11
+ model: z.string(),
12
+ reasoningEffort: z.string().default(''),
13
+ })).default({}),
14
+ });
15
+ export function parseRouteMemory(raw) {
16
+ if (raw === null || typeof raw !== 'object' || Array.isArray(raw))
17
+ return {};
18
+ const out = {};
19
+ for (const [provider, value] of Object.entries(raw)) {
20
+ const id = provider.trim();
21
+ if (id === '' || value === null || typeof value !== 'object' || Array.isArray(value))
22
+ continue;
23
+ const row = value;
24
+ const model = typeof row.model === 'string' ? row.model.trim() : '';
25
+ if (model === '')
26
+ continue;
27
+ const effort = typeof row.reasoningEffort === 'string' ? row.reasoningEffort.trim() : '';
28
+ out[id] = effort === '' ? { model } : { model, reasoningEffort: effort };
29
+ }
30
+ return out;
31
+ }
32
+ export function rememberedRouteFor(memory, provider) {
33
+ return memory[provider.trim()];
34
+ }
35
+ /** Register the route-memory settings section so /model and /provider can persist. */
36
+ export function installRouteMemory(ctx) {
37
+ installSettingsSection(ctx, ROUTE_MEMORY_NAMESPACE, ROUTE_MEMORY_SCHEMA, {
38
+ providers: {},
39
+ }, {
40
+ setSource: () => { },
41
+ onChange: () => { },
42
+ });
43
+ }
44
+ export function upsertRememberedRoute(memory, provider, route) {
45
+ const id = provider.trim();
46
+ if (id === '' || route.model.trim() === '')
47
+ return memory;
48
+ return {
49
+ ...memory,
50
+ [id]: route.reasoningEffort === undefined || route.reasoningEffort === ''
51
+ ? { model: route.model }
52
+ : { model: route.model, reasoningEffort: route.reasoningEffort },
53
+ };
54
+ }
55
+ //# sourceMappingURL=route-memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-memory.js","sourceRoot":"","sources":["../src/route-memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Exclusive lock so two TUI processes do not drive the same session.
3
+ * Stale locks (dead pid) are stolen. Live locks tell the user to attach tmux.
4
+ */
5
+ import { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';
6
+ import { homedir } from 'node:os';
7
+ import { dirname, join } from 'node:path';
8
+ export class SessionLockHeldError extends Error {
9
+ lock;
10
+ path;
11
+ constructor(lock, path) {
12
+ super(formatLockHeldMessage(lock));
13
+ this.name = 'SessionLockHeldError';
14
+ this.lock = lock;
15
+ this.path = path;
16
+ }
17
+ }
18
+ export function sessionLockPath(sessionId, dshHome = process.env.DSH_HOME ?? join(homedir(), '.dsh')) {
19
+ const safe = sessionId.replaceAll(/[^A-Za-z0-9._-]/g, '_');
20
+ return join(dshHome, 'tui-locks', `${safe}.json`);
21
+ }
22
+ export function parseSessionLock(raw) {
23
+ try {
24
+ const parsed = JSON.parse(raw);
25
+ const pid = typeof parsed.pid === 'number' && Number.isInteger(parsed.pid) ? parsed.pid : undefined;
26
+ const sessionId = typeof parsed.sessionId === 'string' ? parsed.sessionId : undefined;
27
+ if (pid === undefined || pid <= 0 || sessionId === undefined || sessionId === '')
28
+ return undefined;
29
+ return {
30
+ pid,
31
+ sessionId,
32
+ startedAt: typeof parsed.startedAt === 'string' ? parsed.startedAt : '',
33
+ ...(typeof parsed.tty === 'string' && parsed.tty !== '' ? { tty: parsed.tty } : {}),
34
+ };
35
+ }
36
+ catch {
37
+ return undefined;
38
+ }
39
+ }
40
+ /** True when `pid` still exists on this machine (best-effort). */
41
+ export function processIsAlive(pid) {
42
+ if (!Number.isInteger(pid) || pid <= 0)
43
+ return false;
44
+ try {
45
+ process.kill(pid, 0);
46
+ return true;
47
+ }
48
+ catch (error) {
49
+ return error.code === 'EPERM';
50
+ }
51
+ }
52
+ export function formatLockHeldMessage(lock) {
53
+ const tty = lock.tty === undefined ? '' : ` · ${lock.tty}`;
54
+ return [
55
+ `会话 ${lock.sessionId} 已在 pid ${lock.pid}${tty} 运行。`,
56
+ '不要再开第二份 TUI。若 SSH 断过:tmux attach -t dsh',
57
+ '确认进程已死后,删除 $DSH_HOME/tui-locks/ 里对应的锁再启动。',
58
+ ].join('\n');
59
+ }
60
+ export function sessionLockDisabled(env = process.env) {
61
+ return env.DSH_TUI_NO_SESSION_LOCK === '1' || env.DSH_TUI_NO_SESSION_LOCK === 'true';
62
+ }
63
+ export async function acquireSessionLock(sessionId, options = {}) {
64
+ const path = sessionLockPath(sessionId, options.dshHome);
65
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
66
+ const info = {
67
+ pid: options.pid ?? process.pid,
68
+ sessionId,
69
+ startedAt: new Date().toISOString(),
70
+ ...(options.tty ? { tty: options.tty } : {}),
71
+ };
72
+ const payload = `${JSON.stringify(info, null, 2)}\n`;
73
+ for (let attempt = 0; attempt < 4; attempt++) {
74
+ try {
75
+ await writeFile(path, payload, { flag: 'wx', mode: 0o600 });
76
+ return { path, info };
77
+ }
78
+ catch (error) {
79
+ if (error.code !== 'EEXIST')
80
+ throw error;
81
+ let existing;
82
+ try {
83
+ existing = parseSessionLock(await readFile(path, 'utf8'));
84
+ }
85
+ catch {
86
+ existing = undefined;
87
+ }
88
+ const ours = options.pid ?? process.pid;
89
+ if (existing !== undefined && processIsAlive(existing.pid) && existing.pid !== ours) {
90
+ throw new SessionLockHeldError(existing, path);
91
+ }
92
+ try {
93
+ await unlink(path);
94
+ }
95
+ catch {
96
+ // Raced with another unlock; retry exclusive create.
97
+ }
98
+ }
99
+ }
100
+ throw new Error(`无法占用会话锁 ${path}`);
101
+ }
102
+ export async function releaseSessionLock(path, pid = process.pid) {
103
+ try {
104
+ const current = parseSessionLock(await readFile(path, 'utf8'));
105
+ if (current !== undefined && current.pid !== pid)
106
+ return;
107
+ await unlink(path);
108
+ }
109
+ catch {
110
+ // Missing lock is fine.
111
+ }
112
+ }
113
+ //# sourceMappingURL=session-lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-lock.js","sourceRoot":"","sources":["../src/session-lock.ts"],"names":[],"mappings":"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"}