@xiaoqiong0v0/opencode-ssh-tool 0.2.4
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/README.md +159 -0
- package/dist/config.d.ts +31 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +107 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +24 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +25 -0
- package/dist/constants.js.map +1 -0
- package/dist/history.d.ts +54 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +114 -0
- package/dist/history.js.map +1 -0
- package/dist/i18n.d.ts +232 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/i18n.js +222 -0
- package/dist/i18n.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +379 -0
- package/dist/index.js.map +1 -0
- package/dist/permission.d.ts +12 -0
- package/dist/permission.d.ts.map +1 -0
- package/dist/permission.js +39 -0
- package/dist/permission.js.map +1 -0
- package/dist/server.d.ts +25 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +179 -0
- package/dist/server.js.map +1 -0
- package/dist/session.d.ts +122 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +410 -0
- package/dist/session.js.map +1 -0
- package/dist/ssh-auth.d.ts +13 -0
- package/dist/ssh-auth.d.ts.map +1 -0
- package/dist/ssh-auth.js +50 -0
- package/dist/ssh-auth.js.map +1 -0
- package/dist/utils.d.ts +33 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +60 -0
- package/dist/utils.js.map +1 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# opencode-ssh-tool
|
|
2
|
+
|
|
3
|
+
opencode 插件:让 opencode 像人一样操作**长驻交互式 SSH 会话**。连接一次,后续在一个会话里连续执行命令,保留当前目录、环境变量、交互状态;远程命令执行同样受 opencode 权限系统管控(类似内置 Bash 工具的审批)。
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
|
|
7
|
+
- **长驻会话**:`ssh_connect` 建立连接后,`ssh_exec` 在同一会话执行命令,保留 cwd/环境/后台进程/sudo 缓存
|
|
8
|
+
- **PTY 交互**:分配伪终端,可处理 sudo 密码、vi、top 等交互程序
|
|
9
|
+
- **权限管控**:只读白名单直接放行、危险命令黑名单硬拒、其余走 `context.ask()` 用户审批
|
|
10
|
+
- **命令完成判定**:哨兵标记 + 静默窗口 + 超时三重兜底,动画输出(进度条等)自动识别
|
|
11
|
+
- **历史消息对**:命令+输出 全部存文件(`~/.opencode/plugins-cache/opencode-ssh-tool/<会话>/`),按对数保留(默认 100 对),重启不丢、会话关闭清理
|
|
12
|
+
- **HTTP 终端查看**:默认开启本地服务,浏览器打开可滚动、自动刷新的终端记录页面
|
|
13
|
+
- **多语言**:工具描述默认英文,`SSH_TOOL_LANG=zh` 切中文
|
|
14
|
+
|
|
15
|
+
## 安装
|
|
16
|
+
|
|
17
|
+
```jsonc
|
|
18
|
+
// opencode.json
|
|
19
|
+
{
|
|
20
|
+
"plugin": ["opencode-ssh-tool"]
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
发布到 npm 后通过 `plugin` 数组引用;或本地调试时挂载到项目 `.opencode/` 文件夹。
|
|
25
|
+
|
|
26
|
+
## 工具
|
|
27
|
+
|
|
28
|
+
| 工具 | 入参 | 行为 |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| `ssh_connect` | `host`, `user`, `port?`, `name?` | 建立长驻 SSH 连接 + 打开 PTY shell;`name` 指定终端名(默认 `default`),同名先关旧终端 |
|
|
31
|
+
| `ssh_exec` | `command`, `waitResult?`, `name?` | 在指定终端执行命令;默认异步提交立即返回,`waitResult=true` 同步等结果 |
|
|
32
|
+
| `ssh_read` | `source?`, `lines?`, `direction?`, `limit?`, `includeCommand?`, `name?` | 读指定终端输出:`buffer` 实时未消费 / `history` 已完成对(前/后 N 条) |
|
|
33
|
+
| `ssh_status` | `name?` | 指定终端状态(busy/pending/连接);省略则列出全部终端 + HTTP 服务状态 |
|
|
34
|
+
| `ssh_disconnect` | `name?` | 断开指定终端(默认 `default`);省略则断开全部终端 |
|
|
35
|
+
|
|
36
|
+
> 一个 opencode 会话可创建**多个命名终端**(如 `db`、`web`、`prod`),用不同 `name` 并行维护;同名重复创建会先关闭旧的。
|
|
37
|
+
|
|
38
|
+
## 配置
|
|
39
|
+
|
|
40
|
+
配置文件 `~/.config/opencode/ssh-tool.jsonc`(首次运行自动生成):
|
|
41
|
+
|
|
42
|
+
```jsonc
|
|
43
|
+
{
|
|
44
|
+
// HTTP 终端记录服务开关(默认 true)
|
|
45
|
+
"server": {
|
|
46
|
+
"enabled": true,
|
|
47
|
+
// 端口:不设默认值。0 = 自动分配随机端口(推荐,避免冲突);可显式指定,如 8137
|
|
48
|
+
"port": 0
|
|
49
|
+
},
|
|
50
|
+
// 会话记录(命令+输出 消息对)管理:全部存文件(~/.opencode/plugins-cache/opencode-ssh-tool/<会话>/),随会话清理
|
|
51
|
+
"history": {
|
|
52
|
+
// 保留的消息对数上限(默认 100,最小 1)。超出时移除最旧的一对
|
|
53
|
+
"maxMessages": 100
|
|
54
|
+
},
|
|
55
|
+
// 工具描述语言:"en" | "zh"(默认 "en",可用环境变量 SSH_TOOL_LANG 覆盖)
|
|
56
|
+
"toolLang": "en",
|
|
57
|
+
// 权限自定义正则(追加到内置默认,控制"拒绝"与"需审批"命令)
|
|
58
|
+
"permission": {
|
|
59
|
+
// 内置默认危险命令黑名单(命中直接拒绝):
|
|
60
|
+
// rm 危险目标(/ ~ . /etc /var /usr 等) | shutdown/reboot/halt/poweroff | mkfs/mkswap/fdisk/parted/dd
|
|
61
|
+
// iptables/ufw/firewall-cmd | systemctl | service stop/restart/kill | kill/killall/pkill
|
|
62
|
+
// passwd/useradd/userdel/groupadd/groupdel | chown -R | chmod -R 777 / | apt remove | npm uninstall
|
|
63
|
+
// DROP TABLE/TRUNCATE/DROP DATABASE | fork炸弹 | > /etc/{passwd,shadow,sudoers,fstab}
|
|
64
|
+
// curl|sh / wget|sh / base64 -d |
|
|
65
|
+
// 自定义补充示例:["^mkfs\\s", "^dd\\s"](空数组 = 仅使用内置默认)
|
|
66
|
+
"deny": [],
|
|
67
|
+
// 内置默认只读白名单(命中且无 shell 元字符则直接放行):
|
|
68
|
+
// ls | cd | cat | grep | tail | head | ps | df | free | pwd | env | echo | curl | wget | git status | whoami | hostname | date | uname | uptime
|
|
69
|
+
// 自定义补充示例:["^df\\s.*-h$"](空数组 = 仅使用内置默认)
|
|
70
|
+
"allow": []
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
多语言优先级:环境变量 `SSH_TOOL_LANG` > 配置文件 `toolLang` > 默认 `en`。
|
|
76
|
+
|
|
77
|
+
权限自定义正则**追加**到内置默认(`DENY` 黑名单 + `ALLOW_READONLY` 白名单),`deny`/`allow` 为空数组时仅用内置默认规则,可自行补充扩展。
|
|
78
|
+
|
|
79
|
+
## 认证
|
|
80
|
+
|
|
81
|
+
按优先级自动选择,认证信息**不硬编码**、不落日志:
|
|
82
|
+
|
|
83
|
+
1. **SSH key**(推荐):用户默认私钥(`id_ed25519` / `id_rsa`)
|
|
84
|
+
2. **SSH agent**:agent socket / Windows OpenSSH agent
|
|
85
|
+
3. **环境变量密码**:`SSH_PASS_<HOST大写>` 优先,回退 `SSH_PASSWORD`
|
|
86
|
+
|
|
87
|
+
## 权限管控
|
|
88
|
+
|
|
89
|
+
```text
|
|
90
|
+
ssh_exec(command)
|
|
91
|
+
├─ 命中 DENY 黑名单(rm -rf / shutdown reboot mkfs 等) → 直接拒绝
|
|
92
|
+
├─ 命中只读白名单 且 无 shell 元字符 → 直接放行
|
|
93
|
+
└─ 其他 → context.ask() 用户审批(:allow / :deny / :always)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
- 只读白名单:`ls|cd|cat|grep|tail|head|ps|df|free|pwd|env|echo|curl|wget|git status|whoami|hostname|date|uname|uptime`
|
|
97
|
+
- 命令含 `;` `&&` `|` `$()` 等 shell 元字符 → 降级走 ask(防拼接绕过)
|
|
98
|
+
- 高危命令不进 ask 直接拒,`ssh_connect` 也走审批
|
|
99
|
+
|
|
100
|
+
## HTTP 终端查看
|
|
101
|
+
|
|
102
|
+
服务默认开启(配置 `server.enabled`)。`ssh_status` / `ssh_read`(history 模式)会返回实际地址(端口 0 时自动分配,避免冲突):
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
浏览器访问 http://127.0.0.1:<port> 查看可滚动、每 2s 自动刷新的终端记录
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
页面按会话切换,展示「命令 + 输出」历史对。
|
|
109
|
+
|
|
110
|
+
## 架构
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
opencode(插件进程)
|
|
114
|
+
├─ ssh2 客户端:长驻连接 + PTY shell(每个 opencode 会话一个)
|
|
115
|
+
│ └─ 哨兵法执行命令(combo; echo __SSH_DONE_<rand>__)
|
|
116
|
+
├─ SessionHistory:命令+输出 消息对(按对数限制,超大落盘)
|
|
117
|
+
└─ HTTP 服务:127.0.0.1 随机端口,浏览器查看终端记录
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## 开发
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
npm install # 安装依赖(dependencies + devDependencies)
|
|
124
|
+
npm run build # tsc:src → dist
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
- TS 源码在 `src/`,编译产物 `dist/`
|
|
128
|
+
- 本地测试:编译产物挂载到测试项目 `.opencode/` 文件夹,在该项目启动 opencode 验证
|
|
129
|
+
- 日志:`@xiaoqiong0v0/opencode-plugin-logger` 按天滚动落盘
|
|
130
|
+
|
|
131
|
+
## 发布
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
npm run build
|
|
135
|
+
npm publish # 只发布 dist/
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
本项目提交 GitHub 发布 npm;使用方 `opencode.json` 的 `plugin` 数组引用。
|
|
139
|
+
|
|
140
|
+
## 测试清单
|
|
141
|
+
|
|
142
|
+
需真实 SSH 主机(可用 Docker 测试环境,见 `.tmp/ssh-test-docker.ps1`):
|
|
143
|
+
|
|
144
|
+
- [ ] `ssh_connect` → 登录成功,cwd 为登录目录
|
|
145
|
+
- [ ] `ssh_exec("ls")` 连续多次,确认永不重连(同一会话)
|
|
146
|
+
- [ ] `ssh_exec("cd /var/log && pwd")` 后 `ssh_exec("pwd")` = `/var/log`(目录保持)
|
|
147
|
+
- [ ] 交互场景:`ssh_exec("sudo ...")` 触发密码提示 → `ssh_read` 配合
|
|
148
|
+
- [ ] 白名单命令不弹审批直接执行;`rm -rf` 被拒绝
|
|
149
|
+
- [ ] 白名单外命令弹 `context.ask()`,`:deny` 拒绝 / `:allow` 放行
|
|
150
|
+
- [ ] 长命令超时:`ssh_exec("sleep 60")` 30s 超时返回,不挂死会话
|
|
151
|
+
- [ ] `ssh_read` 取前/后 N 条历史输出(含 `includeCommand`、`source=buffer`)
|
|
152
|
+
- [ ] `ssh_status` / HTTP 页面浏览器可访问
|
|
153
|
+
- [ ] `ssh_disconnect` 后连接释放
|
|
154
|
+
|
|
155
|
+
## 文档
|
|
156
|
+
|
|
157
|
+
- `docs/requirements/需求说明.md` — 原始需求
|
|
158
|
+
- `docs/design/方案分析.md` — 技术分析、决策、风险
|
|
159
|
+
- `docs/design/结构设计.md` — 编码依据
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Lang } from "./i18n.js";
|
|
2
|
+
/** HTTP 服务配置 */
|
|
3
|
+
export interface ServerConfig {
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
port: number;
|
|
6
|
+
}
|
|
7
|
+
/** 会话记录(命令+输出 消息对)配置 */
|
|
8
|
+
export interface HistoryConfig {
|
|
9
|
+
maxMessages: number;
|
|
10
|
+
}
|
|
11
|
+
/** 权限自定义正则配置(追加到内置默认,控制"拒绝"与"需审批"命令) */
|
|
12
|
+
export interface PermissionConfig {
|
|
13
|
+
/** 危险命令正则(命中直接拒绝),如 ["^mkfs\\s", "^dd\\s"] */
|
|
14
|
+
deny: string[];
|
|
15
|
+
/** 只读白名单正则(命中且无 shell 元字符则直接放行),如 ["^df\\s.*-h$"] */
|
|
16
|
+
allow: string[];
|
|
17
|
+
}
|
|
18
|
+
/** 工具整体配置 */
|
|
19
|
+
export interface ToolConfig {
|
|
20
|
+
server: ServerConfig;
|
|
21
|
+
history: HistoryConfig;
|
|
22
|
+
/** 工具描述语言(默认 en,可用环境变量 SSH_TOOL_LANG 覆盖) */
|
|
23
|
+
toolLang: Lang;
|
|
24
|
+
permission: PermissionConfig;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 加载工具配置:读 jsonc,缺失项用默认值;文件不存在则自动生成模板
|
|
28
|
+
* @returns 工具配置
|
|
29
|
+
*/
|
|
30
|
+
export declare function loadConfig(): ToolConfig;
|
|
31
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAErC,gBAAgB;AAChB,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,wBAAwB;AACxB,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,wCAAwC;AACxC,MAAM,WAAW,gBAAgB;IAC/B,8CAA8C;IAC9C,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,qDAAqD;IACrD,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,aAAa;AACb,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,YAAY,CAAA;IACpB,OAAO,EAAE,aAAa,CAAA;IACtB,4CAA4C;IAC5C,QAAQ,EAAE,IAAI,CAAA;IACd,UAAU,EAAE,gBAAgB,CAAA;CAC7B;AAuED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,UAAU,CA+BvC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// 配置文件读取:~/.config/opencode/ssh-tool.jsonc(服务/记录/语言),首次运行自动生成模板
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
/** 配置默认值 */
|
|
6
|
+
const DEFAULT_CONFIG = {
|
|
7
|
+
server: {
|
|
8
|
+
enabled: true,
|
|
9
|
+
// 端口不设默认值:0 = 自动分配随机端口(避免冲突)
|
|
10
|
+
port: 0,
|
|
11
|
+
},
|
|
12
|
+
history: {
|
|
13
|
+
// 保留的消息对数(最小 1,保留最新)
|
|
14
|
+
maxMessages: 100,
|
|
15
|
+
},
|
|
16
|
+
toolLang: "en",
|
|
17
|
+
permission: {
|
|
18
|
+
deny: [],
|
|
19
|
+
allow: [],
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
/** 配置文件路径:~/.config/opencode/ssh-tool.jsonc */
|
|
23
|
+
function configPath() {
|
|
24
|
+
const dir = process.env.USERPROFILE || process.env.HOME || homedir();
|
|
25
|
+
return join(dir, ".config", "opencode", "ssh-tool.jsonc");
|
|
26
|
+
}
|
|
27
|
+
/** 配置模板(首次运行生成) */
|
|
28
|
+
const CONFIG_TEMPLATE = `{
|
|
29
|
+
// HTTP 终端记录服务开关(默认 true)
|
|
30
|
+
"server": {
|
|
31
|
+
"enabled": true,
|
|
32
|
+
// 端口:不设默认值。0 = 自动分配随机端口(推荐,避免冲突);可显式指定,如 8137
|
|
33
|
+
"port": 0
|
|
34
|
+
},
|
|
35
|
+
// 会话记录(命令+输出 消息对)管理:全部存文件(~/.opencode/plugins-cache/opencode-ssh-tool/<会话>/),随会话清理
|
|
36
|
+
"history": {
|
|
37
|
+
// 保留的消息对数上限(默认 100,最小 1)。超出时移除最旧的一对
|
|
38
|
+
"maxMessages": 100
|
|
39
|
+
},
|
|
40
|
+
// 工具描述语言:"en" | "zh"(默认 "en",可用环境变量 SSH_TOOL_LANG 覆盖)
|
|
41
|
+
"toolLang": "en",
|
|
42
|
+
// 权限自定义正则(追加到内置默认,控制"拒绝"与"需审批"命令)
|
|
43
|
+
"permission": {
|
|
44
|
+
// 内置默认危险命令黑名单(命中直接拒绝,不需要重复添加):
|
|
45
|
+
// rm 危险目标(/ ~ . /etc /var /usr 等) | shutdown/reboot/halt/poweroff | mkfs/mkswap/fdisk/parted/dd
|
|
46
|
+
// iptables/ufw/firewall-cmd | systemctl | service stop/restart/kill | kill/killall/pkill
|
|
47
|
+
// passwd/useradd/userdel/groupadd/groupdel | chown -R | chmod -R 777 / | apt remove | npm uninstall
|
|
48
|
+
// DROP TABLE/TRUNCATE/DROP DATABASE | fork炸弹 | > /etc/{passwd,shadow,sudoers,fstab}
|
|
49
|
+
// curl|sh / wget|sh / base64 -d |
|
|
50
|
+
// 自定义补充示例:["^mkfs\\s", "^dd\\s"](此数组为空 = 仅使用内置默认)
|
|
51
|
+
"deny": [],
|
|
52
|
+
// 内置默认只读白名单(命中且无 shell 元字符则直接放行):
|
|
53
|
+
// ls | cd | cat | grep | tail | head | ps | df | free | pwd | env | echo | curl | wget | git status | whoami | hostname | date | uname | uptime
|
|
54
|
+
// 自定义补充示例:["^df\\s.*-h$"](此数组为空 = 仅使用内置默认)
|
|
55
|
+
"allow": []
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
`;
|
|
59
|
+
/**
|
|
60
|
+
* 去除 jsonc 注释后解析为对象(支持 // 与 /* *\/)
|
|
61
|
+
* @param text jsonc 文本
|
|
62
|
+
* @returns 解析结果对象
|
|
63
|
+
*/
|
|
64
|
+
function parseJsonc(text) {
|
|
65
|
+
const stripped = text
|
|
66
|
+
.replace(/\/\*[\s\S]*?\*\//g, "")
|
|
67
|
+
.replace(/(^|[^:])\/\/.*$/gm, "$1");
|
|
68
|
+
return JSON.parse(stripped);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 加载工具配置:读 jsonc,缺失项用默认值;文件不存在则自动生成模板
|
|
72
|
+
* @returns 工具配置
|
|
73
|
+
*/
|
|
74
|
+
export function loadConfig() {
|
|
75
|
+
try {
|
|
76
|
+
const path = configPath();
|
|
77
|
+
if (!existsSync(path)) {
|
|
78
|
+
mkdirSync(join(path, ".."), { recursive: true });
|
|
79
|
+
writeFileSync(path, CONFIG_TEMPLATE, "utf8");
|
|
80
|
+
return DEFAULT_CONFIG;
|
|
81
|
+
}
|
|
82
|
+
const raw = parseJsonc(readFileSync(path, "utf8"));
|
|
83
|
+
const server = (raw.server ?? {});
|
|
84
|
+
const history = (raw.history ?? {});
|
|
85
|
+
const permission = (raw.permission ?? {});
|
|
86
|
+
const toolLang = raw.toolLang === "zh" ? "zh" : "en";
|
|
87
|
+
return {
|
|
88
|
+
server: {
|
|
89
|
+
enabled: server.enabled ?? DEFAULT_CONFIG.server.enabled,
|
|
90
|
+
port: typeof server.port === "number" && Number.isFinite(server.port) ? server.port : DEFAULT_CONFIG.server.port,
|
|
91
|
+
},
|
|
92
|
+
history: {
|
|
93
|
+
maxMessages: Math.max(1, history.maxMessages ?? DEFAULT_CONFIG.history.maxMessages),
|
|
94
|
+
},
|
|
95
|
+
toolLang,
|
|
96
|
+
permission: {
|
|
97
|
+
deny: Array.isArray(permission.deny) ? permission.deny : [],
|
|
98
|
+
allow: Array.isArray(permission.allow) ? permission.allow : [],
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
// 配置解析失败回退默认
|
|
104
|
+
return DEFAULT_CONFIG;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** 只读命令白名单(整串匹配,含元字符的命令不适用白名单) */
|
|
2
|
+
export declare const ALLOW_READONLY: RegExp;
|
|
3
|
+
/** 高危命令黑名单(命中直接拒绝,不进 ask) */
|
|
4
|
+
export declare const DENY: RegExp;
|
|
5
|
+
/** shell 元字符(出现即降级走 ask,防白名单拼接绕过) */
|
|
6
|
+
export declare const SHELL_META: RegExp;
|
|
7
|
+
/** 单次 ssh_exec 默认超时(毫秒) */
|
|
8
|
+
export declare const EXEC_TIMEOUT_MS = 30000;
|
|
9
|
+
/** 静默窗口阈值:输出停止增长超过此时长视为命令完成 */
|
|
10
|
+
export declare const QUIET_WINDOW_MS = 500;
|
|
11
|
+
/** 动画检测阈值:连续输出超过此时长仍无哨兵/静默 → 判定仍在运行 */
|
|
12
|
+
export declare const ANIMATION_WINDOW_MS = 5000;
|
|
13
|
+
/** ssh2 认证超时(毫秒) */
|
|
14
|
+
export declare const READY_TIMEOUT_MS = 10000;
|
|
15
|
+
/** PTY 窗口尺寸(大窗口减少分页) */
|
|
16
|
+
export declare const PTY_ROWS = 200;
|
|
17
|
+
export declare const PTY_COLS = 500;
|
|
18
|
+
/** 单次工具返回输出上限(字节) */
|
|
19
|
+
export declare const MAX_OUTPUT_LEN = 50000;
|
|
20
|
+
/** 工具描述语言环境变量(en | zh,默认 en) */
|
|
21
|
+
export declare const LANG_ENV = "SSH_TOOL_LANG";
|
|
22
|
+
/** 插件缓存根目录(历史消息对存文件,随会话清理) */
|
|
23
|
+
export declare const CACHE_DIR = ".opencode/plugins-cache/opencode-ssh-tool";
|
|
24
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAEA,kCAAkC;AAClC,eAAO,MAAM,cAAc,QAC0F,CAAA;AAErH,6BAA6B;AAC7B,eAAO,MAAM,IAAI,QAC0kB,CAAA;AAE3lB,qCAAqC;AACrC,eAAO,MAAM,UAAU,QAAgB,CAAA;AAEvC,2BAA2B;AAC3B,eAAO,MAAM,eAAe,QAAS,CAAA;AAErC,+BAA+B;AAC/B,eAAO,MAAM,eAAe,MAAM,CAAA;AAElC,uCAAuC;AACvC,eAAO,MAAM,mBAAmB,OAAQ,CAAA;AAExC,oBAAoB;AACpB,eAAO,MAAM,gBAAgB,QAAS,CAAA;AAEtC,wBAAwB;AACxB,eAAO,MAAM,QAAQ,MAAM,CAAA;AAC3B,eAAO,MAAM,QAAQ,MAAM,CAAA;AAE3B,qBAAqB;AACrB,eAAO,MAAM,cAAc,QAAS,CAAA;AAEpC,gCAAgC;AAChC,eAAO,MAAM,QAAQ,kBAAkB,CAAA;AAEvC,8BAA8B;AAC9B,eAAO,MAAM,SAAS,8CAA8C,CAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// 全局常量:权限正则、超时、PTY 尺寸、输出限制、语言配置
|
|
2
|
+
/** 只读命令白名单(整串匹配,含元字符的命令不适用白名单) */
|
|
3
|
+
export const ALLOW_READONLY = /^(?:ls|cd|cat|grep|tail|head|ps|df|free|pwd|env|echo|curl|wget|git status|whoami|hostname|date|uname|uptime)\b.*$/;
|
|
4
|
+
/** 高危命令黑名单(命中直接拒绝,不进 ask) */
|
|
5
|
+
export const DENY = /(?:rm\s+(?:-[a-z]*[fr][a-z]*(?:\s+-[a-z]*[fr][a-z]*)?\s+)?(?:\/(?:\s|$)|~|\.(?:\.)?|\/(?:etc|var|usr|boot|bin|sbin|lib|lib64|opt|root)(?:\s|$))|shutdown|reboot|halt|poweroff|mkfs|mkswap|fdisk|parted|dd\s|iptables|ufw|firewall-cmd|systemctl|service\s+\w+\s+(?:stop|restart|kill)|kill(?:all)?\s|pkill\s|passwd\s|useradd|userdel|groupadd|groupdel|chown\s+-R|chmod\s+-R\s+777\s+\/|apt\s+remove|apt-get\s+remove|npm\s+(?:uninstall|rm)\b|DROP\s+TABLE|TRUNCATE\s+TABLE|DROP\s+DATABASE|:\(\)\s*\{|>\s*\/etc\/(?:passwd|shadow|sudoers|fstab)|curl\s+.*\|\s*(?:ba)?sh|wget\s+.*\|\s*(?:ba)?sh|base64\s+-d\s*[|>])/;
|
|
6
|
+
/** shell 元字符(出现即降级走 ask,防白名单拼接绕过) */
|
|
7
|
+
export const SHELL_META = /[;|&`$()<>]/;
|
|
8
|
+
/** 单次 ssh_exec 默认超时(毫秒) */
|
|
9
|
+
export const EXEC_TIMEOUT_MS = 30_000;
|
|
10
|
+
/** 静默窗口阈值:输出停止增长超过此时长视为命令完成 */
|
|
11
|
+
export const QUIET_WINDOW_MS = 500;
|
|
12
|
+
/** 动画检测阈值:连续输出超过此时长仍无哨兵/静默 → 判定仍在运行 */
|
|
13
|
+
export const ANIMATION_WINDOW_MS = 5_000;
|
|
14
|
+
/** ssh2 认证超时(毫秒) */
|
|
15
|
+
export const READY_TIMEOUT_MS = 10_000;
|
|
16
|
+
/** PTY 窗口尺寸(大窗口减少分页) */
|
|
17
|
+
export const PTY_ROWS = 200;
|
|
18
|
+
export const PTY_COLS = 500;
|
|
19
|
+
/** 单次工具返回输出上限(字节) */
|
|
20
|
+
export const MAX_OUTPUT_LEN = 50_000;
|
|
21
|
+
/** 工具描述语言环境变量(en | zh,默认 en) */
|
|
22
|
+
export const LANG_ENV = "SSH_TOOL_LANG";
|
|
23
|
+
/** 插件缓存根目录(历史消息对存文件,随会话清理) */
|
|
24
|
+
export const CACHE_DIR = ".opencode/plugins-cache/opencode-ssh-tool";
|
|
25
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAEhC,kCAAkC;AAClC,MAAM,CAAC,MAAM,cAAc,GACzB,mHAAmH,CAAA;AAErH,6BAA6B;AAC7B,MAAM,CAAC,MAAM,IAAI,GACf,ylBAAylB,CAAA;AAE3lB,qCAAqC;AACrC,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAA;AAEvC,2BAA2B;AAC3B,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAA;AAErC,+BAA+B;AAC/B,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAA;AAElC,uCAAuC;AACvC,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,CAAA;AAExC,oBAAoB;AACpB,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAA;AAEtC,wBAAwB;AACxB,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,CAAA;AAC3B,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,CAAA;AAE3B,qBAAqB;AACrB,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAA;AAEpC,gCAAgC;AAChC,MAAM,CAAC,MAAM,QAAQ,GAAG,eAAe,CAAA;AAEvC,8BAA8B;AAC9B,MAAM,CAAC,MAAM,SAAS,GAAG,2CAA2C,CAAA"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** 消息对元数据(输出存文件,内存只存引用) */
|
|
2
|
+
export interface HistoryPair {
|
|
3
|
+
command: string;
|
|
4
|
+
/** 输出文件路径(持久化) */
|
|
5
|
+
file: string;
|
|
6
|
+
size: number;
|
|
7
|
+
ts: number;
|
|
8
|
+
/** 序号(文件顺序) */
|
|
9
|
+
seq: number;
|
|
10
|
+
}
|
|
11
|
+
/** 消息对存储:目录 <cacheRoot>/<sessionID>/,每对一文件,超对数删最旧 */
|
|
12
|
+
export declare class SessionHistory {
|
|
13
|
+
private readonly maxMessages;
|
|
14
|
+
private pairs;
|
|
15
|
+
private readonly dir;
|
|
16
|
+
private nextSeq;
|
|
17
|
+
/**
|
|
18
|
+
* @param cacheRoot 插件缓存根目录(如 ~/.opencode/plugins-cache/opencode-ssh-tool)
|
|
19
|
+
* @param sessionID opencode 会话 ID(用作子目录名)
|
|
20
|
+
* @param maxMessages 保留消息对数(最小 1,保留最新)
|
|
21
|
+
*/
|
|
22
|
+
constructor(cacheRoot: string, sessionID: string, maxMessages: number);
|
|
23
|
+
/** 从已有文件恢复索引(重启同 sessionID 可恢复历史) */
|
|
24
|
+
private _restore;
|
|
25
|
+
/**
|
|
26
|
+
* 追加一条命令+输出对(写文件),超对数移除最旧
|
|
27
|
+
* @param command 命令
|
|
28
|
+
* @param output 输出
|
|
29
|
+
*/
|
|
30
|
+
append(command: string, output: string): void;
|
|
31
|
+
/** 超对数:删除最旧文件并移除索引 */
|
|
32
|
+
private _trim;
|
|
33
|
+
/**
|
|
34
|
+
* 当前保留的所有消息对(旧→新)
|
|
35
|
+
* @returns 消息对数组
|
|
36
|
+
*/
|
|
37
|
+
getPairs(): HistoryPair[];
|
|
38
|
+
/**
|
|
39
|
+
* 读取某对输出(从文件)
|
|
40
|
+
* @param pair 消息对
|
|
41
|
+
* @returns 输出文本
|
|
42
|
+
*/
|
|
43
|
+
readOutput(pair: HistoryPair): string;
|
|
44
|
+
/**
|
|
45
|
+
* 当前消息对数
|
|
46
|
+
* @returns 对数
|
|
47
|
+
*/
|
|
48
|
+
totalPairs(): number;
|
|
49
|
+
/**
|
|
50
|
+
* 会话关闭:删除整个会话目录(含所有消息文件)
|
|
51
|
+
*/
|
|
52
|
+
dispose(): void;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"AAKA,2BAA2B;AAC3B,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,kBAAkB;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,eAAe;IACf,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,qDAAqD;AACrD,qBAAa,cAAc;IAavB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAZ9B,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,OAAO,CAAI;IAEnB;;;;OAIG;IACH,YACE,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACA,WAAW,EAAE,MAAM,EAKrC;IAED,qCAAqC;IACrC,OAAO,CAAC,QAAQ;IA2BhB;;;;OAIG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAO5C;IAED,sBAAsB;IACtB,OAAO,CAAC,KAAK;IAab;;;OAGG;IACH,QAAQ,IAAI,WAAW,EAAE,CAExB;IAED;;;;OAIG;IACH,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAOpC;IAED;;;OAGG;IACH,UAAU,IAAI,MAAM,CAEnB;IAED;;OAEG;IACH,OAAO,IAAI,IAAI,CAMd;CACF"}
|
package/dist/history.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// 会话记录存储:命令+输出 消息对,全部存文件(持久化,重启不丢),按对数限制
|
|
2
|
+
import { mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
/** 消息对存储:目录 <cacheRoot>/<sessionID>/,每对一文件,超对数删最旧 */
|
|
5
|
+
export class SessionHistory {
|
|
6
|
+
maxMessages;
|
|
7
|
+
pairs = [];
|
|
8
|
+
dir;
|
|
9
|
+
nextSeq = 1;
|
|
10
|
+
/**
|
|
11
|
+
* @param cacheRoot 插件缓存根目录(如 ~/.opencode/plugins-cache/opencode-ssh-tool)
|
|
12
|
+
* @param sessionID opencode 会话 ID(用作子目录名)
|
|
13
|
+
* @param maxMessages 保留消息对数(最小 1,保留最新)
|
|
14
|
+
*/
|
|
15
|
+
constructor(cacheRoot, sessionID, maxMessages) {
|
|
16
|
+
this.maxMessages = maxMessages;
|
|
17
|
+
this.dir = join(cacheRoot, sessionID);
|
|
18
|
+
mkdirSync(this.dir, { recursive: true });
|
|
19
|
+
this._restore();
|
|
20
|
+
}
|
|
21
|
+
/** 从已有文件恢复索引(重启同 sessionID 可恢复历史) */
|
|
22
|
+
_restore() {
|
|
23
|
+
let files;
|
|
24
|
+
try {
|
|
25
|
+
files = readdirSync(this.dir).filter((f) => f.endsWith(".json"));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
files = [];
|
|
29
|
+
}
|
|
30
|
+
files.sort();
|
|
31
|
+
for (const f of files) {
|
|
32
|
+
try {
|
|
33
|
+
const data = JSON.parse(readFileSync(join(this.dir, f), "utf8"));
|
|
34
|
+
const seq = parseInt(f.split("-")[0] ?? "0", 10) || this.nextSeq;
|
|
35
|
+
const size = data.output?.length ?? 0;
|
|
36
|
+
this.pairs.push({ command: data.command, file: join(this.dir, f), size, ts: data.ts, seq });
|
|
37
|
+
if (seq >= this.nextSeq)
|
|
38
|
+
this.nextSeq = seq + 1;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
/* 跳过损坏文件 */
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
this.pairs.sort((a, b) => a.seq - b.seq);
|
|
45
|
+
this._trim();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 追加一条命令+输出对(写文件),超对数移除最旧
|
|
49
|
+
* @param command 命令
|
|
50
|
+
* @param output 输出
|
|
51
|
+
*/
|
|
52
|
+
append(command, output) {
|
|
53
|
+
const ts = Date.now();
|
|
54
|
+
const seq = this.nextSeq++;
|
|
55
|
+
const file = join(this.dir, `${String(seq).padStart(6, "0")}-${ts}.json`);
|
|
56
|
+
writeFileSync(file, JSON.stringify({ command, output, ts }), "utf8");
|
|
57
|
+
this.pairs.push({ command, file, size: output.length, ts, seq });
|
|
58
|
+
this._trim();
|
|
59
|
+
}
|
|
60
|
+
/** 超对数:删除最旧文件并移除索引 */
|
|
61
|
+
_trim() {
|
|
62
|
+
while (this.pairs.length > Math.max(1, this.maxMessages)) {
|
|
63
|
+
const oldest = this.pairs.shift();
|
|
64
|
+
if (oldest) {
|
|
65
|
+
try {
|
|
66
|
+
rmSync(oldest.file, { force: true });
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
/* 忽略 */
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* 当前保留的所有消息对(旧→新)
|
|
76
|
+
* @returns 消息对数组
|
|
77
|
+
*/
|
|
78
|
+
getPairs() {
|
|
79
|
+
return [...this.pairs];
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* 读取某对输出(从文件)
|
|
83
|
+
* @param pair 消息对
|
|
84
|
+
* @returns 输出文本
|
|
85
|
+
*/
|
|
86
|
+
readOutput(pair) {
|
|
87
|
+
try {
|
|
88
|
+
const data = JSON.parse(readFileSync(pair.file, "utf8"));
|
|
89
|
+
return data.output ?? "";
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return `[cannot read history file: ${pair.file}]`;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* 当前消息对数
|
|
97
|
+
* @returns 对数
|
|
98
|
+
*/
|
|
99
|
+
totalPairs() {
|
|
100
|
+
return this.pairs.length;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* 会话关闭:删除整个会话目录(含所有消息文件)
|
|
104
|
+
*/
|
|
105
|
+
dispose() {
|
|
106
|
+
try {
|
|
107
|
+
rmSync(this.dir, { recursive: true, force: true });
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
/* 忽略 */
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.js","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"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"}
|