Skip to content
dsh.fish
Bundle

dsh-tool-ssh

MobaXterm-style SSH/SFTP tool plugin for DeepSeek Harness: saved connection profiles, persistent multiplexed sessions, remote command execution, and file transfer to Linux hosts (e.g. Alibaba Cloud ECS).

Source
hoshinoick811
stars
4 stars
License
MIT
Updated
Updated 6 hours ago

Readme

# dsh-tool-ssh

DeepSeek Harness (DSH) 的 SSH/SFTP 工具插件,提供类似 MobaXterm 的远程主机接入能力:连接配置管理、持久会话复用、远程命令执行、文件上传/下载/读写,以及 **Web GUI 里的远程操作窗口**(文件浏览器 + 实时终端)。适用于接入 Linux 主机,例如阿里云 ECS。

## Web UI(图形界面)

插件加载后,会话标题栏顶部的标签行(与「轨迹」同一排)会出现 **「🖥️ SSH 远程控制」** 标签。点击后像浏览器切换标签页一样,主区域整体切换到 SSH 远程控制台:

- **左栏:文件管理**——远程文件浏览器:路径栏、↑ 上级、↻ 刷新、上传按钮;目录列表(单击进入目录、双击/按钮下载文件)。
- **右栏:多终端标签页**——每个标签一个独立 SSH PTY 终端(xterm.js,Canvas 渲染器),可直接输入 Linux 命令;顶部标签栏可 **「+ 新终端」** 添加多个终端,点 ✕ 关闭。
- **会话保持**:SSH 会话存活在宿主进程,切换会话视图(去对话/轨迹再回来)或切换终端标签时**连接不断、远端 shell 继续运行**(cwd/进程状态保留);回来时宿主先回放期间的全部输出再直播。只有点 ✕ 关闭标签或重启 GUI 才真正断开。
- **性能**:Canvas 渲染器 + 按键 30ms 批量发送 + 自适应按帧合并 + fit 前置(无重排抖动)。
- **拖拽分栏**——文件栏与终端之间的分隔条可左右拖动,自由调节两边宽度;顶部按钮可一键「📁 文件: 显示/隐藏」。
- 顶部下拉框选择已保存的连接配置(如 `aliyun`);新建终端使用当前选择的连接。
- **连接管理**:下拉框右侧提供 **↻ 刷新** 与 **🗑 删除所选**(删除时自动关闭连到该主机的终端,选中项自动落到剩余连接);添加/删除连接后列表**即时刷新**,无需切换页面——在对话里用 `ssh_connections action=add/remove` 的变更也会在数秒内自动同步到下拉框。

实现:host 侧在 `webServer` 注册 `/plugins/dsh-tool-ssh/*` 端点(loopback + Origin 围栏);client 侧是 `client.js` 模块,注册为 `conversation.view` 会话视图(与 trajectory 同 slot);终端输出经 SSE 流式推送,宿主为每个会话保留有界回放缓冲;`xterm.js`/`addon-canvas.js`/`xterm.css` 由插件自身的 `/assets` 路由提供。

> **限宽列处理**:dsh web 的会话内容区默认被 `--dsh-chat-content-width: 748px` 限宽并居中。插件在浏览器端注入页面级 `<style>`,用 `[data-phase]:has([data-dsh-ssh-view])` 作用域把该变量与 `max-width` 覆盖为全宽——**仅在 SSH 视图激活时生效**,切回对话/轨迹即自动恢复,不影响聊天观感;样式在插件卸载时移除。

## 工具列表

| 工具 | 作用 |
|---|---|
| `ssh_connections` | 管理已保存的连接配置(list/add/update/remove),存在 `$DSH_HOME/dsh-tool-ssh/connections.json` |
| `ssh_connect` | 打开持久 SSH 会话(用已保存的配置,或内联 host/user/密码/密钥) |
| `ssh_exec` | 在远程主机执行命令,返回 stdout/stderr/退出码;无会话时按已存配置自动连接 |
| `ssh_read` | 通过 SFTP 读取远程文本文件 |
| `ssh_write` | 通过 SFTP 写入远程文本文件 |
| `ssh_list` | 列出远程目录(类型/权限/大小/修改时间) |
| `ssh_upload` | 本地上传 → 远程(SFTP fastPut) |
| `ssh_download` | 远程下载 → 本地(SFTP fastGet) |
| `ssh_disconnect` | 关闭会话 |
| `ssh_sessions` | 列出当前打开的会话 |

## 工作机制

- 会话是**持久且复用**的:一次 `ssh_connect` 后,后续 `ssh_exec` / SFTP 工具共用同一条连接(多路复用),类似 MobaXterm 的会话标签页。
- 其他工具传 `connection` 时,可以是已保存的配置名,也可以是 `ssh_connect` 指定的 `sessionId`;如果对应会话未打开但存在同名配置,会自动连接。
- 配置/密码/密钥以 JSON 明文存放在 `$DSH_HOME/dsh-tool-ssh/connections.json`(默认),**请自行保证本机安全**;推荐使用密钥认证。

## 安装(接入 web profile)

```powershell
# 方式一:从 GitHub 安装(发布后)
dsh plugin --profile web add git+https://github.com/hoshinoick811/dsh-tool-ssh.git

# 方式二:本地开发(从插件目录的上级执行)
dsh plugin --profile web add file:F:/new project/dsh-tool-ssh

# 装完重启 web profile(dsh web / 重启 GUI),工具即出现在模型目录
```

安装后 `dsh plugin` 会自动把声明了 `dsh.bundle.patch` 的依赖加入 profile 的
`dsh.profile.bundles` 层;插件行通过包内 `cordis.patch.yml` 的 `insert` 挂载到 profile 根组合,工具全局注册。

## 使用示例(阿里云 ECS)

```
1. ssh_connections action=add name=aliyun host=192.0.2.1 username=root privateKeyPath=C:\keys\aliyun.pem
2. ssh_exec connection=aliyun command="systemctl status nginx"
3. ssh_read connection=aliyun remotePath=/etc/nginx/nginx.conf
4. ssh_write connection=aliyun remotePath=/etc/nginx/conf.d/app.conf content="server { listen 80; ... }"
5. ssh_upload connection=aliyun localPath=./dist/index.html remotePath=/var/www/app/index.html
6. ssh_download connection=aliyun remotePath=/var/log/nginx/error.log
7. ssh_disconnect connection=aliyun
```

## 开发

- `lib/ssh-core.js` — 会话管理器(ssh2 封装),可独立于 DSH 测试。
- `test/smoke.mjs` — 针对公开测试服务器 `test.rebex.net`(demo/password,端口 2222)的核心逻辑冒烟测试:

```powershell
cd dsh-tool-ssh
npm install
node test/smoke.mjs
```

## 安全说明

- 密码与私钥内容以明文存于本机配置文件;密钥文件建议设置仅当前用户可读。
- 插件运行在 DSH 宿主进程内,不受 agent 沙箱约束 —— 连接的主机与执行的命令请务必谨慎。
- 远程主机需放行 22 端口(阿里云安全组),建议使用非 root 用户 + sudo。

Install

dsh plugin --profile web add github:hoshinoick811/dsh-tool-ssh

Profile: web

  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source