@hyzyn/dsh-tty 0.9.0 → 0.10.1
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/LICENSE +214 -21
- package/README.md +77 -10
- package/client.js +32 -58
- package/lib/index.d.ts +24 -7
- package/lib/index.js +432 -112
- package/lib/index.js.map +1 -1
- package/lib/shell-integration.d.ts +11 -0
- package/lib/shell-integration.js +182 -48
- package/lib/shell-integration.js.map +1 -1
- package/lib/ssh.d.ts +24 -0
- package/lib/ssh.js +114 -2
- package/lib/ssh.js.map +1 -1
- package/lib/tmux.d.ts +48 -0
- package/lib/tmux.js +176 -0
- package/lib/tmux.js.map +1 -0
- package/package.json +26 -10
package/LICENSE
CHANGED
|
@@ -1,21 +1,214 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright [yyyy] [name of copyright owner]
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
|
202
|
+
Copyright 2026 dsh-plugin-kit contributors
|
|
203
|
+
|
|
204
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
205
|
+
you may not use this file except in compliance with the License.
|
|
206
|
+
You may obtain a copy of the License at
|
|
207
|
+
|
|
208
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
209
|
+
|
|
210
|
+
Unless required by applicable law or agreed to in writing, software
|
|
211
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
212
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
213
|
+
See the License for the specific language governing permissions and
|
|
214
|
+
limitations under the License.
|
package/README.md
CHANGED
|
@@ -18,7 +18,10 @@ xterm.js 全交互终端(node-pty 真实 PTY,WebGL 渲染器加速),支
|
|
|
18
18
|
补齐**管理闭环**:`sftp_mkdir`(parents 逐级补齐)/ `sftp_rename`(跨目录
|
|
19
19
|
移动)/ `sftp_remove`(递归删除)/ `sftp_tree`(限深递归列举);0.9.0 起
|
|
20
20
|
**SFTP 界面可选双栏风格**(左本机 / 右远程、行内直传,宿主服务端对拷),
|
|
21
|
-
面板头部压缩为「标签行 + SSH
|
|
21
|
+
面板头部压缩为「标签行 + SSH 连接栏」两行;0.10.0 起支持**会话持久化
|
|
22
|
+
(tmux)**——「持久终端」标签由 tmux server(专用 socket)托管,断线保活
|
|
23
|
+
超时、甚至宿主重启后重开标签即按名接回原现场(正在跑的程序原样存活),
|
|
24
|
+
SSH 侧同理(远程 tmux)。
|
|
22
25
|
|
|
23
26
|

