@stardustlc/dsh-docker 0.3.4 → 0.4.1
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 +19 -0
- package/README.en.md +23 -67
- package/README.md +22 -64
- package/docs/USAGE.en.md +79 -0
- package/docs/USAGE.md +79 -0
- package/docs/VALIDATION.md +13 -0
- package/lib/args.js +55 -4
- package/lib/exec.js +2 -0
- package/lib/index.js +1 -1
- package/lib/tools.js +12 -5
- package/package.json +5 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# 更新记录
|
|
2
|
+
|
|
3
|
+
[返回简介](README.md) · [使用说明](docs/USAGE.md) · [验证记录](docs/VALIDATION.md)
|
|
4
|
+
|
|
5
|
+
## 0.4.1 (2026-10-05)
|
|
6
|
+
|
|
7
|
+
- 修复旧版 DSH 生成 PTC SDK 时不支持的数组约束;仍在执行前严格限制 argv 的 128 项与总长度,保留精确参数和审批。
|
|
8
|
+
|
|
9
|
+
## 0.4.0 (2026-10-05)
|
|
10
|
+
|
|
11
|
+
- docker_exec 增加 argv 精确参数数组,修复空参数、相邻引号与转义;拒绝未闭合命令,并在启动前处理取消。argv 同样显示完整审批内容。
|
|
12
|
+
|
|
13
|
+
## 0.3.4 (2026-09-28)
|
|
14
|
+
|
|
15
|
+
- 更新官方 Harness 0.2.0-rc.1 的兼容声明和共同加载验证;运行时代码未变。验证范围见[验证记录](docs/VALIDATION.md)。
|
|
16
|
+
|
|
17
|
+
## 更早的改动
|
|
18
|
+
|
|
19
|
+
完整历史可查阅 [GitHub 提交记录](https://github.com/STARDUSTLC666/dsh-docker/commits/master)。
|
package/README.en.md
CHANGED
|
@@ -1,90 +1,46 @@
|
|
|
1
|
-
[中文](README.md)
|
|
2
|
-
|
|
3
1
|
# dsh-docker
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
[中文](README.md)
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+

|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
Inspect and manage local Docker containers and images from DSH.
|
|
10
8
|
|
|
11
|
-
[](https://www.npmjs.com/package/@stardustlc/dsh-docker) [](https://www.npmjs.com/package/@stardustlc/dsh-docker)
|
|
12
10
|
|
|
13
|
-
##
|
|
11
|
+
## What it does
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
- Inspect containers, images, logs and resource status.
|
|
14
|
+
- Run container commands and common management operations.
|
|
15
|
+
- Keep execution and destructive operations under host approval.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
## Install
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
In DSH Desktop, install `@stardustlc/dsh-docker` from the Plugins panel. If the bundled dsh command is available:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
dsh plugin --profile
|
|
22
|
+
dsh plugin --profile desktop add @stardustlc/dsh-docker
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
For the web version, replace `desktop` with `web`. Restart DSH after installation.
|
|
26
26
|
|
|
27
|
-
##
|
|
27
|
+
## Start using it
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
dsh plugin --profile web remove @stardustlc/dsh-docker
|
|
31
|
-
```
|
|
29
|
+
Ask: “Find out why this container exited. Start with its status and logs.”
|
|
32
30
|
|
|
33
|
-
|
|
31
|
+
## Requirements and configuration
|
|
34
32
|
|
|
33
|
+
Requires an accessible Docker CLI and Docker daemon.
|
|
35
34
|
|
|
36
|
-
|
|
35
|
+
Detailed configuration, tool arguments and troubleshooting are in the [usage guide](docs/USAGE.en.md). For standalone development, follow the Node requirement in [package.json](package.json).
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
- id: docker
|
|
40
|
-
name: '@stardustlc/dsh-docker'
|
|
41
|
-
config:
|
|
42
|
-
# dockerPath: C:\Program Files\Docker\Docker\resources\bin\docker.exe
|
|
43
|
-
dockerPath: docker # optional; or use the DSH_DOCKER_PATH env var
|
|
44
|
-
timeoutMs: 60000 # per-operation timeout (default 60s, 5s - 10min)
|
|
45
|
-
# execApproval: false # disable the docker_exec approval gate (default true)
|
|
46
|
-
# manageApproval: false # disable approval for stop/restart/rm (default true; not recommended)
|
|
47
|
-
```
|
|
37
|
+
## Documentation
|
|
48
38
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
| `docker_ps` | List containers (status/image/state, filterable) | — |
|
|
54
|
-
| `docker_images` | List local images (repository/tag/size/created, dangling-only filter) | — |
|
|
55
|
-
| `docker_logs` | Tail container logs (line clamp, short follow) | — |
|
|
56
|
-
| `docker_inspect` | Container details (image/state/ports) | — |
|
|
57
|
-
| `docker_exec` | Run a command inside a container | Approval gate + container-name validation |
|
|
58
|
-
| `docker_manage` | start / stop / restart / rm | Approval gate for stop/restart/rm |
|
|
59
|
-
| `docker_health` | Check Docker daemon and safety settings | — |
|
|
60
|
-
|
|
61
|
-
### Examples
|
|
62
|
-
|
|
63
|
-
```text
|
|
64
|
-
docker_ps {}
|
|
65
|
-
docker_ps { all: true, name: web }
|
|
66
|
-
docker_images { dangling: true }
|
|
67
|
-
docker_logs { container: web, tail: 200 }
|
|
68
|
-
docker_inspect { container: web }
|
|
69
|
-
docker_exec { container: web, command: 'df -h' }
|
|
70
|
-
docker_manage { container: web, action: restart }
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## Safety
|
|
74
|
-
|
|
75
|
-
- **No shell**: every argument is its own argv element — command injection is impossible
|
|
76
|
-
- **Approval gates**: docker_exec and docker_manage stop/restart/rm ask first; headless environments without an approval channel are denied
|
|
77
|
-
- **Container-name validation**: only `[A-Za-z0-9][A-Za-z0-9_.:-]*` accepted — no argument injection
|
|
78
|
-
- **Timeout clamps**: 5s - 10min per operation; follow mode capped at an extra 30s
|
|
79
|
-
- **Log clamping**: tail 1-2000 lines
|
|
80
|
-
|
|
81
|
-
## Development
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
pnpm install
|
|
85
|
-
pnpm test # build + 35 tests
|
|
86
|
-
```
|
|
39
|
+
- [Usage and troubleshooting](docs/USAGE.en.md)
|
|
40
|
+
- [Changelog](CHANGELOG.md)
|
|
41
|
+
- [Validation scope and history](docs/VALIDATION.md)
|
|
42
|
+
- [Report a problem or suggest a feature](https://github.com/STARDUSTLC666/dsh-docker/issues)
|
|
87
43
|
|
|
88
44
|
## License
|
|
89
45
|
|
|
90
|
-
MIT
|
|
46
|
+
[MIT](LICENSE)
|
package/README.md
CHANGED
|
@@ -1,88 +1,46 @@
|
|
|
1
|
-
[English](README.en.md)
|
|
2
|
-
|
|
3
1
|
# dsh-docker
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
[English](README.en.md)
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+

|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
在 DSH 中查看和管理本机 Docker 容器与镜像。
|
|
10
8
|
|
|
11
|
-
[](https://www.npmjs.com/package/@stardustlc/dsh-docker) [](https://www.npmjs.com/package/@stardustlc/dsh-docker)
|
|
12
10
|
|
|
13
|
-
##
|
|
11
|
+
## 功能
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
- 查看容器、镜像、日志和资源状态。
|
|
14
|
+
- 运行容器内命令,执行常用管理操作。
|
|
15
|
+
- 执行和破坏性操作遵循宿主审批。
|
|
16
16
|
|
|
17
17
|
## 安装
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
dsh plugin --profile web add @stardustlc/dsh-docker
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
需要本机装有 Docker(`docker version` 能出结果即可);不在 PATH 上时用 `dockerPath` 指定。
|
|
24
|
-
|
|
25
|
-
## 卸载
|
|
19
|
+
桌面版可在「插件」面板按包名 `@stardustlc/dsh-docker` 安装。已配置 dsh 命令时也可使用:
|
|
26
20
|
|
|
27
21
|
```bash
|
|
28
|
-
dsh plugin --profile
|
|
22
|
+
dsh plugin --profile desktop add @stardustlc/dsh-docker
|
|
29
23
|
```
|
|
30
24
|
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
网页版把命令中的 `desktop` 改为 `web`。安装后重启 DSH。
|
|
33
26
|
|
|
34
|
-
##
|
|
27
|
+
## 开始使用
|
|
35
28
|
|
|
36
|
-
|
|
37
|
-
- id: docker
|
|
38
|
-
name: '@stardustlc/dsh-docker'
|
|
39
|
-
config:
|
|
40
|
-
# dockerPath: C:\Program Files\Docker\Docker\resources\bin\docker.exe
|
|
41
|
-
dockerPath: docker # 可选;也可用环境变量 DSH_DOCKER_PATH
|
|
42
|
-
timeoutMs: 60000 # 单次操作超时(默认 60 秒,5 秒 - 10 分钟)
|
|
43
|
-
# execApproval: false # 关闭 docker_exec 审批门(默认 true)
|
|
44
|
-
# manageApproval: false # 关闭 stop/restart/rm 审批门(默认 true,不推荐)
|
|
45
|
-
```
|
|
29
|
+
安装后可说:“检查这个容器为什么退出,先查看状态和日志。”
|
|
46
30
|
|
|
47
|
-
##
|
|
48
|
-
|
|
49
|
-
| 工具 | 作用 | 安全 |
|
|
50
|
-
| :-- | :-- | :-- |
|
|
51
|
-
| `docker_ps` | 列出容器(状态/镜像/运行态,可过滤)| — |
|
|
52
|
-
| `docker_images` | 列出本地镜像(仓库/标签/大小/创建时间,可只看悬空镜像)| — |
|
|
53
|
-
| `docker_logs` | 查看日志尾部(行数钳制,可短时 follow)| — |
|
|
54
|
-
| `docker_inspect` | 容器详情(镜像/状态/端口)| — |
|
|
55
|
-
| `docker_exec` | 容器内执行命令 | 审批门 + 容器名白名单校验 |
|
|
56
|
-
| `docker_manage` | start / stop / restart / rm | stop/restart/rm 审批门 |
|
|
57
|
-
| `docker_health` | Docker daemon 与安全配置自检 | — |
|
|
58
|
-
|
|
59
|
-
### 示例
|
|
60
|
-
|
|
61
|
-
```text
|
|
62
|
-
docker_ps {}
|
|
63
|
-
docker_ps { all: true, name: web }
|
|
64
|
-
docker_images { dangling: true }
|
|
65
|
-
docker_logs { container: web, tail: 200 }
|
|
66
|
-
docker_inspect { container: web }
|
|
67
|
-
docker_exec { container: web, command: 'df -h' }
|
|
68
|
-
docker_manage { container: web, action: restart }
|
|
69
|
-
```
|
|
31
|
+
## 依赖与配置
|
|
70
32
|
|
|
71
|
-
|
|
33
|
+
需要已安装且可访问的 Docker CLI 与 Docker 服务。
|
|
72
34
|
|
|
73
|
-
|
|
74
|
-
- **审批门**:docker_exec 与 docker_manage 的 stop/restart/rm 默认弹审批;headless 无审批通道时拒绝
|
|
75
|
-
- **容器名校验**:只允许 `[A-Za-z0-9][A-Za-z0-9_.:-]*`,杜绝参数注入
|
|
76
|
-
- **超时钳制**:单次操作 5 秒 - 10 分钟;follow 模式额外限 30 秒
|
|
77
|
-
- **日志钳制**:tail 1-2000 行
|
|
35
|
+
详细配置、工具参数与排错见[使用说明](docs/USAGE.md)。从源码独立开发时,Node 要求以 [package.json](package.json) 为准。
|
|
78
36
|
|
|
79
|
-
##
|
|
37
|
+
## 文档
|
|
80
38
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
39
|
+
- [使用与排错](docs/USAGE.md)
|
|
40
|
+
- [更新记录](CHANGELOG.md)
|
|
41
|
+
- [验证范围与历史记录](docs/VALIDATION.md)
|
|
42
|
+
- [问题反馈与功能建议](https://github.com/STARDUSTLC666/dsh-docker/issues)
|
|
85
43
|
|
|
86
44
|
## License
|
|
87
45
|
|
|
88
|
-
MIT
|
|
46
|
+
[MIT](LICENSE)
|
package/docs/USAGE.en.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# dsh-docker usage guide
|
|
2
|
+
|
|
3
|
+
[Overview](../README.en.md) · [Changelog](../CHANGELOG.md) · [Validation](VALIDATION.md)
|
|
4
|
+
|
|
5
|
+
## Current improvements
|
|
6
|
+
|
|
7
|
+
Prefer docker_exec with container="web" and argv=["printf","%s","a b"]. Supply exactly one of command or argv. The host performs no variable, pipe or command-substitution expansion. Explicit container shell calls such as ["sh","-c","..."] remain approval-gated.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
dsh plugin --profile web add @stardustlc/dsh-docker
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Requires Docker installed locally (`docker version` should work); use `dockerPath` when it is not on PATH.
|
|
16
|
+
|
|
17
|
+
## Uninstall
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
dsh plugin --profile web remove @stardustlc/dsh-docker
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Then restart the web service. To clean up fully, also remove the plugin entry from your profile `cordis.patch.yml` if you overrode it.
|
|
24
|
+
|
|
25
|
+
## Configuration
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
- id: docker
|
|
29
|
+
name: '@stardustlc/dsh-docker'
|
|
30
|
+
config:
|
|
31
|
+
# dockerPath: C:\Program Files\Docker\Docker\resources\bin\docker.exe
|
|
32
|
+
dockerPath: docker # optional; or use the DSH_DOCKER_PATH env var
|
|
33
|
+
timeoutMs: 60000 # per-operation timeout (default 60s, 5s - 10min)
|
|
34
|
+
# execApproval: false # disable the docker_exec approval gate (default true)
|
|
35
|
+
# manageApproval: false # disable approval for stop/restart/rm (default true; not recommended)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Tools
|
|
39
|
+
|
|
40
|
+
| Tool | Purpose | Safety |
|
|
41
|
+
| :-- | :-- | :-- |
|
|
42
|
+
| `docker_ps` | List containers (status/image/state, filterable) | — |
|
|
43
|
+
| `docker_images` | List local images (repository/tag/size/created, dangling-only filter) | — |
|
|
44
|
+
| `docker_logs` | Tail container logs (line clamp, short follow) | — |
|
|
45
|
+
| `docker_inspect` | Container details (image/state/ports) | — |
|
|
46
|
+
| `docker_exec` | Run a command inside a container | Approval gate + container-name validation |
|
|
47
|
+
| `docker_manage` | start / stop / restart / rm | Approval gate for stop/restart/rm |
|
|
48
|
+
| `docker_health` | Check Docker daemon and safety settings | — |
|
|
49
|
+
|
|
50
|
+
### Examples
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
docker_ps {}
|
|
54
|
+
docker_ps { all: true, name: web }
|
|
55
|
+
docker_images { dangling: true }
|
|
56
|
+
docker_logs { container: web, tail: 200 }
|
|
57
|
+
docker_inspect { container: web }
|
|
58
|
+
docker_exec { container: web, command: 'df -h' }
|
|
59
|
+
docker_manage { container: web, action: restart }
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Safety
|
|
63
|
+
|
|
64
|
+
- **No shell concatenation**: arguments are passed separately to Docker CLI rather than combined into a shell command.
|
|
65
|
+
- **Approval gates**: docker_exec and docker_manage stop/restart/rm ask first; headless environments without an approval channel are denied
|
|
66
|
+
- **Container-name validation**: only `[A-Za-z0-9][A-Za-z0-9_.:-]*` accepted — no argument injection
|
|
67
|
+
- **Timeout clamps**: 5s - 10min per operation; follow mode capped at an extra 30s
|
|
68
|
+
- **Log clamping**: tail 1-2000 lines
|
|
69
|
+
|
|
70
|
+
## Development
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
pnpm install
|
|
74
|
+
pnpm test # build + 35 tests
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT
|
package/docs/USAGE.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# dsh-docker 使用说明
|
|
2
|
+
|
|
3
|
+
[返回简介](../README.md) · [更新记录](../CHANGELOG.md) · [验证记录](VALIDATION.md)
|
|
4
|
+
|
|
5
|
+
## 本次改进
|
|
6
|
+
|
|
7
|
+
推荐 docker_exec { container: "web", argv: ["printf", "%s", "a b"] }。command 与 argv 二选一;宿主不执行变量、管道或命令替换。确需容器 Shell 时显式使用 ["sh", "-c", "..."],仍需审批。
|
|
8
|
+
|
|
9
|
+
## 安装
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
dsh plugin --profile web add @stardustlc/dsh-docker
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
需要本机装有 Docker(`docker version` 能出结果即可);不在 PATH 上时用 `dockerPath` 指定。
|
|
16
|
+
|
|
17
|
+
## 卸载
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
dsh plugin --profile web remove @stardustlc/dsh-docker
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
卸载后重启 Web 服务。如需彻底清理,可再手动删除自己 profile `cordis.patch.yml` 中覆盖的插件行。
|
|
24
|
+
|
|
25
|
+
## 配置
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
- id: docker
|
|
29
|
+
name: '@stardustlc/dsh-docker'
|
|
30
|
+
config:
|
|
31
|
+
# dockerPath: C:\Program Files\Docker\Docker\resources\bin\docker.exe
|
|
32
|
+
dockerPath: docker # 可选;也可用环境变量 DSH_DOCKER_PATH
|
|
33
|
+
timeoutMs: 60000 # 单次操作超时(默认 60 秒,5 秒 - 10 分钟)
|
|
34
|
+
# execApproval: false # 关闭 docker_exec 审批门(默认 true)
|
|
35
|
+
# manageApproval: false # 关闭 stop/restart/rm 审批门(默认 true,不推荐)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## 工具一览
|
|
39
|
+
|
|
40
|
+
| 工具 | 作用 | 安全 |
|
|
41
|
+
| :-- | :-- | :-- |
|
|
42
|
+
| `docker_ps` | 列出容器(状态/镜像/运行态,可过滤)| — |
|
|
43
|
+
| `docker_images` | 列出本地镜像(仓库/标签/大小/创建时间,可只看悬空镜像)| — |
|
|
44
|
+
| `docker_logs` | 查看日志尾部(行数钳制,可短时 follow)| — |
|
|
45
|
+
| `docker_inspect` | 容器详情(镜像/状态/端口)| — |
|
|
46
|
+
| `docker_exec` | 容器内执行命令 | 审批门 + 容器名白名单校验 |
|
|
47
|
+
| `docker_manage` | start / stop / restart / rm | stop/restart/rm 审批门 |
|
|
48
|
+
| `docker_health` | Docker daemon 与安全配置自检 | — |
|
|
49
|
+
|
|
50
|
+
### 示例
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
docker_ps {}
|
|
54
|
+
docker_ps { all: true, name: web }
|
|
55
|
+
docker_images { dangling: true }
|
|
56
|
+
docker_logs { container: web, tail: 200 }
|
|
57
|
+
docker_inspect { container: web }
|
|
58
|
+
docker_exec { container: web, command: 'df -h' }
|
|
59
|
+
docker_manage { container: web, action: restart }
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## 安全设计
|
|
63
|
+
|
|
64
|
+
- **无 shell 拼接**:参数通过独立 argv 传入 Docker CLI,避免由插件拼接 shell 命令。
|
|
65
|
+
- **审批门**:docker_exec 与 docker_manage 的 stop/restart/rm 默认弹审批;headless 无审批通道时拒绝
|
|
66
|
+
- **容器名校验**:只允许 `[A-Za-z0-9][A-Za-z0-9_.:-]*`,杜绝参数注入
|
|
67
|
+
- **超时钳制**:单次操作 5 秒 - 10 分钟;follow 模式额外限 30 秒
|
|
68
|
+
- **日志钳制**:tail 1-2000 行
|
|
69
|
+
|
|
70
|
+
## 开发
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
pnpm install
|
|
74
|
+
pnpm test # 构建并执行测试
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# dsh-docker 验证记录
|
|
2
|
+
|
|
3
|
+
本页整理原 README 的历史验证说明,保留当时的版本、日期与范围。自动测试、启动检查、浏览器操作和真实服务验收分别记录,不能相互替代。更详细的版本验收文件仍保留在仓库中。
|
|
4
|
+
|
|
5
|
+
## 原中文记录
|
|
6
|
+
|
|
7
|
+
验证宿主:官方源码构建的 Harness `0.2.0-rc.1`(commit `407e65c8`)+ Node `24.16.0`(2026-09-28)。36 项插件测试在隔离环境全部通过;同一个宿主里 18 个插件共同加载,注册 7 个工具,工具 schema 与健康检查契约通过。本轮未启用真实端口与外部服务。
|
|
8
|
+
|
|
9
|
+
## Original English record
|
|
10
|
+
|
|
11
|
+
Validation host: Harness `0.2.0-rc.1` built from official sources (commit `407e65c8`) with Node `24.16.0` on 2026-09-28. All 36 plugin tests pass in an isolated environment; all 18 plugins mount together in one host registering 7 tools, with tool schemas and health-check contracts passing. No live ports or external services were exercised in this round.
|
|
12
|
+
|
|
13
|
+
2026-09-13 fix: retain the service receiver when calling `subprocess.spawn`, preventing failures caused by passing the method as an unbound callback. Verified against a real isolated host subprocess service. `docker_ps` passes through the real host subprocess service with a Node child producing fixed Docker output. A live Docker daemon was not used.
|
package/lib/args.js
CHANGED
|
@@ -36,9 +36,60 @@ export function manageArgs(docker, action, container) {
|
|
|
36
36
|
}
|
|
37
37
|
/** 拆分 exec 的命令字符串(按空白,支持引号)。 */
|
|
38
38
|
export function splitCommand(command) {
|
|
39
|
+
if (command.length > 32768 || command.includes('\0'))
|
|
40
|
+
throw new Error('命令超过 32768 字符或含 NUL;请检查输入。');
|
|
39
41
|
const parts = [];
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
let token = '', started = false, quote = '';
|
|
43
|
+
for (let i = 0; i < command.length; i++) {
|
|
44
|
+
const ch = command[i];
|
|
45
|
+
if (quote === "'") {
|
|
46
|
+
if (ch === "'")
|
|
47
|
+
quote = '';
|
|
48
|
+
else
|
|
49
|
+
token += ch;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (ch === '\\' && quote !== "'") {
|
|
53
|
+
const next = command[i + 1];
|
|
54
|
+
if (next === undefined)
|
|
55
|
+
throw new Error('命令末尾的转义未完成,请使用 argv 传递原始参数。');
|
|
56
|
+
if (quote === '"' && !['"', '\\', '$', '`', '\n'].includes(next))
|
|
57
|
+
token += ch;
|
|
58
|
+
else {
|
|
59
|
+
i++;
|
|
60
|
+
if (next !== '\n')
|
|
61
|
+
token += next;
|
|
62
|
+
}
|
|
63
|
+
started = true;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (quote === '"') {
|
|
67
|
+
if (ch === '"')
|
|
68
|
+
quote = '';
|
|
69
|
+
else
|
|
70
|
+
token += ch;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (ch === '"' || ch === "'") {
|
|
74
|
+
quote = ch;
|
|
75
|
+
started = true;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (/\s/.test(ch)) {
|
|
79
|
+
if (started) {
|
|
80
|
+
parts.push(token);
|
|
81
|
+
token = '';
|
|
82
|
+
started = false;
|
|
83
|
+
}
|
|
84
|
+
;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
token += ch;
|
|
88
|
+
started = true;
|
|
89
|
+
}
|
|
90
|
+
if (quote)
|
|
91
|
+
throw new Error('命令引号未闭合,请修正或使用 argv 参数数组。');
|
|
92
|
+
if (started)
|
|
93
|
+
parts.push(token);
|
|
94
|
+
return parts;
|
|
44
95
|
}
|
package/lib/exec.js
CHANGED
|
@@ -17,6 +17,7 @@ export function createSubprocessRunner(spawn, graceMs, defaultTimeoutMs) {
|
|
|
17
17
|
: AbortSignal.any([options.signal, controller.signal]);
|
|
18
18
|
let handle;
|
|
19
19
|
try {
|
|
20
|
+
signal.throwIfAborted();
|
|
20
21
|
handle = spawn({
|
|
21
22
|
argv,
|
|
22
23
|
cwd: process.cwd(),
|
|
@@ -29,6 +30,7 @@ export function createSubprocessRunner(spawn, graceMs, defaultTimeoutMs) {
|
|
|
29
30
|
signal,
|
|
30
31
|
});
|
|
31
32
|
const outcome = await handle.done;
|
|
33
|
+
signal.throwIfAborted();
|
|
32
34
|
const stdout = handle.collected.stdout?.readFrom(0).text ?? '';
|
|
33
35
|
const stderr = handle.collected.stderr?.readFrom(0).text ?? '';
|
|
34
36
|
return { exitCode: outcome.exitCode, signal: outcome.signal, stdout, stderr };
|
package/lib/index.js
CHANGED
|
@@ -24,7 +24,7 @@ export function apply(ctx, config) {
|
|
|
24
24
|
ctx.on('tools/pre-execute', async (exec, next) => {
|
|
25
25
|
const args = (typeof exec.arguments === 'object' && exec.arguments !== null ? exec.arguments : {});
|
|
26
26
|
if (exec.name === 'docker_exec' && cfg.execApproval) {
|
|
27
|
-
const command = typeof args.command === 'string' ? args.command : '';
|
|
27
|
+
const command = Array.isArray(args.argv) ? JSON.stringify(args.argv) : typeof args.command === 'string' ? args.command : '';
|
|
28
28
|
const container = typeof args.container === 'string' ? args.container : '';
|
|
29
29
|
return {
|
|
30
30
|
kind: 'ask',
|
package/lib/tools.js
CHANGED
|
@@ -18,6 +18,8 @@ function compileParameters(spec) {
|
|
|
18
18
|
node.type = prop.type;
|
|
19
19
|
if (typeof prop?.description === 'string')
|
|
20
20
|
node.description = prop.description;
|
|
21
|
+
if (prop?.items)
|
|
22
|
+
node.items = prop.items;
|
|
21
23
|
properties[key] = node;
|
|
22
24
|
}
|
|
23
25
|
return { type: 'object', properties, ...(required.length > 0 ? { required } : {}) };
|
|
@@ -42,7 +44,9 @@ function executionSignal(exec) {
|
|
|
42
44
|
return signal instanceof AbortSignal ? signal : undefined;
|
|
43
45
|
}
|
|
44
46
|
async function runChecked(runner, argv, timeoutMs, label, signal) {
|
|
47
|
+
signal?.throwIfAborted();
|
|
45
48
|
const result = await runner.run(argv, { timeoutMs, ...(signal === undefined ? {} : { signal }) });
|
|
49
|
+
signal?.throwIfAborted();
|
|
46
50
|
if (result.exitCode !== 0) {
|
|
47
51
|
const tail = result.stderr.trim().split(/\r?\n/).slice(-6).join(' | ');
|
|
48
52
|
throw new Error(label + '失败(退出码 ' + String(result.exitCode ?? 'null') + '):' + (tail || '无错误输出') + '。请确认 docker 可用(docker version)。');
|
|
@@ -195,10 +199,11 @@ export function buildDockerTools(config, runner) {
|
|
|
195
199
|
};
|
|
196
200
|
const dockerExec = {
|
|
197
201
|
name: 'docker_exec',
|
|
198
|
-
description: '在容器内执行命令(默认走审批门)。command
|
|
202
|
+
description: '在容器内执行命令(默认走审批门)。command 或 argv 必须且只能提供一个。推荐 argv 参数数组,精确保留空格、引号和空参数;command 支持引号与转义。宿主不执行 Shell 展开。返回退出码与 stdout。',
|
|
199
203
|
parameters: compileParameters({
|
|
200
204
|
container: { type: 'string', required: true, description: '容器名或 ID(必填)。' },
|
|
201
|
-
command: { type: 'string',
|
|
205
|
+
command: { type: 'string', description: '命令字符串,如 ls -la;与 argv 二选一。' },
|
|
206
|
+
argv: { type: 'array', items: { type: 'string' }, description: '精确命令参数,最多 128 项,如 ["sh", "-c", "cat /etc/hosts"];与 command 二选一。' },
|
|
202
207
|
}),
|
|
203
208
|
output: {
|
|
204
209
|
schema: execSchema,
|
|
@@ -210,9 +215,11 @@ export function buildDockerTools(config, runner) {
|
|
|
210
215
|
async execute(rawArgs, exec) {
|
|
211
216
|
const args = asRecord(rawArgs);
|
|
212
217
|
const container = assertContainerRef(requiredString(args, 'container', '容器名'));
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
218
|
+
if ((args.command !== undefined) === (args.argv !== undefined))
|
|
219
|
+
throw new Error('command 与 argv 必须且只能提供一个。');
|
|
220
|
+
const command = args.argv !== undefined ? args.argv : splitCommand(requiredString(args, 'command', '命令'));
|
|
221
|
+
if (!Array.isArray(command) || command.length === 0 || command.length > 128 || command.some(part => typeof part !== 'string' || part.includes('\0')) || typeof command[0] !== 'string' || !command[0].trim() || command.reduce((size, part) => size + part.length, 0) > 32768)
|
|
222
|
+
throw new Error('命令参数无效:argv 需含 1–128 个字符串、首项非空、总长不超过 32768 字符且不含 NUL。');
|
|
216
223
|
const result = await runChecked(runner, execArgs(cfg.dockerPath, container, command), timeout, 'docker exec', executionSignal(exec));
|
|
217
224
|
return { container, exitCode: result.exitCode, stdout: result.stdout };
|
|
218
225
|
},
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stardustlc/dsh-docker",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "DSH
|
|
3
|
+
"version": "0.4.1",
|
|
4
|
+
"description": "在 DSH 中查看和管理本机 Docker 容器与镜像。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"types": "lib/index.d.ts",
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
"lib",
|
|
18
18
|
"cordis.patch.yml",
|
|
19
19
|
"README.md",
|
|
20
|
-
"README.en.md"
|
|
20
|
+
"README.en.md",
|
|
21
|
+
"docs",
|
|
22
|
+
"CHANGELOG.md"
|
|
21
23
|
],
|
|
22
24
|
"scripts": {
|
|
23
25
|
"build": "tsc -p tsconfig.json",
|