@zhangfengshun/dsh-remote-ssh 2.0.8 → 2.0.9

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.
Files changed (2) hide show
  1. package/README.md +31 -161
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,192 +1,62 @@
1
1
  # @zhangfengshun/dsh-remote-ssh
2
2
 
3
- 类 **VSCode Remote-SSH** 的 **DeepSeek Harness(DSH)** Web 插件:通过 SSH 连接远程超算 / 服务器,在 DSH 中完成远程工作区、远程文件浏览 / 编辑、集成远程终端,并让模型可以直接读写远程文件、执行远程命令。
3
+ 类 **VSCode Remote-SSH** 的 **DSH** 插件:通过 SSH 连接远程超算 / 服务器,在 DSH 内置「文件」「终端」页签中直接操作远程文件和终端。
4
4
 
5
- 界面与工具描述均支持**中英文双语**,跟随 DSH 设置中的语言自动切换。
6
-
7
- ## 功能特性
5
+ ## 功能
8
6
 
9
7
  | 能力 | 说明 |
10
8
  | --- | --- |
11
- | 🔌 远程连接 | SSH 连接超算 / 服务器,密钥认证(推荐)或密码认证(需本机 `sshpass`),内置「测试连接」;支持 `ProxyJump` 跳板机 |
12
- | 连接复用 | 持久 SSH 会话池,文件操作复用同一条已认证连接,不再每次握手(首次后近乎瞬时) |
13
- | 📥 配置导入 | 一键从 `~/.ssh/config`(递归 `Include`)发现主机并批量导入连接配置 |
14
- | 📂 远程文件 | 内置「文件」页签通过 fs.* 拦截**直接 SSH 读写远程文件**,无需同步——打开即读远程,保存即写远程 |
15
- | 💻 远程终端 | 内置「终端」页签自动通过 shell wrapper 检测远程工作区,打开 SSH 交互式终端(仅密钥认证) |
16
- | 🌐 远程工作区 | 选择远程目录创建**原生工作区**(本地镜像目录 + 原生注册),一键打开进入远程环境 |
17
- | 🤖 模型工具 | 12 个 `remote_ssh_*` 工具,模型可读写远程文件、执行远程命令、内容搜索、文件名查找、目录/删除/移动;在远程工作区会话中免填连接参数 |
18
- | 🌍 国际化 | 界面文案 + 工具描述中英双语,通过 `ctx.locale` 跟随 DSH 语言设置自动切换 |
9
+ | 🔌 SSH 连接 | 密钥 / 密码认证,ProxyJump 跳板机,`~/.ssh/config` 一键导入 |
10
+ | 📂 远程文件 | 内置「文件」页签直接 SSH 读写远程文件,无需同步 |
11
+ | 💻 远程终端 | 内置「终端」页签自动检测远程工作区,SSH 交互式终端 |
12
+ | 🌐 远程工作区 | 选择远程目录创建原生工作区,一键进入远程环境 |
13
+ | 🤖 模型工具 | 12 `remote_ssh_*` 工具,会话感知免填连接参数 |
14
+ | 🌍 双语 | 中英文界面 + 工具描述,跟随 DSH 语言自动切换 |
19
15
 
20
16
  ## 安装
21
17
 
22
- ### 本地 / 开发安装
23
-
24
18
  ```bash
25
- dsh plugin --profile <name> add /absolute/path/to/dsh-remote-ssh
19
+ dsh plugin --profile <name> add @zhangfengshun/dsh-remote-ssh@2.0.8
26
20
  ```
27
21
 