|
|
24
27
|
|
|
@@ -55,7 +58,8 @@ dsh plugin --profile web add link:$(pwd)/packages/tty # 仓库开发调试
|
|
|
55
58
|
把面板收起——PTY 会话与输出缓冲保持存活,侧边栏「终端」入口上显示
|
|
56
59
|
「运行中/总数」徽标与状态点(有输出时脉冲提示),点击入口即可恢复;
|
|
57
60
|
悬浮条 ✕ / 标题栏 ✕ 才真正关闭并结束全部会话;
|
|
58
|
-
- 标题栏 ✕ 关闭面板并结束全部会话(PTY
|
|
61
|
+
- 标题栏 ✕ 关闭面板并结束全部会话(PTY 树级清理;tmux 持久标签同时
|
|
62
|
+
kill-session);会话退出后点终端区域可重开;
|
|
59
63
|
- 并发上限默认 4(配置 `maxSessions`,1~16)。
|
|
60
64
|
|
|
61
65
|

|
|
@@ -66,7 +70,7 @@ dsh plugin --profile web add link:$(pwd)/packages/tty # 仓库开发调试
|
|
|
66
70
|
|
|
67
71
|
| 工具 | 作用 |
|
|
68
72
|
| --- | --- |
|
|
69
|
-
| `tty_list` | 列出活跃终端会话(sid / kind(local\|ssh)/ target / pid / **cwd 实时跟随 cd** /
|
|
73
|
+
| `tty_list` | 列出活跃终端会话(sid / kind(local\|ssh)/ target / pid / **cwd 实时跟随 cd** / 活动时间;tmux 持久会话带 `persist` 标记) |
|
|
70
74
|
| `tty_capture` | 读取近期输出(尾部 N 行,默认清洗 ANSI,`raw:true` 取原始流);**`last:true` 只返回上一条已完成命令的输出 + 退出码**(shell 集成标记,见下节) |
|
|
71
75
|
| `tty_screen` | 读取**当前可见屏幕**的渲染结果(xterm-headless 虚拟屏,纯文本)——能真正读懂 vim / htop / 菜单等 TUI 界面 |
|
|
72
76
|
| `tty_expect` | 用正则**等待后续输出**中的就绪信号(dev server URL、构建完成等);超时不抛错(`matched:false` + 尾部输出),命令提前结束也会带退出码早停 |
|
|
@@ -163,6 +167,54 @@ subsystem,宿主半体 `src/sftp.ts`):
|
|
|
163
167
|
递归、同名覆盖,**字节不经过浏览器**);单窗体风格照旧,设置卡片切换,
|
|
164
168
|
重新打开 SFTP 生效。
|
|
165
169
|
|
|
170
|
+
## 会话持久化(tmux,0.10.0)
|
|
171
|
+
|
|
172
|
+
默认安全模型不变:会话随宿主生死(内核级 PTY 清理)。需要「活得比宿主久」
|
|
173
|
+
的工作(dev server、build、训练任务),开**持久终端**——会话状态委托给
|
|
174
|
+
tmux server(专用 socket `dsh-tty`,与用户自己的 tmux 完全隔离),断线保活
|
|
175
|
+
超时、甚至宿主重启后都能接回:
|
|
176
|
+
|
|
177
|
+
- **入口(0.10.1 简化)**:设置卡片「会话持久化」选 `tmux` 即唯一开关——开启后
|
|
178
|
+
**所有新开的标签默认持久化**:「+」菜单的「本地终端」、连接簿条目点击、
|
|
179
|
+
SSH 连接对话框(「持久会话」默认勾选,单次连接可取消)。不再有单独的
|
|
180
|
+
「持久终端」菜单项与条目级勾选;
|
|
181
|
+
- **机制**:spawn/ssh 帧带 `persist` + 客户端生成、随标签规格保存的稳定
|
|
182
|
+
`persistName`——本地把 `-c` 包装层换成 `exec tmux -L dsh-tty -f
|
|
183
|
+
<conf> new-session -A -s dsh-<名>`(cwd 由 node-pty spawn 继承);SSH 则
|
|
184
|
+
远程 `exec tmux -L dsh-tty -f /dev/null new-session -A -s dsh-<名>` 开
|
|
185
|
+
pty channel。`-A` attach-or-create:宿主重启后重开标签按同名接回原
|
|
186
|
+
tmux 会话,正在跑的程序、pane 状态原样恢复;
|
|
187
|
+
- **恢复链路**:浏览器重连后查 `sessions`——持久标签 sid 已失效的,客户端
|
|
188
|
+
自动按原 persistName 重新 spawn(非持久标签维持丢弃语义);保活回收器
|
|
189
|
+
超时只杀 PTY(tmux 客户端),**不杀 tmux 会话**,回收后照样可接回;
|
|
190
|
+
同宿主内的重连(attach)对 tmux 会话**不回放宿主缓冲**——回放会把可见屏
|
|
191
|
+
先写进全新 xterm(幽灵滚动条),tmux 整屏重画再画一遍(重影)——改为
|
|
192
|
+
强制 `tmux refresh-client` 重画恰好一次;
|
|
193
|
+
持久标签规格同时写入 **localStorage**(sessionStorage 只对同一浏览器标签
|
|
194
|
+
可见,dsh 重启自动打开的新窗口原本读不到、恢复就断在这一环)——全新
|
|
195
|
+
窗口打开面板时按规格直接 respawn:tmux 会话存活则接回原现场,已消失
|
|
196
|
+
(远程重装/重装丢失)则开新 shell;规格只随「标签被主动关闭/退出」淘汰,
|
|
197
|
+
不做事前存活确认(确认依赖的留存状态一旦漂移会让恢复静默失效);
|
|
198
|
+
- **关闭语义**:kill 帧(标签 ✕ / 关面板)对 tmux 背书会话先
|
|
199
|
+
`tmux kill-session` 再杀客户端——真正结束,而不是 detach 留活口;
|
|
200
|
+
整个页面关闭时默认**留存**(保活期后可再恢复),配置
|
|
201
|
+
`endOnPageClose: true` 则改为保活期结束时连 tmux 会话一起结束;
|
|
202
|
+
- **shell 集成兼容**:tmux 会吞掉不认识的转义序列——钩子检测 `$TMUX` 把
|
|
203
|
+
OSC 133/7 包进 DCS passthrough 信封(payload 内 ESC 双写),tmux ≥3.3 +
|
|
204
|
+
`allow-passthrough on`(宿主自动写入桩 conf)时解包转发,宿主解析器看到的
|
|
205
|
+
仍是裸标记:`tty_expect` / OSC 7 cwd 跟随在持久标签内照常工作;
|
|
206
|
+
`tty_capture{last}` 另有一层修正——tmux 的 pane 重画是异步批量的,命令输出
|
|
207
|
+
会落在 D 标记之后逃出捕获窗口,故钩子在发 D 前先 `capture-pane` 把 pane
|
|
208
|
+
内容经 `OSC 133;T`(base64,最近 200 行)随流直送,宿主优先采用 T 快照
|
|
209
|
+
作为命令输出(超出 200 行的输出截断头部,与环形缓冲语义一致);
|
|
210
|
+
- **运行资产**:`<DSH_HOME|~/.dsh>/tty/` 下的稳定桩目录(tmux server 比宿主
|
|
211
|
+
进程活得久,不能用临时目录):`tmux.conf`(status off 防重绘污染捕获、
|
|
212
|
+
真色 overrides、`default-command` 指向内层启动器)与 `inner.sh`(按当前
|
|
213
|
+
配置 exec 内层 shell,zsh ZDOTDIR / bash --rcfile 桩照常注入);配置热改
|
|
214
|
+
对新开 pane 生效,`tmux.conf` 本身只在 tmux server 首启时读取;
|
|
215
|
+
- **降级**:本机/远程未安装 tmux 时,持久 spawn 自动落回普通会话,终端里
|
|
216
|
+
回一行灰字提示;不装任何东西也能正常用,只是无持久化。
|
|
217
|
+
|
|
166
218
|
## SSH 连接(方案 C)
|
|
167
219
|
|
|
168
220
|
0.2.0 起标签栏「+」变为一键菜单,除本地终端外还能开 **SSH 标签页**:宿主
|
|
@@ -225,28 +277,31 @@ subsystem,宿主半体 `src/sftp.ts`):
|
|
|
225
277
|
| `colorTerm` | `truecolor` | COLORTERM 值 |
|
|
226
278
|
| `cwd` | 宿主启动目录 | 兜底工作目录(客户端当前会话 cwd 优先) |
|
|
227
279
|
| `reconnectGraceSec` | 120 | 异常断开后会话保活秒数(0~3600):刷新页面/网络抖动后会话存活等待重连,超时由回收器结束;`0` = 旧行为,断开立即结束 |
|
|
228
|
-
| `sshHosts` | `[]` | SSH 连接簿(面板「+」菜单可选):条目 `{name, host, port=22, username, auth=agent\|key\|password, keyPath, passphrase, password}`;保存时整体替换、同名覆盖;`password` / `passphrase` 支持 `env:VAR`
|
|
280
|
+
| `sshHosts` | `[]` | SSH 连接簿(面板「+」菜单可选):条目 `{name, host, port=22, username, auth=agent\|key\|password, keyPath, passphrase, password, agentForward}`;保存时整体替换、同名覆盖;`password` / `passphrase` 支持 `env:VAR` 引用,避免明文入库;持久化开启时条目点击默认以 tmux 持久会话打开 |
|
|
229
281
|
| `hostKeys` | `[]` | SSH 主机指纹记录(TOFU,自动维护):条目 `{host, port, fingerprint}`;按 host:port 唯一,首次连接自动追加,指纹变更拒绝连接;设置卡片可删除重置 |
|
|
230
282
|
| `shellIntegration` | true | 注入 OSC 133/7 shell 集成(命令边界标记 + cwd 上报;`tty_capture{last}` 依赖它);zsh/bash 支持,其他 shell 自动跳过;出兼容问题时可关闭 |
|
|
231
283
|
| `tunnels` | `[]` | 端口转发隧道:条目 `{name, bookName, direction=local\|remote, localPort?, remoteHost?, remotePort?, localTargetHost?, localTargetPort?, enabled}`;`bookName` 引用连接簿条目提供主机与认证;卡片「端口转发」区块可视化维护 |
|
|
232
284
|
| `sftpStyle` | `dialog` | SFTP 文件浏览界面风格:`dialog` 单窗体(远程目录 + 上传/下载/拖拽)/ `dual` 双栏(左本机 / 右远程,行内 `⇨/⇦` 宿主服务端直传);重新打开 SFTP 生效 |
|
|
285
|
+
| `persistence` | `off` | 会话持久化:`off` 会话随宿主生死(默认);`tmux` 开启后**所有新开的标签默认由 tmux server 托管**、可跨宿主重启恢复(需本机/远程安装 tmux);SSH 对话框可对单次连接取消 |
|
|
286
|
+
| `endOnPageClose` | `false` | 页面(最后一个连接)断开且保活期结束时,是否连 tmux 持久会话一起结束。默认 `false` = 留存可恢复;`true` = 页面关了就不保活(保活期内刷新仍可无缝接回) |
|
|
233
287
|
|
|
234
288
|
## 帧协议(/api/dsh-tty/ws,JSON 文本帧;v3 = 单连接多会话 + 断线重连)
|
|
235
289
|
|
|
236
290
|
| 方向 | 帧 | 说明 |
|
|
237
291
|
| --- | --- | --- |
|
|
238
|
-
| C→S | `{t:'spawn', sid?, cols?, rows?, cwd?}` | 创建会话;sid 缺省由宿主生成,cwd
|
|
239
|
-
| C→S | `{t:'ssh', sid?, cols?, rows?, name? \| host, username,
|
|
292
|
+
| C→S | `{t:'spawn', sid?, cols?, rows?, cwd?, persist?, persistName?}` | 创建会话;sid 缺省由宿主生成,cwd 缺省用配置兜底;`persist` + 稳定 `persistName`(0.10.0)= tmux 持久会话(`dsh-<名>`,需 persistence=tmux) |
|
|
293
|
+
| C→S | `{t:'ssh', sid?, cols?, rows?, name? \| host, username, …, persist?, persistName?}` | 创建 SSH 会话(ssh2 原生);`name` 引用连接簿条目作基底,内联 `host/port/username/auth/keyPath/passphrase/password/agentForward` 可逐项覆盖;`persist` 语义同 spawn(远程 tmux 托管) |
|
|
240
294
|
| C→S | `{t:'input', sid?, d}` | 按键/粘贴数据 |
|
|
241
295
|
| C→S | `{t:'resize', sid?, cols, rows}` | 面板尺寸变化 |
|
|
296
|
+
| C→S | `{t:'refresh', sid?}` | 强制重画(0.10.1):宿主对 tmux 会话执行 `refresh-client`(客户端 reset 清残 scrollback 后请现场重画;非 tmux 会话 no-op) |
|
|
242
297
|
| C→S | `{t:'kill', sid?}` | 关闭会话(孤儿会话也允许跨连接 kill,防泄漏) |
|
|
243
298
|
| C→S | `{t:'sessions'}` | 列出全局会话快照(`attachable` 标记可重连者) |
|
|
244
299
|
| C→S | `{t:'attach', sid}` | 重连孤儿会话(保活窗口内):`ready(reattached:true)` 后紧跟一帧 `data` 回放输出缓冲 |
|
|
245
|
-
| S→C | `{t:'ready', sid, pid, kind, target?, reattached?}` | 会话就绪;`kind:'local'` 带 pid,`kind:'ssh'` 时 pid=null、target=user@host[:port];attach 复用此帧并带 `reattached:true` |
|
|
300
|
+
| S→C | `{t:'ready', sid, pid, kind, target?, persist?, reattached?}` | 会话就绪;`kind:'local'` 带 pid,`kind:'ssh'` 时 pid=null、target=user@host[:port];attach 复用此帧并带 `reattached:true`;`persist:true` 表示 tmux 持久会话(0.10.0) |
|
|
246
301
|
| S→C | `{t:'data', sid, d}` | 终端输出(utf8 文本,StringDecoder 兜跨帧多字节序列);**12ms 窗口/64KB 阈值合并成帧**(0.4.1),exit/kill 前强制冲刷保证帧序 |
|
|
247
302
|
| S→C | `{t:'exit', sid, code, signal}` | PTY 退出事实(恰好一次;attach 换连接后仍随当前连接送达) |
|
|
248
303
|
| S→C | `{t:'error', sid?, m}` | 错误 |
|
|
249
|
-
| S→C | `{t:'sessions', list}` | 会话快照(`{sid, kind, target, pid?, cwd, startedAt, lastOutputAt, attachable}
|
|
304
|
+
| S→C | `{t:'sessions', list, tmux?}` | 会话快照(`{sid, kind, target, pid?, cwd, startedAt, lastOutputAt, attachable, persist?}`);`tmux` = 专用 socket 上现存的持久会话名 + SSH 持久会话留存名(0.10.1,可观测字段) |
|
|
250
305
|
|
|
251
306
|
断线保活语义:客户端正常关面板会先逐个发 `kill` 再断开;因此「WS close
|
|
252
307
|
且仍有存活会话」判定为异常断开——会话转入孤儿状态(输出继续积累进环形
|
|
@@ -300,6 +355,7 @@ pnpm --filter @hyzyn/dsh-tty ssh-smoke # SSH 冒烟:内存 SSH server(ssh
|
|
|
300
355
|
`PROMPT_COMMAND`/钩子数组,集成可能失效——可关闭 `shellIntegration` 或
|
|
301
356
|
反馈补丁兼容。
|
|
302
357
|
- **端口转发边界**:本地监听固定 127.0.0.1(不暴露局域网);remote 方向服务端监听还受服务端 sshd `GatewayPorts` 限制;隧道的 SSH 连接与终端会话独立,均走 TOFU 钉扎与连接簿认证;隧道规格变更(端口/目标/启停)经「保存」热生效,热改连接簿凭证则在下次重连时生效。
|
|
358
|
+
- **会话持久化(tmux)边界**:持久标签由 tmux server(专用 socket `dsh-tty`)托管——宿主被硬杀 / 保活回收 / 浏览器丢失标签规格时,tmux 会话会**留存**(这正是恢复能力的前提),直到机器重启或手动 `tmux -L dsh-tty kill-server`;agent 命令粒度工具(capture{last}/expect)依赖 tmux ≥3.3 的 DCS `allow-passthrough`,更低版本持久化可用但该能力降级(SSH 远程会话不注入 shell 集成钩子,capture{last} 本就不可用,与持久化无关);恢复接回重画的是当前可见屏,断线前的滚动历史在 tmux 自己的 history buffer(copy-mode)里,不在外层 xterm 滚动区;持久标签的 `exit` 帧退出码是 tmux 客户端的(0),shell 退出码经 OSC 133;D 标记照常可用;`tmux.conf` 只在 tmux server 首启时读取(改配置后需 `tmux -L dsh-tty kill-server` 让下次 spawn 重建 server);`grace=0` 的「断开立即结束」对持久标签同样会 kill-session(tmux 会话不存活);持久 SSH 会话要求远程装有 tmux(未装自动降级普通会话,连接栏常驻「未持久化」标记),且远程 `~/.tmux.conf` 不影响专用 socket 的独立 conf(`-f /dev/null`);SSH 持久会话名随 settings 留存;**两个窗口同时接回同一持久会话**时共享同一个宿主 PTY(0.10.1,单客户端扇出,名额不翻倍),两侧行数以最近调整尺寸的窗口为准(尺寸不一致时较大一侧由 onResize 自愈重画)。
|
|
303
359
|
- **SFTP 边界**:文件权限 = 对应 SSH 账号的终端权限(无额外沙箱/chroot);下载经浏览器内存(超大文件建议终端 `scp`/`rsync`);agent 工具 `sftp_read` ≤1MB 且拒绝二进制、`sftp_write` 单次 ≤1MB(大内容走面板上传或终端);`sftp_*` 工具只收连接簿条目名,内联凭证仅供面板对话框使用。
|
|
304
360
|
- **SSH host key 为 TOFU 钉扎**:首次连接自动记录 sha256 指纹(trust on
|
|
305
361
|
first use),之后指纹一致放行、变更拒绝——不再是无条件放行的
|
|
@@ -337,6 +393,11 @@ pnpm --filter @hyzyn/dsh-tty ssh-smoke # SSH 冒烟:内存 SSH server(ssh
|
|
|
337
393
|
│ 残包 carry)→ 命令边界捕获(tty_capture{last} / tty_expect 早停)
|
|
338
394
|
│ 与 cwd 跟随(tty_list)
|
|
339
395
|
├─ 本地路径:ctx.get('subprocess').spawnTerminal({ argv: shell -c 包装层, cwd })
|
|
396
|
+
│ 持久标签(0.10.0):包装层换 `exec tmux -L dsh-tty -f <conf> new -A -s dsh-<名>`
|
|
397
|
+
│ (src/tmux.ts:探测/资产生成/spawn 计划/kill-session;稳定资产在
|
|
398
|
+
│ <DSH_HOME|~/.dsh>/tty/——tmux.conf + inner.sh + zsh/bash 桩;tmux 会吞
|
|
399
|
+
│ 不认识的序列,shell 集成钩子检测 $TMUX 把 OSC 133/7 包 DCS passthrough
|
|
400
|
+
│ 信封,tmux ≥3.3 解包转发,宿主解析器零改动)
|
|
340
401
|
├─ 辅助路由:/api/dsh-tty/ssh-config(~/.ssh/config 导入候选)、
|
|
341
402
|
│ /api/dsh-tty/env-vars(env 插件托管变量名)、/api/dsh-tty/known-hosts
|
|
342
403
|
│ (TOFU 指纹预填充,src/known-hosts.ts 解析含 hashed 条目)、
|
|
@@ -356,7 +417,10 @@ SSH 路径 (src/ssh.ts,方案 C)
|
|
|
356
417
|
password·passphrase 支持 env:VAR 取密;host key 经 HostKeyStore
|
|
357
418
|
TOFU 钉扎),开 shell channel 包装成与 PTY 同形状的 TermHandle
|
|
358
419
|
(pid=null,kind='ssh',target=user@host[:port]),
|
|
359
|
-
背压一并透传到 channel —— 之后与本地 PTY
|
|
420
|
+
背压一并透传到 channel —— 之后与本地 PTY 无差别调度;
|
|
421
|
+
persist 时先 `command -v tmux` 探测再 `exec tmux -L dsh-tty -f /dev/null
|
|
422
|
+
new -A -s dsh-<名>` 开 pty channel(远程 tmux 托管;无 tmux 降级普通
|
|
423
|
+
shell channel + 灰字提示;kill 经连接内 `tmux kill-session` 收尾)
|
|
360
424
|
```
|
|
361
425
|
|
|
362
426
|
M0 探针、集成测试(B1~B24 共 58 项断言)与真实实例冒烟(live / TUI)在
|
|
@@ -369,7 +433,10 @@ shells 候选路由、bash 3.2 shell 集成(DEBUG trap 兜底:capture{last}
|
|
|
369
433
|
exitCode、tty_expect 命令结束早停)、SFTP 文件传输(list/mkdir/upload/
|
|
370
434
|
download/remove 路由 + sftp_* 工具,test-sshd 内存 sshd 端到端)、SFTP 管理
|
|
371
435
|
闭环(agent sftp_mkdir/-rename/-remove/-tree:parents 补齐、tree 限深截断、
|
|
372
|
-
|
|
436
|
+
跨目录移动、非空删除拒绝与递归删除);会话持久化(B25/B26:persistence
|
|
437
|
+
门控、tmux 会话托管与 kill-session 收尾、无 tmux 降级提示、DCS passthrough
|
|
438
|
+
下 capture{last}、保活回收只杀 PTY 不杀 tmux 会话、同 persistName 接回现场
|
|
439
|
+
——本机无 tmux 时自动只跑降级路径)。SSH 路径由 `ssh-smoke`
|
|
373
440
|
(内存 SSH server × 真实 `spawnSsh`)验证:password 认证建链与 prompt、
|
|
374
441
|
命令往返、pty-req 初始尺寸与 resize(window-change)、terminate /
|
|
375
442
|
exit-status 全链路,以及 TOFU 指纹记录(S7)与指纹变更拒绝连接(S8);
|