@lemoncat7/dsh-ssh 0.1.0-alpha.15

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 (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +105 -0
  3. package/cordis.patch.yml +10 -0
  4. package/lib/api.d.ts +23 -0
  5. package/lib/api.d.ts.map +1 -0
  6. package/lib/api.js +571 -0
  7. package/lib/api.js.map +1 -0
  8. package/lib/client-api.d.ts +174 -0
  9. package/lib/client-api.d.ts.map +1 -0
  10. package/lib/client-api.js +88 -0
  11. package/lib/client-api.js.map +1 -0
  12. package/lib/client.d.ts +4 -0
  13. package/lib/client.d.ts.map +1 -0
  14. package/lib/client.js +8067 -0
  15. package/lib/client.js.map +7 -0
  16. package/lib/config.d.ts +14 -0
  17. package/lib/config.d.ts.map +1 -0
  18. package/lib/config.js +31 -0
  19. package/lib/config.js.map +1 -0
  20. package/lib/connector.d.ts +30 -0
  21. package/lib/connector.d.ts.map +1 -0
  22. package/lib/connector.js +216 -0
  23. package/lib/connector.js.map +1 -0
  24. package/lib/credentials.d.ts +25 -0
  25. package/lib/credentials.d.ts.map +1 -0
  26. package/lib/credentials.js +84 -0
  27. package/lib/credentials.js.map +1 -0
  28. package/lib/directory.d.ts +8 -0
  29. package/lib/directory.d.ts.map +1 -0
  30. package/lib/directory.js +45 -0
  31. package/lib/directory.js.map +1 -0
  32. package/lib/domain.d.ts +121 -0
  33. package/lib/domain.d.ts.map +1 -0
  34. package/lib/domain.js +136 -0
  35. package/lib/domain.js.map +1 -0
  36. package/lib/exec.d.ts +15 -0
  37. package/lib/exec.d.ts.map +1 -0
  38. package/lib/exec.js +82 -0
  39. package/lib/exec.js.map +1 -0
  40. package/lib/forwards.d.ts +26 -0
  41. package/lib/forwards.d.ts.map +1 -0
  42. package/lib/forwards.js +213 -0
  43. package/lib/forwards.js.map +1 -0
  44. package/lib/index.d.ts +9 -0
  45. package/lib/index.d.ts.map +1 -0
  46. package/lib/index.js +53 -0
  47. package/lib/index.js.map +1 -0
  48. package/lib/proxy.d.ts +9 -0
  49. package/lib/proxy.d.ts.map +1 -0
  50. package/lib/proxy.js +116 -0
  51. package/lib/proxy.js.map +1 -0
  52. package/lib/sftp-client.d.ts +12 -0
  53. package/lib/sftp-client.d.ts.map +1 -0
  54. package/lib/sftp-client.js +123 -0
  55. package/lib/sftp-client.js.map +1 -0
  56. package/lib/sftp.d.ts +43 -0
  57. package/lib/sftp.d.ts.map +1 -0
  58. package/lib/sftp.js +251 -0
  59. package/lib/sftp.js.map +1 -0
  60. package/lib/sidebar-anchor.d.ts +8 -0
  61. package/lib/sidebar-anchor.d.ts.map +1 -0
  62. package/lib/sidebar-anchor.js +50 -0
  63. package/lib/sidebar-anchor.js.map +1 -0
  64. package/lib/store.d.ts +20 -0
  65. package/lib/store.d.ts.map +1 -0
  66. package/lib/store.js +154 -0
  67. package/lib/store.js.map +1 -0
  68. package/lib/terminal.d.ts +108 -0
  69. package/lib/terminal.d.ts.map +1 -0
  70. package/lib/terminal.js +384 -0
  71. package/lib/terminal.js.map +1 -0
  72. package/lib/tools.d.ts +7 -0
  73. package/lib/tools.d.ts.map +1 -0
  74. package/lib/tools.js +237 -0
  75. package/lib/tools.js.map +1 -0
  76. package/package.json +107 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 lemoncat7
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # dsh-ssh
2
+
3
+ 面向 DeepSeek Harness 的 SSH 会话管理插件。它把连接管理、浏览器终端、代理、端口转发和 AI 会话授权放在同一个 DSH 工作区里。
4
+
5
+ ## 能力
6
+
7
+ - SSH 密码、私钥和 SSH Agent 认证
8
+ - HTTP CONNECT、SOCKS5 和 SSH 跳板代理
9
+ - 本地转发(`-L`)、远程转发(`-R`)和动态 SOCKS5 转发(`-D`)
10
+ - 浏览器交互终端,支持输入、增量输出、窗口尺寸同步和主动断开
11
+ - 当前会话右侧栏支持多个 AI 终端切换与键盘输入
12
+ - SFTP 文件浏览、文本/图片/PDF 预览和流式下载
13
+ - 有序多主机跳板链,兼容已有单跳板配置
14
+ - 独立密钥库集中保存常用用户名、密码和私钥,SSH 连接仅保存引用
15
+ - 按 DSH 会话注入连接;未注入的主机对 AI 完全不可见
16
+ - AI 可执行一次性命令,或打开、读取、操作和关闭独立的交互终端
17
+ - 左侧远端区域提供右侧栏开关;目录页使用真实 SFTP 浏览远端文件,终端页使用单一终端画面观察并操作 AI 终端
18
+ - 插件服务与 Web 客户端兼容 Windows、macOS 和 Linux,不依赖本机 `ssh` 或 `sftp` 命令
19
+ - 首次连接主机指纹确认、输出上限、命令超时和公开端口绑定保护
20
+
21
+ ## 界面
22
+
23
+ 侧栏入口名为「远端」,通过官方 `sidebar.footer.action` 注册。浏览器兼容层只把这个入口锚定到官方 Workspace 区域上方;它不会替换 `sidebar.workspaces`,锚点失效时会自动留在官方 Footer。远端标题右侧按钮与折叠栏图标负责开关 SSH 右侧栏;展开后的第一项「SSH 面板」进入完整管理工作区,它下面只显示当前 DSH 会话已授权的 SSH 连接。点击其中一台主机会打开右侧栏并直接切换到该远端。切换到其他会话会自动退出管理工作区,也可以使用工作区左上角的返回按钮。
24
+
25
+ 管理工作区分成三部分:
26
+
27
+ 1. 左侧主机目录:按 Profile 的可选分组以文件夹展示,支持展开、收起、搜索、选择和凭据状态;未填写分组的主机归入「未分组」。
28
+ 2. 中间工作区:终端、SFTP、端口转发、密钥库和全局设置。SFTP 直接使用左侧选中的主机,可浏览、预览、下载和流式上传文件;同名文件覆盖前会再次确认,单文件上限为 512 MB。
29
+ 3. 右侧会话注入检查器:选择当前对话可用的主机、权限级别,以及是否自动允许权限范围内的 SSH 操作。
30
+
31
+ 工作区通过共享的 `@lemoncat7/dsh-plugin-ui` 自适应壳布局。宽容器使用三栏;窄于 820px 时主机目录与会话授权切换为左右抽屉,窄于 520px 时进一步压缩 SFTP 次要信息和操作密度。响应式判断使用容器查询,因此手机、桌面分屏和 DSH 窄面板采用同一套行为。
32
+
33
+ SSH 插件不会向聊天标题栏添加按钮。右侧栏统一从左侧「远端」区域打开;当前会话尚未注入主机时会显示授权引导。仅执行命令权限显示 SFTP 目录;终端控制权限同时显示 SFTP 目录和 AI 终端。多个终端通过紧凑标签切换,运行中的终端支持键盘输入。进入 SFTP 子目录时,该目录会同步成为后续 `ssh_exec` 与新终端的工作目录。
34
+
35
+ 新建和编辑连接的表单内提供「测试连接」。测试直接使用尚未保存的表单内容,可验证密钥库凭据、HTTP/SOCKS5 代理和有序跳板链;首次连接的主机指纹也在表单内确认。测试过程不会临时创建 Profile,也不会把凭据写入配置文件。
36
+
37
+ ## AI 工具
38
+
39
+ | 工具 | 用途 |
40
+ | --- | --- |
41
+ | `ssh_list` | 只列出当前 DSH 会话已注入的连接 |
42
+ | `ssh_set_cwd` | 设置并验证当前会话在指定主机上的工作目录 |
43
+ | `ssh_exec` | 执行一次性远端命令 |
44
+ | `ssh_terminal_open` | 打开当前 Agent 独占的 SSH 终端 |
45
+ | `ssh_terminal_send` | 向终端发送文本并等待输出稳定 |
46
+ | `ssh_terminal_read` | 分页读取终端回滚缓冲区 |
47
+ | `ssh_terminal_signal` | 发送允许的 POSIX 信号 |
48
+ | `ssh_terminal_close` | 关闭终端 |
49
+ | `ssh_forward_list` | 列出已注入连接的转发规则 |
50
+ | `ssh_forward_start` | 启动已有转发规则 |
51
+ | `ssh_forward_stop` | 停止已有转发规则 |
52
+
53
+ 工具始终从 `exec.agent.session.id` 解析注入关系。模型不能通过参数绕过授权,也不能枚举其他 DSH 会话的主机或终端。
54
+
55
+ ## 凭据与安全
56
+
57
+ 普通连接资料保存在 `statePath` 指定的原子 JSON 文件中。以下敏感字段只写入 DSH `ctx.credentials` 的 `dsh-ssh/<profile-id>` Grant Record:
58
+
59
+ - SSH 密码
60
+ - 私钥
61
+ - 私钥口令
62
+ - 代理密码
63
+
64
+ 密钥库条目使用独立的 `dsh-ssh-vault/<credential-id>` Grant Record。SSH Profile 只保存 `credentialId`,不会复制或读回密钥库中的明文。仍被连接引用的密钥库条目不能删除。
65
+
66
+ 管理 API 和 Web UI只返回是否配置以及字段名,不返回任何凭据值。默认拒绝非回环地址的端口监听;若确实需要监听 `0.0.0.0`,必须在「远端 → 设置」中显式开启。
67
+
68
+ 首次连接会拒绝未知主机密钥并展示 SHA-256 指纹。用户确认后才把指纹写入 Profile,后续连接严格比对。
69
+
70
+ ## DSH 配置
71
+
72
+ 安装包后,bundle 会插入默认配置:
73
+
74
+ ```yaml
75
+ - id: ssh
76
+ name: '@lemoncat7/dsh-ssh'
77
+ config:
78
+ statePath: !!js dshHomePath('ssh/state.json')
79
+ exposeWeb: true
80
+ apiPrefix: /ssh-local/v1
81
+ defaultCommandTimeoutMs: 30000
82
+ maxOutputChars: 32000
83
+ allowPublicBind: false
84
+ ```
85
+
86
+ 插件依赖当前 DSH 的 `credentials` 和 `tools` 服务。浏览器管理还需要 Web Profile 的 `webServer`;浏览器终端和 AI 终端由插件内部按所有者隔离管理,不依赖 Host Root 中不存在的 `terminals` 服务。
87
+
88
+ ## 开发与打包
89
+
90
+ ```bash
91
+ npm install
92
+ npm test
93
+ npm pack --pack-destination dist
94
+ ```
95
+
96
+ 运行时要求 Node.js 22.19+ 或 Node.js 24+,并与 DSH `0.1.1-rc.2` 接口对齐。
97
+
98
+ ## 终端隔离说明
99
+
100
+ 浏览器终端和 AI 终端共享同一个连接 Profile 与凭据,但不是同一个终端实例:
101
+
102
+ - 浏览器终端由插件的同源管理 API 持有,页面关闭或空闲超时后清理。
103
+ - AI 终端由插件按 `sessionId` 分区持有。Web Profile 的官方 Terminal 服务位于每个 Agent Preset 的私有 Realm,主机插件不能跨 Realm 注册 Backend,因此插件使用相同的 owner-scoped 规则实现 SSH 终端隔离,并在插件卸载或进程退出时统一清理。
104
+
105
+ 这种边界避免浏览器用户和模型同时争用同一个 TTY,也遵守 DSH 不允许跨 Agent 共享终端的所有权规则。
@@ -0,0 +1,10 @@
1
+ - insert:
2
+ - id: ssh
3
+ name: '@lemoncat7/dsh-ssh'
4
+ config:
5
+ statePath: !!js dshHomePath('ssh/state.json')
6
+ exposeWeb: true
7
+ apiPrefix: /ssh-local/v1
8
+ defaultCommandTimeoutMs: 30000
9
+ maxOutputChars: 32000
10
+ allowPublicBind: false
package/lib/api.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import { SshConnector } from './connector.js';
3
+ import { SshCredentialVault } from './credentials.js';
4
+ import { ForwardManager } from './forwards.js';
5
+ import { SshStore } from './store.js';
6
+ import { AiTerminalManager, BrowserTerminalManager } from './terminal.js';
7
+ export interface WebServerLike {
8
+ register(route: {
9
+ kind: 'prefix';
10
+ path: string;
11
+ handler(req: IncomingMessage, res: ServerResponse): void | Promise<void>;
12
+ }): () => void;
13
+ }
14
+ export interface SshApiRuntime {
15
+ store: SshStore;
16
+ credentials: SshCredentialVault;
17
+ connector: SshConnector;
18
+ forwards: ForwardManager;
19
+ terminals: BrowserTerminalManager;
20
+ aiTerminals: AiTerminalManager;
21
+ }
22
+ export declare function registerSshApi(webServer: WebServerLike, prefix: string, runtime: SshApiRuntime): () => void;
23
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAEhE,OAAO,EAAwB,YAAY,EAAE,MAAM,gBAAgB,CAAA;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAKrD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAErC,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAMzE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE;QACd,IAAI,EAAE,QAAQ,CAAA;QACd,IAAI,EAAE,MAAM,CAAA;QACZ,OAAO,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;KACzE,GAAG,MAAM,IAAI,CAAA;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,QAAQ,CAAA;IACf,WAAW,EAAE,kBAAkB,CAAA;IAC/B,SAAS,EAAE,YAAY,CAAA;IACvB,QAAQ,EAAE,cAAc,CAAA;IACxB,SAAS,EAAE,sBAAsB,CAAA;IACjC,WAAW,EAAE,iBAAiB,CAAA;CAC/B;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,IAAI,CAa3G"}