28
- ### 发布后安装
29
-
30
- ```bash
31
- dsh plugin --profile <name> add @zhangfengshun/dsh-remote-ssh@2.0.7
32
- ```
33
-
34
- > ⚠️ 安装后需**重启 DSH** 才生效;后续仅修改 Client 半边时刷新浏览器即可。
35
- >
36
- > ⚠️ **安装顺序**:本插件会自动覆盖 `dsh-better-sidebar` 的 `shell` 配置。为确保 patch 生效(config 覆盖在 insert 之后应用),`@zhangfengshun/dsh-remote-ssh` 必须在 bundles 列表中排在 `dsh-better-sidebar` **之后**。如果先安装了 `@zhangfengshun/dsh-remote-ssh`,再安装 `dsh-better-sidebar`,需手动调整 `profile/package.json` 中 `dsh.profile.bundles` 的顺序,把 `@zhangfengshun/dsh-remote-ssh` 移到最后。
37
-
38
- ## 快速开始
39
-
40
- 1. 安装插件并重启 DSH(安装时自动配置 better-sidebar 的 shell 指向 wrapper 脚本)。
41
- 2. 打开 **设置 → 🖥️ 远程连接**,添加一条连接(主机 / 端口 / 用户名 / 密钥或密码),点「测试连接」验证。
42
- 3. 需要把远程目录当作工作区时:走 DSH 原生「添加工作区」流程,在弹窗中选择「**选择远程目录…**」→ 选择连接 → 浏览并选择远程目录。
43
- 4. 创建后内置「文件」页签**直接显示远程文件**——打开文件即读远程,保存即写远程,无需同步。
44
- 5. 在远程工作区中打开内置「终端」页签 → 自动 SSH 到远程主机(仅密钥认证)。
45
-
46
- ## 使用指南
47
-
48
- ### 1. 添加远程连接
49
-
50
- 设置 → 🖥️ 远程连接,填写:
51
-
52
- | 字段 | 说明 |
53
- | --- | --- |
54
- | 名称 | 自定义显示名 |
55
- | 主机 | SSH 主机名或 IP(如 `login.example.com`) |
56
- | 端口 | SSH 端口,默认 `22` |
57
- | 用户名 | 登录用户 |
58
- | 认证方式 | `密钥`(推荐)或 `密码` |
59
- | 密钥路径 / 密码 | 私钥路径(如 `~/.ssh/id_rsa`)或登录密码 |
60
- | 远程根目录 | 远程默认目录,默认 `~` |
61
-
62
- 连接配置持久化在 DSH 设置命名空间 `dsh-remote-ssh` 中(密码字段 `role('secret')` 脱敏)。
63
-
64
- ### 2. 远程文件(内置「文件」页签)
65
-
66
- **直接 SSH 读写,无需同步**:
67
-
68
- - 在远程工作区中打开内置「文件」页签 → 直接显示远程文件树;
69
- - 点击文件 → 直接通过 SSH 读取远程文件内容;
70
- - 编辑保存 → 直接通过 SSH 写回远程文件;
71
- - 全程透明:客户端看到的是本地镜像路径,Host 拦截器自动转换为远程路径并通过 SSH 执行。
72
-
73
- **技术原理**:插件注册了 4 个 exact 路由(`/sidebar/api/fs.tree`、`fs.read`、`fs.write`、`fs.search`),在 better-sidebar 的 prefix 路由之前拦截。当请求路径对应的会话 cwd 含 `.remote-ssh.json` 时走 SSH,否则走本地 fs(行为与 better-sidebar 原始实现一致)。
22
+ > 安装后需**重启 DSH**。`@zhangfengshun/dsh-remote-ssh` 必须在 bundles 列表中排在 `dsh-better-sidebar` **之后**。
74
23
 
75
- ### 3. 远程终端(内置「终端」页签)
24
+ ## 使用
76
25
 
77
- 通过 shell wrapper 实现:终端启动时自动检测当前工作目录下的 `.remote-ssh.json`,若存在且含密钥路径自动 `ssh -tt` 连接远程主机;否则启动本地 shell。
26
+ 1. **设置 🖥️ 远程连接**添加连接(主机/端口/用户/密钥)→ 点「测试连接」验证
27
+ 2. **添加工作区** → 选「选择远程目录…」→ 选连接 → 浏览并选择远程目录
28
+ 3. 打开内置「文件」页签 → 直接显示远程文件,编辑保存直接写回远程
29
+ 4. 打开内置「终端」页签 → 自动 SSH 到远程主机(仅密钥认证)
78
30
 
79
- **自动配置**:安装插件后,`cordis.patch.yml` 自动把 better-sidebar 的 `shell` 配置覆盖为 wrapper 脚本路径(用 `!!js` 动态计算,适配不同平台和用户主目录)。**无需手动编辑任何配置文件。**
80
-
81
- 工作流程:
82
- 1. 插件启动时自动在 `~/.dsh/remote-ssh/` 下生成 wrapper 脚本:
83
- - `dsh-remote-shell.js`(核心逻辑:检测 `.remote-ssh.json` → `ssh -tt`;否则本地 shell)
84
- - Windows: `dsh-remote-shell.cmd`(薄壳调用 .js)
85
- - POSIX: `dsh-remote-shell`(薄壳调用 .js)
86
- 2. 安装时自动覆盖 better-sidebar 的 `shell` config 指向 wrapper 脚本。
87
- 3. 重启 DSH 后,在远程工作区中打开终端 → 自动 SSH 到远程主机;在本地工作区中打开终端 → 照常启动本地 shell。
88
-
89
- > ⚠️ 终端透明接入仅支持**密钥认证**(密码无法安全传入 wrapper 脚本)。密码认证的连接仍可使用模型工具和远程文件操作。
90
- > 若需覆盖自动配置,在 profile 的 `cordis.patch.yml` 中加一条 `id: better-sidebar` 的 `config.shell` 即可(profile patch 优先于 bundle patch)。
91
-
92
- ### 4. 远程工作区(🌐)
93
-
94
- 1. 打开 DSH 原生「添加工作区」流程;
95
- 2. 选择「**选择远程目录…**」→ 选择连接 → 浏览并选择远程目录;
96
- 3. 插件在本地生成镜像目录 `~/.dsh/remote-workspaces/<id>`,写入 `.remote-ssh.json`(连接信息,供 shell wrapper 和 fs.* 拦截器读取),并注册进原生工作区列表(标题 `🌐 <名称>`);
97
- 4. 从工作区创建会话后,会话工作目录即该镜像目录,模型工具自动感知对应的远程连接与目录。
98
-
99
- ### 5. 模型工具(🤖)
100
-
101
- 插件向模型注册 12 个工具,模型可直接操作远程环境:
31
+ ## 模型工具
102
32
 
