dsh-ssh-workbench 1.7.0 → 1.7.8
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/CHANGELOG.md +84 -0
- package/README.md +13 -10
- package/docs/architecture.md +8 -8
- package/docs/execution-model.md +1 -1
- package/docs/quickstart.md +8 -5
- package/lib/client.js +1078 -61
- package/lib/core/background.js +18 -4
- package/lib/core/managed-context.js +12 -1
- package/lib/core/prefs.js +35 -2
- package/lib/core/remote-exec-tool.js +54 -7
- package/lib/core/remote-file-tools.js +91 -8
- package/lib/core/ssh.js +22 -0
- package/lib/index.js +10 -5
- package/lib/routes.js +17 -3
- package/package.json +17 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,90 @@
|
|
|
4
4
|
|
|
5
5
|
> 产品对外名称:**SSH Workbench / 远程工作台**(v1.6.4 起统一)。包名 `dsh-ssh-workbench`、数据目录 `~/.dsh/ssh-workbench`。历史条目中的旧标识已统一为当前名称,便于检索。
|
|
6
6
|
|
|
7
|
+
## [1.7.8] - 2026-11-14
|
|
8
|
+
|
|
9
|
+
### 变更(远程执行能力补齐)
|
|
10
|
+
|
|
11
|
+
- `remote_exec` 的每个 task 支持 `run_in_background`:批量任务里可以混跑前台命令和后台进程,后台任务立即返回远端 pid 与日志,其余 task 继续并发;`timeoutMs` 只约束启动,不再需要为长任务单独切到 `remote_bash` / `remote_pwsh`。
|
|
12
|
+
- 远程写入原子化(POSIX):`remote_write` / `remote_edit` 先写同目录临时文件,再 `rename` 覆盖目标,并尽量保留原权限位;连接中断或写入失败时原文件保持不变。Windows 目标保持直接写入;软链目标写穿链接而不是替换链接。
|
|
13
|
+
- POSIX 后台日志从 `/tmp` 移到 `~/.dsh/ssh-workbench/logs`(`DSH_SSH_WORKBENCH_LOG_DIR` 可覆盖),避免系统 tmp 清理;该目录不可写时自动回退 `/tmp`。
|
|
14
|
+
|
|
15
|
+
### 文档
|
|
16
|
+
|
|
17
|
+
- README / quickstart / architecture 同步上述行为;明确 composer 下方 pill 只反映工具调用,后台进程启动后 pill 消失不代表远端进程结束。
|
|
18
|
+
|
|
19
|
+
## [1.7.7] - 2026-11-14
|
|
20
|
+
|
|
21
|
+
### 新增(工作区文件补齐原生能力)
|
|
22
|
+
|
|
23
|
+
- 页头补回搜索:走 Host 的 `workspaceFiles/search`(ripgrep),按文件名或路径匹配,输入即搜、结果按层级缩进、右侧显示所在目录,支持清空与 Esc 关闭;结果过多或搜索未完成时给出提示。默认排除 `node_modules`、`dist` 等目录,与官方一致。
|
|
24
|
+
- 「在应用中打开」由单个按钮升级为官方同款拆分按钮:主按钮用默认应用打开当前目录并显示该应用图标与名称,右侧箭头列出 Host 上可用的全部应用(来自 `session.workspacePathApplications`,含 Finder/VS Code/GitHub Desktop/终端等),选哪个用哪个。没有可用应用列表时回退为单按钮,按系统默认应用打开。
|
|
25
|
+
- 两处都沿用 `remote.workspaceFiles` / `remote.session` 命名空间,只读取 DSH 已提供的宿主能力,不新增后端接口。
|
|
26
|
+
|
|
27
|
+
## [1.7.6] - 2026-11-14
|
|
28
|
+
|
|
29
|
+
### 变更(设置页改为即时生效)
|
|
30
|
+
|
|
31
|
+
- 插件管理页去掉「保存」按钮:每个开关拨动后立即提交该字段并回读生效值。旧 Host 不支持新字段时仍提示重启,而不是谎报成功。
|
|
32
|
+
- 三个开关保持一致的三态偏好语义(设置页覆盖优先,未设置回落到 `cordis.patch.yml`)。
|
|
33
|
+
|
|
34
|
+
### 变更(层级模式按本地/远程分工)
|
|
35
|
+
|
|
36
|
+
- 「工作区文件」层级页是**本机**目录浏览,因此隐藏只对远程有意义的「上传 / 新建文件夹 / 传输记录」,也不再显示行菜单里的「下载 / 复制文件」——这些仍保留在远程工作台的 SFTP 面板。
|
|
37
|
+
- 该页补回 DSH 原生的「在应用中打开」:页头按钮打开当前目录,行菜单对文件/目录用系统默认应用打开(走 Host 的 `session.openWorkspacePath`,因此只对 Host 本地路径生效)。远程 SFTP 页面不显示该入口。
|
|
38
|
+
|
|
39
|
+
## [1.7.5] - 2026-11-14
|
|
40
|
+
|
|
41
|
+
### 修复(层级模式对齐官方观感)
|
|
42
|
+
|
|
43
|
+
- 指南页(开始页)入口改回 DSH 官方的 `workspace` 条目:沿用官方 id、`workspace.files` 命令、`order: 10` 与官方图标,位置回到第一格而不是掉到列表末尾。
|
|
44
|
+
- 页签图标改用官方 `FileTypeIcon` 的 folder 图形(16px),与 DSH 自己的「工作区文件」页签一致,不再使用插件自绘图标。
|
|
45
|
+
- 页签标题与指南文案仍为「工作区文件 / Workspace files」,与原生页同名。
|
|
46
|
+
|
|
47
|
+
## [1.7.2] - 2026-11-13
|
|
48
|
+
|
|
49
|
+
### 新增(系统文件浏览层级模式)
|
|
50
|
+
|
|
51
|
+
- 插件管理页新增「系统文件浏览使用层级模式」开关,默认关闭。开启后,右侧栏的「工作区文件」页由插件接管,改为带面包屑、后退/上级/根目录导航的层级浏览器;关闭后恢复 DSH 原生文件页。
|
|
52
|
+
- 接管页只浏览当前会话目录:根目录固定为会话 `cwd`,输入路径或点击上级都不能越界;文件通过 DSH 资源协议 `dsh-resource://file/session/...` 交给官方预览打开,Markdown/代码/图片/PDF 等仍享受官方预览能力。
|
|
53
|
+
- 该开关与 `remoteFileWrite` 一样支持三态偏好:设置页覆盖优先,未设置时回落到 `systemFileHierarchy` 配置(默认 `false`)。
|
|
54
|
+
- `POST /dsh-ssh-workbench/prefs` 增加 `systemFileHierarchy` 字段;`GET /state` 的 `config.systemFileHierarchy` 返回实际生效值。
|
|
55
|
+
|
|
56
|
+
### 修复
|
|
57
|
+
|
|
58
|
+
- 层级浏览器在接管模式下隐藏资源选择器,避免从「工作区文件」页切换到其他本机/远程资源而绕过会话目录边界。
|
|
59
|
+
|
|
60
|
+
## [1.7.1] - 2026-11-13
|
|
61
|
+
|
|
62
|
+
### 新增(右键菜单)
|
|
63
|
+
|
|
64
|
+
- 远程/本地文件行复用 DSH 官方的 `contextMenu` 服务:右键、`Shift+F10` 与行尾省略号按钮打开同一套菜单,不再使用插件私有的 `primitives.Menu` 弹层。菜单项为打开、下载、复制文件、复制路径、重命名、删除;删除标红并单独分组。
|
|
65
|
+
- 菜单动作在打开时按当前行解析,标签跟随界面语言;单个动作失败会写回面板错误行,不会静默失败。
|
|
66
|
+
- 官方菜单服务不可用时(例如宿主版本较旧)自动回退到原有省略号菜单,功能不缺失。
|
|
67
|
+
|
|
68
|
+
### 新增
|
|
69
|
+
|
|
70
|
+
- 插件管理页新增「允许远程写入」开关:`remote_write` / `remote_edit` 不必再改配置文件,直接在「插件 → 远程工作台」里打开或关闭。开关存在本地偏好(`~/.dsh/ssh-workbench/prefs.json`),未设置时回落到 `remoteFileWrite` 配置,因此既可以用 UI 临时启用,也可以用配置文件做默认值。
|
|
71
|
+
- `GET /state` 的 `config.remoteFileWrite` 现在返回**实际生效**的值(偏好优先、配置兜底),设置页、模型上下文与工具拒绝逻辑共用同一判定。
|
|
72
|
+
- 写开关变化会立即生效:工具执行时按调用解析,模型上下文每轮重新读取,不需要重启 DSH。
|
|
73
|
+
- 设置页在保存后会回读实际生效的值:如果当前运行的 DSH 还是旧版本、后端不接受这个开关,界面会提示「重启 DSH 后生效」,而不是谎报保存成功。
|
|
74
|
+
|
|
75
|
+
### 新增(文件预览)
|
|
76
|
+
|
|
77
|
+
- CSV / TSV 直接在预览页签里渲染成表格:逗号/制表符分隔、支持引号包裹与转义、字段内换行、CRLF;可在「表格 / 源码」之间切换。大表按 500 行、40 列截断并分别提示是行还是列被截断。
|
|
78
|
+
- SVG 按图片渲染,同时保留「源码」视图;其余矢量/位图格式行为不变。
|
|
79
|
+
|
|
80
|
+
### 修复
|
|
81
|
+
|
|
82
|
+
- 文件预览不再静默截断:超过读取上限时,头部显示「已截断」徽标(悬停给出说明),底部行数改用「前 N 行」。之前 1 MB 以上的日志只显示开头部分,但界面看不出任何区别。
|
|
83
|
+
- 图片超过预览上限时不再渲染残缺图片,改为明确提示「图片超过预览上限,无法完整显示;请下载后查看」,底部也不再显示无意义的行数。
|
|
84
|
+
- 被读取上限截断的表格,底部从「N 行 · M 列」改用「前 N 行 · M 列」,与文本类预览口径一致。
|
|
85
|
+
|
|
86
|
+
### 变更
|
|
87
|
+
|
|
88
|
+
- 写工具与上下文里「写入已关闭」的提示不再指向裸配置项,改为提示在插件设置里打开开关。
|
|
89
|
+
- `POST /dsh-ssh-workbench/prefs` 现在同时接受 `sidebar` 与 `remoteFileWrite`,返回体带上生效后的 `config`;只传 `sidebar` 仍然兼容。
|
|
90
|
+
|
|
7
91
|
## [1.7.0] - 2026-11-13
|
|
8
92
|
|
|
9
93
|
以 1.6.4 为基线的一个中版本:远程执行改为「每次调用显式带目标」,并补齐远程文件工具、多资源并行与执行指示。
|
package/README.md
CHANGED
|
@@ -23,15 +23,16 @@ DeepSeek Harness 的**远程工作台**:SSH 终端、本地与远程文件、@
|
|
|
23
23
|
| Windows 宿主 | Windows 上的 DSH 没有原生 `bash`(DSH 按平台禁用):插件在两种宿主上都注册 `remote_bash` / `remote_pwsh` / `remote_exec`,所以 Windows 宿主也能操作 POSIX 目标;原生 `pwsh` 仍只作用于本机 |
|
|
24
24
|
| Windows 目标 | Windows 目标经插件自有的 `remote_pwsh` 执行:命令包成 UTF-16LE 的 `-EncodedCommand` 脚本(避免引号转义),强制 UTF-8 输出并回传真实退出码;PowerShell 危险命令另有黑名单 |
|
|
25
25
|
| 方言探测 | 目标实际是 POSIX 还是 Windows 由连接后的 `uname -s` / `cmd /c ver` 探测并写入 `facts.dialect`,不依赖手工填写的 `platform`;探测结果用于选择 `remote_bash` / `remote_pwsh`、超时包装和目标上下文文案 |
|
|
26
|
-
| 远程文件工具 | `remote_read` / `remote_glob` / `remote_grep` 直接操作远程文件(显式 `server`);`remote_write` / `remote_edit`
|
|
27
|
-
| `remote_exec` 多资源并行 | 一次调用传 `tasks: [{ server, command, workdir?, timeoutMs? }]`;每个任务**显式指定目标**,按各自方言选择 POSIX/Windows 执行器,并发执行(默认 4,上限 8
|
|
26
|
+
| 远程文件工具 | `remote_read` / `remote_glob` / `remote_grep` 直接操作远程文件(显式 `server`);`remote_write` / `remote_edit` 默认关闭,可在插件管理的「允许远程写入」开关或 `remoteFileWrite` 配置里开启。原生 `read`/`write`/`edit`/`glob`/`grep` 仍只作用于本地 |
|
|
27
|
+
| `remote_exec` 多资源并行 | 一次调用传 `tasks: [{ server, command, workdir?, timeoutMs?, run_in_background? }]`;每个任务**显式指定目标**,按各自方言选择 POSIX/Windows 执行器,并发执行(默认 4,上限 8),逐任务超时、输出上限与错误隔离;不依赖也不修改任何会话目标状态。任务可单独立 `run_in_background`,返回远端 pid 与日志 |
|
|
28
28
|
| `remote_bash` / `remote_pwsh` | `command`、`workdir`(绝对路径 / `~/x` / 相对路径)、`timeoutMs`、取消沿用同一套语义;POSIX 目标超时后远端命令组会被终止(远端有 `timeout` 时含 `-k` 补 KILL),Windows 目标只能客户端停止等待 |
|
|
29
29
|
| 结果输出 | 原生 `bash` / `pwsh` 保留 DSH 原生终端卡片;`remote_bash` / `remote_pwsh` / `remote_exec` 返回带 server / cwd / 退出码 / stdout / stderr 的文本结果 |
|
|
30
|
-
| 后台任务 | `run_in_background: true` 在远端起**脱离会话**的进程:POSIX 用 `nohup` 重定向到 `/tmp
|
|
30
|
+
| 后台任务 | `run_in_background: true` 在远端起**脱离会话**的进程:POSIX 用 `nohup` 重定向到 `~/.dsh/ssh-workbench/logs`(`DSH_SSH_WORKBENCH_LOG_DIR` 可覆盖,不可写时回退 `/tmp`),Windows 用 `Start-Process` + 日志文件;结果返回 pid、日志路径和读取/停止命令(`tail -f` / `kill`、`Get-Content -Wait` / `Stop-Process`)。它不注册到 DSH 本地 `job_*` 注册表,进程在工具调用返回后继续运行 |
|
|
31
31
|
| 平台徽标 | 资源列表/设置页显示 **Linux / Windows** 徽标(来自连接后探测的 `facts.dialect`,不是手填字段);连接测试结果也显示探测到的平台 |
|
|
32
32
|
| 执行统计 | composer 下方的 pill 只读展示本会话的远程执行次数,结构对齐 DSH Token 用量弹窗:标题「远程执行」+ 总次数、分隔线、目标名 → 次数;没有执行时不显示。执行中 pill 会实时显示当前目标(单目标为 `host165 · 执行中`,多目标为 `2 个目标 · 执行中`),1.5 秒轮询;它不切换目标、不打开工作台,也不显示成功/失败或用时 |
|
|
33
33
|
| 远程工作台 | 左侧导航的独立页面:左侧终端(本地终端 / 远程 SSH 终端),右侧文件管理(本地用户主目录 / 远程 SFTP,远程默认打开登录 home),文件可**在工作台内直接预览**,拖动分隔条调整宽度;每个页签一个终端会话,仅活动页签轮询、非活动页签暂停并在切回时续读(UI 能力,不占模型工具) |
|
|
34
34
|
| 侧边栏开关 | 插件管理 → 远程工作台 → 页面里的「在侧边栏显示远程工作台」可关闭左侧导航入口;关闭后 `@资源名` 远程执行、设置页与模型工具不受影响 |
|
|
35
|
+
| 系统文件层级模式 | 插件管理 → 远程工作台 → 「系统文件浏览使用层级模式」默认关闭。开启后右侧栏「工作区文件」改为带面包屑/上级导航的层级浏览器,只浏览当前会话目录;保留 DSH 原生的刷新、搜索与「在应用中打开」(含选择其他应用);关闭恢复 DSH 原生页面 |
|
|
35
36
|
| 危险命令黑名单 | `rm -rf /`、`mkfs`、`dd of=/dev/*`、`fdisk/parted/wipefs`、改根目录权限、fork bomb 等同步拦截;多行脚本、`&`、引号/转义、路径变体、`$()`/`eval` 都会先还原再判断;其他命令交给 DSH 审批 |
|
|
36
37
|
|
|
37
38
|
**不做**:诊断包、HTTP 探测、跨主机文件分发、远程 IDE/SSHFS/透明代理(远程文件能力是显式的 `remote_*` 工具,不把本地 `read`/`write` 隐式重定向到远端)、命令分级(allow/guarded)、AI 风险解释和审计。
|
|
@@ -49,10 +50,10 @@ dsh plugin --profile desktop add dsh-ssh-workbench
|
|
|
49
50
|
```bash
|
|
50
51
|
npm test
|
|
51
52
|
npm run pack
|
|
52
|
-
# 然后在 DSH 的插件管理里安装 dist/dsh-ssh-workbench-1.7.
|
|
53
|
+
# 然后在 DSH 的插件管理里安装 dist/dsh-ssh-workbench-1.7.8.tgz
|
|
53
54
|
```
|
|
54
55
|
|
|
55
|
-
发布包是**自包含**的:SSH 传输依赖(纯 JS 的 ssh2 及其依赖)已放在 `vendor/` 里随包携带,安装时不会运行 `node-gyp`、不需要 Xcode Command Line Tools,也不会额外下载依赖;包体积因此略大(约
|
|
56
|
+
发布包是**自包含**的:SSH 传输依赖(纯 JS 的 ssh2 及其依赖)已放在 `vendor/` 里随包携带,安装时不会运行 `node-gyp`、不需要 Xcode Command Line Tools,也不会额外下载依赖;包体积因此略大(约 1.1 MB),换来任何机器开箱即装。组件与许可证见 `vendor/NOTICE.md`。
|
|
56
57
|
|
|
57
58
|
本地开发时,也可以在 DSH 的插件管理页直接安装本目录(Bundle 安装会读取 `package.json` 的 `dsh` 字段)。
|
|
58
59
|
|
|
@@ -68,7 +69,7 @@ npm run pack
|
|
|
68
69
|
@web-1 看下磁盘和内存
|
|
69
70
|
```
|
|
70
71
|
|
|
71
|
-
模型会调用 `remote_bash({ server: "web-1", command })`(Windows 目标是 `remote_pwsh`),命令实际跑在目标上。`read` / `write` / `edit` / `glob` / `grep` 仍然作用于本机;要读写远程文件,模型会改用 `remote_read` / `remote_glob` / `remote_grep
|
|
72
|
+
模型会调用 `remote_bash({ server: "web-1", command })`(Windows 目标是 `remote_pwsh`),命令实际跑在目标上。`read` / `write` / `edit` / `glob` / `grep` 仍然作用于本机;要读写远程文件,模型会改用 `remote_read` / `remote_glob` / `remote_grep`(写入需在插件管理里打开「允许远程写入」):
|
|
72
73
|
|
|
73
74
|
```
|
|
74
75
|
@web-1 把 /etc/nginx/nginx.conf 里 worker_connections 改成 2048,改完 nginx -t
|
|
@@ -101,11 +102,12 @@ npm run pack
|
|
|
101
102
|
|
|
102
103
|
- **stdout/stderr 顺序**:两者是独立管道,收集后分开返回(与原生 bash 的值契约一致),交错顺序会丢失;看 `make`/`pip install` 这类日志时需要留意。
|
|
103
104
|
- **Windows 本地路径**:工作台本地文件面板已按 Windows 分隔符处理面包屑与文件名;极少数外部工具生成的混合分隔符路径仍可能显示成一段,可在路径编辑框直接输入绝对路径。
|
|
104
|
-
- **`remote_exec`
|
|
105
|
-
- **后台任务**:`run_in_background` 返回的是远端 pid + 日志,不是 DSH 本地 job id;`timeoutMs` 和取消只影响启动调用,不作用于已脱离的进程。POSIX
|
|
105
|
+
- **`remote_exec` 批量规则**:一次最多 8 个 task、默认并发 4,所有结果共享 `maxBatchOutputBytes` 预算,超出会按任务截断;每个 task 都可以单独设置 `run_in_background`。
|
|
106
|
+
- **后台任务**:`run_in_background` 返回的是远端 pid + 日志,不是 DSH 本地 job id;`timeoutMs` 和取消只影响启动调用,不作用于已脱离的进程。POSIX 日志默认写在 `~/.dsh/ssh-workbench/logs`(可用 `DSH_SSH_WORKBENCH_LOG_DIR` 覆盖),只有该目录不可写时才回退 `/tmp`。
|
|
106
107
|
- **超时终止**:远端有 `timeout` 时,超时会连同远端进程组一起终止(支持 `-k` 时再补一次 KILL,缓冲时间可用 `timeoutKillAfterMs` 调整);远端没有 `timeout` 时只能停止等待,stderr 会提示"命令可能仍在运行"。**取消(Esc)不会立刻杀远端**:通道关闭后远端仍会计时到自己的 deadline。
|
|
107
108
|
- **stdin 恒为 EOF**:远程命令的 stdin 在启动后立即关闭(等价 `</dev/null`),`cat`/`read` 等读 stdin 的命令会直接得到 EOF。
|
|
108
|
-
- **文件工具分本地/远程**:原生 `read`/`write`/`edit`/`glob`/`grep` 只作用于本地;远程文件用显式的 `remote_read`/`remote_glob`/`remote_grep`,写入用 `remote_write`/`remote_edit
|
|
109
|
+
- **文件工具分本地/远程**:原生 `read`/`write`/`edit`/`glob`/`grep` 只作用于本地;远程文件用显式的 `remote_read`/`remote_glob`/`remote_grep`,写入用 `remote_write`/`remote_edit`(默认关闭)。POSIX 目标的远程写入会先写同目录临时文件再 `rename` 原子替换,并尽量保留原权限位;Windows 目标没有可靠的覆盖 rename,仍为直接写入;软链目标会写穿链接而不是替换链接。修改配置前仍建议备份;大文件/二进制仍建议走右侧栏 SFTP 面板。
|
|
110
|
+
- **composer pill 与后台任务**:pill 只在工具调用开始/结束时更新;`run_in_background` 的进程在工具返回后继续运行,pill 不会保持“执行中”,这不代表远端进程已结束。
|
|
109
111
|
- **并发由 DSH 调度**:`remote_exec` 显式声明并行安全,因此一次批量任务会真正并发(受 `batchConcurrency` 上限约束);原生 `bash` 与 `remote_bash` / `remote_pwsh` 仍是 exclusive 工具,同一轮里的多个 shell 调用按 DSH 调度串行。插件为单台服务器提供最多 6 条并发通道。
|
|
110
112
|
- **目标标识**:DSH 的工具卡片是官方渲染且没有装饰插槽,插件不替换卡片;远程调用的目标由工具参数(`server`)与结果里的 `target` / `cwd` 行体现,composer 下方的 pill 另提供本会话执行次数与执行中的实时目标。
|
|
111
113
|
- **侧边栏开关**:开关存放在 `~/.dsh/ssh-workbench/prefs.json`,在插件管理里保存后当前窗口立即生效;关闭时左侧导航不再出现远程工作台入口,右侧栏的「远程工作台」「远程文件」页签保持不变。
|
|
@@ -131,7 +133,8 @@ npm run pack
|
|
|
131
133
|
| `maxBatchOutputBytes` | `262144` | 一次 `remote_exec` 所有任务共享的 stdout/stderr 总预算 |
|
|
132
134
|
| `remoteFileReadBytes` | `262144` | `remote_read` 单次读取上限(字节) |
|
|
133
135
|
| `remoteFileEditBytes` | `2097152` | `remote_write` / `remote_edit` 的文件上限(字节) |
|
|
134
|
-
| `remoteFileWrite` | `false` |
|
|
136
|
+
| `remoteFileWrite` | `false` | `remote_write` / `remote_edit` 的默认开关;插件管理里的「允许远程写入」可覆盖它,默认关闭 |
|
|
137
|
+
| `systemFileHierarchy` | `false` | 系统「工作区文件」是否使用插件的层级浏览器;插件管理里的「系统文件浏览使用层级模式」可覆盖它 |
|
|
135
138
|
| `remoteGlobMaxResults` | `200` | `remote_glob` 结果上限 |
|
|
136
139
|
| `remoteGlobMaxDepth` | `4` | `remote_glob` 递归深度上限 |
|
|
137
140
|
| `remoteGrepMaxResults` | `200` | `remote_grep` 结果上限 |
|
package/docs/architecture.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SSH Workbench(dsh-ssh-workbench)架构(v1.7.
|
|
1
|
+
# SSH Workbench(dsh-ssh-workbench)架构(v1.7.8)
|
|
2
2
|
|
|
3
3
|
> 产品定位与用法见 [README.md](../README.md);本文只讲实现分层。
|
|
4
4
|
|
|
@@ -55,7 +55,7 @@ vendor/
|
|
|
55
55
|
- 从宿主消息里提取 `@名字`,匹配服务器清单;
|
|
56
56
|
- 仅记录为 @ 提示(candidates),不产生 active target;每轮注入资源清单与显式 server 工具规则,模型自行选择目标;
|
|
57
57
|
- 注入一条 user-role 资源上下文(source kind `ssh-workbench-target`),并 spread 下游 decision。
|
|
58
|
-
3. 模型选择一个远程工具并显式传 `server`:`remote_bash` / `remote_pwsh` / `remote_exec`,或远程文件工具 `remote_read` / `remote_glob` / `remote_grep
|
|
58
|
+
3. 模型选择一个远程工具并显式传 `server`:`remote_bash` / `remote_pwsh` / `remote_exec`,或远程文件工具 `remote_read` / `remote_glob` / `remote_grep`(写入需在插件管理里打开「允许远程写入」,对应 prefs 覆盖或 `remoteFileWrite` 配置)。原生 `bash` / `pwsh` 不经过插件,始终本地执行。
|
|
59
59
|
4. DSH 审批(本插件不参与)。
|
|
60
60
|
5. `ctx.tools.guard()`(`guard.js`):从 `arguments.server`(或 `remote_exec.tasks[]` 的每个 server)解析目标,按对应方言检查黑名单 → 命中直接拒绝。`gate.js` 先把每段还原成 argv words(去引号/转义、剥 `sudo`/`timeout` 等包装、路径规范化、重定向按 token、`$()`/`eval` 递归)再匹配。
|
|
61
61
|
6. 工具实现(`remote-shell-tool.js` / `remote-exec-tool.js` / `remote-file-tools.js`):
|
|
@@ -68,15 +68,15 @@ vendor/
|
|
|
68
68
|
|
|
69
69
|
## 多资源并行
|
|
70
70
|
|
|
71
|
-
`remote_exec({ tasks: [{ server, command, workdir?, timeoutMs? }], concurrency? })` 是插件自有的 `defineTool`,不走 `tools/execute`:
|
|
71
|
+
`remote_exec({ tasks: [{ server, command, workdir?, timeoutMs?, run_in_background? }], concurrency? })` 是插件自有的 `defineTool`,不走 `tools/execute`:
|
|
72
72
|
|
|
73
73
|
- **显式目标**:每个 task 自己带 `server`,不依赖也不修改任何会话目标状态;`server: "local"` 被拒绝,任务只能落在纳管资源上。
|
|
74
74
|
- **全量预检**:先解析全部 server、方言、workdir、timeout;任一 task 非法则整批拒绝,不会执行一半。
|
|
75
75
|
- **真正并发**:工具声明 `isConcurrencySafe: () => true`,DSH 的 batch 调度会把它和其他 parallel-safe 调用一起放进有界并发池;工具内部再按 `batchConcurrency`(默认 4,最大 8)跨服务器并发。单台服务器仍受 `maxChannelsPerServer` 约束。
|
|
76
76
|
- **逐任务隔离**:每个 task 按自己的 `facts.dialect` 选择 POSIX/Windows 适配器与 guard 规则;超时、传输失败、非零退出码只影响该任务,结果按输入顺序渲染。
|
|
77
77
|
- **输出预算**:一次 batch 共享 `maxBatchOutputBytes`(默认 256 KiB),每个 task 先取 `maxOutputBytes` 与均分预算的较小值,避免一次 fan-out 撑爆上下文。
|
|
78
|
-
-
|
|
79
|
-
- **UI**:composer 下方 pill 是执行账本的只读投影,结构对齐 DSH 内置 Token 用量弹窗:标题行「远程执行」+ 本 Session 总次数、0.5px 分隔线、目标名 →
|
|
78
|
+
- **后台任务**:每个 task 可单独设置 `run_in_background`;启动后该任务立即返回远端 pid 与日志,其余 task 继续并发执行。
|
|
79
|
+
- **UI**:composer 下方 pill 是执行账本的只读投影,结构对齐 DSH 内置 Token 用量弹窗:标题行「远程执行」+ 本 Session 总次数、0.5px 分隔线、目标名 → 执行次数。不显示成功/失败、用时或模型指标,也不承担切换或打开工作台;它只反映工具调用的开始/结束,后台任务启动后 pill 消失不代表远端进程结束。终端/文件从左侧工作台进入。弹层通过 `react-dom.createPortal` 挂到 `document.body`,避免被 composer 的 stacking context 裁切。没有执行记录时不显示,因此不存在“切本地后残留”。
|
|
80
80
|
|
|
81
81
|
## 多宿主与多方言
|
|
82
82
|
|
|
@@ -97,9 +97,9 @@ DSH 的内置 shell 工具按宿主平台二选一:POSIX 宿主有 `bash`、
|
|
|
97
97
|
|
|
98
98
|
`run_in_background: true` 不再报错,而是启动一个**脱离 SSH 会话**的远端进程:
|
|
99
99
|
|
|
100
|
-
- POSIX:`sh -c '<脚本>'` 内用 `nohup "$SHELL" -lc` 启动命令,stdout/stderr 重定向到
|
|
100
|
+
- POSIX:`sh -c '<脚本>'` 内用 `nohup "$SHELL" -lc` 启动命令,stdout/stderr 重定向到 `~/.dsh/ssh-workbench/logs` 下 `mktemp` 生成的日志(`DSH_SSH_WORKBENCH_LOG_DIR` 可覆盖,目录不可写时回退 `/tmp`);启动器打印 `__SDH_BG_PID__` / `__SDH_BG_LOG__` 标记。
|
|
101
101
|
- Windows:外层 PowerShell 用 `Start-Process -RedirectStandardOutput/-RedirectStandardError -WindowStyle Hidden -PassThru` 启动内层编码脚本,输出 `__SDH_BG_PID__` / `__SDH_BG_LOG__` / `__SDH_BG_ERR__`。
|
|
102
|
-
- 工具/路由解析标记后返回 pid
|
|
102
|
+
- 工具/路由解析标记后返回 pid、日志路径与读取/停止命令;`remote_exec` 的每个 task 各自解析并返回自己的 pid/日志;启动失败(没有 pid)返回 `REMOTE_BACKGROUND_FAILED`(原生 bash 路由)或该 task 的 `background start failed` 错误。
|
|
103
103
|
- 远端进程不在 DSH 本地 `job_*` 注册表里:`job_output` 看不到它,模型用 `tail` / `Get-Content` 取输出、`kill` / `Stop-Process` 停止;`timeoutMs` 与取消只作用于启动调用。
|
|
104
104
|
|
|
105
105
|
## 关键契约(来自 DSH,非本插件发明)
|
|
@@ -108,7 +108,7 @@ DSH 的内置 shell 工具按宿主平台二选一:POSIX 宿主有 `bash`、
|
|
|
108
108
|
- `agent/pre-step`:返回 `{ kind: 'enter', messages }`,改写必须 spread。
|
|
109
109
|
- `ctx.tools.guard()`:同步、单调的拒绝;在审批之后执行。
|
|
110
110
|
- 原生 `bash` 输出值:`{ kind:'foreground', cwd, exitCode, signal, timedOut, aborted, timeoutMs, stdout, stderr }`。
|
|
111
|
-
- 模型可见工具:`remote_exec`、`remote_bash`、`remote_pwsh`、`remote_read`、`remote_glob`、`remote_grep`、`remote_write`、`remote_edit`
|
|
111
|
+
- 模型可见工具:`remote_exec`、`remote_bash`、`remote_pwsh`、`remote_read`、`remote_glob`、`remote_grep`、`remote_write`、`remote_edit` 在两种宿主上都注册;默认只读工具可用,写工具在写入开关打开前明确拒绝;开关来自插件管理里的「允许远程写入」,未设置时回落到 `remoteFileWrite` 配置。原生 `bash` / `pwsh` / `read` / `write` / `edit` / `glob` / `grep` 保持本地语义。`remote_exec` 与只读文件工具声明 `isConcurrencySafe:true`,shell 与写文件工具保持 exclusive。
|
|
112
112
|
|
|
113
113
|
## @ 提示生命周期
|
|
114
114
|
|
package/docs/execution-model.md
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
| 单个目标 | `remote_bash({ server, command })` |
|
|
29
29
|
| 多个目标并行 | `remote_exec({ tasks: [{ server, command }] })` |
|
|
30
30
|
| 本机操作 | 原生 `bash` / `pwsh` / `read` / `write` / … |
|
|
31
|
-
| 远程文件 | `remote_read` / `remote_glob` / `remote_grep
|
|
31
|
+
| 远程文件 | `remote_read` / `remote_glob` / `remote_grep`(写需打开「允许远程写入」) |
|
|
32
32
|
|
|
33
33
|
**每个调用的目标都写在参数里**,因此并行安全、可审计、可复现,也不存在「状态残留」。执行工具在两种宿主上都注册,避免宿主自带 shell 平台差异(Windows 宿主没有原生 `bash`)影响可用性。
|
|
34
34
|
|
package/docs/quickstart.md
CHANGED
|
@@ -10,7 +10,9 @@ npm test
|
|
|
10
10
|
npm run pack
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
然后安装 `dist/dsh-ssh-workbench-1.7.
|
|
13
|
+
然后安装 `dist/dsh-ssh-workbench-1.7.8.tgz`。安装后重启/重载插件。
|
|
14
|
+
|
|
15
|
+
插件管理 → 远程工作台里可以打开「系统文件浏览使用层级模式」:右侧栏「工作区文件」会换成插件的层级浏览器,范围仅限当前会话目录;默认关闭。
|
|
14
16
|
|
|
15
17
|
发布包自带纯 JS 的 SSH 依赖,安装过程不需要编译(不需要 Xcode Command Line Tools)、也不额外下载 npm 包,离线机器同样可以安装。
|
|
16
18
|
|
|
@@ -58,7 +60,8 @@ composer 下方的 pill 只读展示本会话各目标的远程执行次数,
|
|
|
58
60
|
**左侧导航 → 远程工作台** 是一个独立页面:左边终端,右边文件管理,中间分隔条可拖动。
|
|
59
61
|
|
|
60
62
|
- 终端:点「+」新建 **本地终端** 或选择一台远程资源开 **远程 SSH 终端**;每个页签一个会话,关闭页签即结束会话。只有活动页签在后台读取输出,切回其他页签时会从上次位置补齐,不会丢输出。
|
|
61
|
-
- 文件:跟着当前终端页签走 —— 本地终端时显示 **本地用户主目录文件**(默认 `$HOME`,可用插件配置 `localRoot` 指定其他绝对目录),远程终端时显示该资源的 **SFTP 文件**(远程默认打开登录用户的 home
|
|
63
|
+
- 文件:跟着当前终端页签走 —— 本地终端时显示 **本地用户主目录文件**(默认 `$HOME`,可用插件配置 `localRoot` 指定其他绝对目录),远程终端时显示该资源的 **SFTP 文件**(远程默认打开登录用户的 home)。两类文件都支持浏览/**在工作台内直接单击预览**/下载/上传/重命名/删除/新建文件夹,远程文件还有传输记录与续传。文件行的操作菜单走 DSH 官方右键菜单:**右键**、`Shift+F10` 或行尾省略号按钮都能打开同一套菜单(打开、下载、复制文件、复制路径、重命名、删除)。
|
|
64
|
+
- 预览范围:Markdown(可切源码)、代码与配置(行号/换行/复制)、CSV/TSV(表格,可切源码)、图片(含 SVG,SVG 可切源码)、其他纯文本;文本读取上限 1 MB、图片 5 MB,超出时头部显示「已截断」并在底部标「前 N 行」。PDF、Office、压缩包等二进制走下载后本地打开。
|
|
62
65
|
- 本地文件范围限定在 `localRoot`(默认用户主目录)及其子目录,面包屑显示真实路径;越界路径与指向外部的符号链接会被拒绝,需要操作根目录以外的本地路径时用本地终端。
|
|
63
66
|
- 页面刷新/关闭会尽力关闭终端会话;进程异常退出时服务端会话会在空闲 30 分钟后回收。
|
|
64
67
|
|
|
@@ -67,7 +70,7 @@ composer 下方的 pill 只读展示本会话各目标的远程执行次数,
|
|
|
67
70
|
## 6. 常见问题
|
|
68
71
|
|
|
69
72
|
**远程文件怎么读写?**
|
|
70
|
-
原生 `read` / `write` / `edit` / `glob` / `grep` 始终作用于 DSH 主机;远程文件请让模型使用显式的远程文件工具:`remote_read`、`remote_glob`、`remote_grep
|
|
73
|
+
原生 `read` / `write` / `edit` / `glob` / `grep` 始终作用于 DSH 主机;远程文件请让模型使用显式的远程文件工具:`remote_read`、`remote_glob`、`remote_grep`。写入默认关闭:在「插件 → 远程工作台 → 允许远程写入」打开开关(或设置 `remoteFileWrite: true`)后才可使用 `remote_write` / `remote_edit`;后者默认要求 oldText 唯一匹配。大文件、二进制和上传/下载仍建议用右侧栏 SFTP 面板。POSIX 目标的写入是「同目录临时文件 + rename」原子替换,并尽量保留原权限位;Windows 目标仍为直接写入;软链目标写穿链接。修改关键配置前仍建议备份。
|
|
71
74
|
|
|
72
75
|
**命令很慢/超时?**
|
|
73
76
|
远程命令默认 120s,可用远程 shell 工具的 `timeoutMs` 参数(原生 `bash` / `remote_bash` / `remote_pwsh`)或插件配置 `commandTimeoutMs` 调整。连接池会复用连接,第一次会稍慢。超时后如果远端有 `timeout`,整个远端进程组会被终止(TERM 后按 `timeoutKillAfterMs` 再补 KILL);没有 `timeout` 的服务器(如 macOS)只能停止等待,命令可能还在跑,结果 stderr 会提示这一点。**取消(Esc)不会立即杀远端**,远端仍会计时到自己的 deadline。
|
|
@@ -79,10 +82,10 @@ composer 下方的 pill 只读展示本会话各目标的远程执行次数,
|
|
|
79
82
|
每个远程工具结果都带 server / target / cwd(如 `web-1:/var/log`),工具卡片也会显示执行的资源;composer 下方的 pill 只统计本会话执行次数。原生 `bash` / `pwsh` 的结果永远来自本机。
|
|
80
83
|
|
|
81
84
|
**能不能一次让多个资源并行执行?**
|
|
82
|
-
可以,让模型调用 `remote_exec`:每个 task 显式带 `server`,默认并发 4、最多 8,单次最多 8 个 task
|
|
85
|
+
可以,让模型调用 `remote_exec`:每个 task 显式带 `server`,默认并发 4、最多 8,单次最多 8 个 task;每个任务独立超时、独立输出、互不污染,结果按输入顺序返回。每个 task 也可单独设置 `run_in_background`,需要长任务时不必切回后台工具。`remote_bash` / `remote_pwsh` 也各自显式带 `server`,不存在需要先切换的单 active target。
|
|
83
86
|
|
|
84
87
|
**怎么跑长时间任务 / 后台服务?**
|
|
85
|
-
让模型带 `run_in_background: true` 调用远程 shell 工具(`remote_bash` / `remote_pwsh
|
|
88
|
+
让模型带 `run_in_background: true` 调用远程 shell 工具(`remote_bash` / `remote_pwsh`),或在 `remote_exec` 的某个 task 上设置它。工具会立刻返回远端 pid 和日志路径:
|
|
86
89
|
- POSIX:`tail -f <log>` 看输出,`kill <pid>` 停止;
|
|
87
90
|
- Windows:`Get-Content -LiteralPath '<log>' -Wait` 看输出,`Stop-Process -Id <pid> -Force` 停止。
|
|
88
91
|
后台进程与本次工具调用脱离,调用返回后继续运行;`timeoutMs` 只约束启动调用本身。它不是 DSH 本地 job,`job_*` 工具看不到它。
|