103
33
  | 工具 | 用途 |
104
34
  | --- | --- |
105
- | `remote_ssh_profiles` | 列出已保存连接配置;返回当前会话的远程工作区上下文 |
106
- | `remote_ssh_exec` | 在远程主机执行命令(返回 stdout / stderr / exitCode) |
35
+ | `remote_ssh_profiles` | 列出连接配置 + 当前会话远程工作区上下文 |
36
+ | `remote_ssh_exec` | 执行远程命令 |
107
37
  | `remote_ssh_ls` | 列举远程目录 |
108
- | `remote_ssh_cat` | 读取远程文本文件(base64 传输,二进制安全) |
109
- | `remote_ssh_write` | 写入远程文件(覆盖写入) |
110
- | `remote_ssh_sync` | 远端文件同步到本地镜像目录(tar 流式管道) |
111
- | `remote_ssh_push` | 本地镜像目录推送回远端(tar 流式管道) |
112
- | `remote_ssh_grep` | 递归搜索远程文件内容(grep -rnIE,支持 include/ignoreCase) |
113
- | `remote_ssh_glob` | 按通配符查找远程文件(find -name,递归) |
114
- | `remote_ssh_mkdir` | 创建远程目录(mkdir -p) |
115
- | `remote_ssh_delete` | 删除远程文件或目录(rm -rf,⚠️ 不可恢复) |
116
- | `remote_ssh_move` | 移动/重命名远程文件或目录(mv) |
117
-
118
- **会话感知**:当会话是从远程工作区创建时,模型调用这些工具可**不填** `profileId` / `host` / `user` 等连接参数,自动复用该工作区的连接,相对路径基于该工作区远程目录解析。
119
-
120
- ## 目录结构
121
-
122
- ```
123
- dsh-remote-ssh/
124
- ├── package.json # npm 元数据 + dsh.bundle / dsh.client 声明
125
- ├── cordis.patch.yml # bundle 挂载补丁(install 时加入 profile bundle 栈)
126
- ├── lib/
127
- │ ├── index.js # Host 半边(SSH + settings + 12 个工具 + HTTP API + fs.* 拦截)
128
- │ └── client.js # Client 半边(better-sidebar 页签 + 设置小节 + i18n)
129
- ├── LICENSE
130
- ├── CHANGELOG.md
131
- └── README.md
132
- ```
133
-
134
- ## 架构
38
+ | `remote_ssh_cat` | 读取远程文件 |
39
+ | `remote_ssh_write` | 写入远程文件 |
40
+ | `remote_ssh_grep` | 搜索远程文件内容 |
41
+ | `remote_ssh_glob` | 查找远程文件 |
42
+ | `remote_ssh_mkdir` | 创建远程目录 |
43
+ | `remote_ssh_delete` | 删除远程文件/目录 |
44
+ | `remote_ssh_move` | 移动/重命名 |
45
+ | `remote_ssh_sync` | 远端同步到本地镜像 |
46
+ | `remote_ssh_push` | 本地镜像推送回远端 |
135
47
 
136
- ```
137
- 浏览器 (Client 半边) Node 进程 (Host 半边)
138
- ┌───────────────────────────────┐ fetch ┌──────────────────────────────────┐
139
- │ ctx.betterSidebar.registerTab │ ──────▶ │ ctx.webServer │
140
- │ · remssh:editor (隐藏) │ ◀────── │ · /sidebar/api/fs.* (exact) │
141
- │ ctx.slots: settings.section │ JSON │ 拦截 better-sidebar 的 fs API │
142
- │ · 连接配置 + 工作区管理 │ │ 远程→SSH / 本地→本地 fs │
143
- │ ctx.slots: directoryFlow │ │ · /remote-ssh/api/* (prefix) │
144
- │ · 本地 / 远程目录两选弹窗 │ │ listDir/readFile/writeFile/… │
145
- └───────────────────────────────┘ │ · settings + shell wrapper 生成 │
146
- │ ctx.tools:12 个 remote_ssh_* │
147
- └───────────────┬──────────────────┘
148
- │ SSH
149
- ┌───────────────┴──────────────┐
150
- │ ~/.dsh/remote-ssh/ │
151
- │ dsh-remote-shell.js │
152
- │ dsh-remote-shell[.cmd] │ ← better-sidebar shell 指向此文件
153
- └─────────────────────────────┘
154
- 远程超算 / 服务器
155
- ```
48
+ 远程工作区会话中调用工具可免填 `profileId` 等连接参数。
156
49
 
157
- 关键设计:
50
+ ## 原理
158
51
 
159
- - **fs.* 拦截(核心)**:注册 4 个 exact 路由(`/sidebar/api/fs.tree` 等),在 `match()` 中 exact 优先于 prefix 检查,从而拦截 better-sidebar 的 fs API。当会话 cwd 含 `.remote-ssh.json` 时走 SSH,否则走本地 fs
160
- - **路径透明映射**:客户端看到的是本地镜像路径,Host 拦截器自动转换为远程路径,通过 SSH 执行后返回结果。对客户端完全透明。
161
- - **免 shell 引号转义**:远程命令通过 `subprocess.spawn({ argv })` 以参数数组调起 `ssh.exe`,避免引号 / 空格问题。
162
- - **二进制安全读文件**:远程 `base64 -w0` 输出,Host 用 `Buffer` 解码为 UTF-8。
163
- - **写文件走 stdin**:远程 `cat > <file>`,内容经子进程 stdin 传入。
164
- - **文件列举**:`find -printf '%Y\t%f\t%s\n'`(`%Y` 跟随软链接取目标类型,适配超算家目录软链接)。
165
- - **Shell wrapper**:插件启动时生成跨平台 wrapper 脚本(Node.js + 薄壳),检测工作区 `.remote-ssh.json` 自动 SSH,使内置「终端」页签透明接入远程。
166
- - **国际化**:Client 接入 `ctx.locale`,注册 `zh` / `en` 词典,界面与工具描述跟随 DSH 语言自动切换。
52
+ 插件注册 4 个 exact 路由(`/sidebar/api/fs.tree`、`fs.read`、`fs.write`、`fs.search`),在 better-sidebar 的 prefix 路由之前拦截。会话 cwd 含 `.remote-ssh.json` 时走 SSH,否则走本地 fs。客户端看到的是本地镜像路径,Host 自动转换为远程路径——对客户端完全透明。
167
53
 
168
- ## 已知限制
169
-
170
- 1. **终端透明接入仅限密钥认证**:shell wrapper 通过 `.remote-ssh.json` 读取密钥路径,密码认证无法安全传入。密码认证的连接仍可使用模型工具和远程文件操作。
171
- 2. **文件操作依赖 GNU 工具**(`find -printf`、`base64 -w0`):目标为 Linux 超算时通用。
172
- 3. **密码认证需本机 `sshpass`**(Windows 默认没有);密钥认证无此依赖。
173
- 4. **fs.search 远程搜索**返回的路径为相对于远程根目录的相对路径,客户端拼接为本地镜像路径格式显示。
174
-
175
- ## 路线图
176
-
177
- - [x] 从 `~/.ssh/config` 自动导入连接
178
- - [x] ProxyJump / 跳板机、SSH config 复用
179
- - [x] 远程文件合并到内置「文件」页签(fs.* 拦截 + 直接 SSH 读写,无需同步)
180
- - [x] 远程终端合并到内置「终端」页签(shell wrapper 透明 SSH)
181
- - [x] 远程工作区目录选择器(本地/远程两选,不依赖 browse capability)
182
- - [ ] 密码凭据走 `credentials` 服务(避免明文进 argv)
54
+ Shell wrapper(`~/.dsh/remote-ssh/dsh-remote-shell[.cmd]`)检测工作区 `.remote-ssh.json`,自动 `ssh -tt` 连接远程,使内置「终端」页签透明接入。
183
55
 
184
56
  ## 许可证
185
57
 
186
58
  [MIT](./LICENSE)
187
59
 
188
- ---
189
-
190
60
  ## ❤️ 七夕快乐
191
61
 
192
62
  本项目是送给 **zhangyi** 的七夕礼物。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhangfengshun/dsh-remote-ssh",
3
- "version": "2.0.8",
3
+ "version": "2.0.9",
4
4
  "description": "DSH web plugin: VSCode Remote-SSH-like remote development (SSH to supercomputers/servers, remote workspace, file explorer, integrated terminal), integrated with dsh-better-sidebar and DSH settings.",
5
5
  "keywords": [
6
6
  "dsh",