@xcanwin/manyoyo 5.3.5 → 5.3.7
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 +115 -87
- package/bin/manyoyo.js +11 -21
- package/lib/log-path.js +41 -0
- package/lib/web/server.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
# <p align="center"><a href="https://github.com/xcanwin/manyoyo">MANYOYO(慢悠悠)</a></p>
|
|
6
|
-
<p align="center"
|
|
6
|
+
<p align="center">面向 AI Agent CLI 的 Docker / Podman 安全沙箱。</p>
|
|
7
|
+
<p align="center">用于隔离 Claude Code、Codex、Gemini、OpenCode 等命令行智能体,降低宿主机风险,并保持可复现的运行环境。</p>
|
|
7
8
|
<p align="center">
|
|
8
9
|
<a href="https://www.npmjs.com/package/@xcanwin/manyoyo"><img alt="npm" src="https://img.shields.io/npm/v/@xcanwin/manyoyo?style=flat-square" /></a>
|
|
9
10
|
<a href="https://github.com/xcanwin/manyoyo/actions/workflows/npm-publish.yml"><img alt="Build status" src="https://img.shields.io/github/actions/workflow/status/xcanwin/manyoyo/npm-publish.yml?style=flat-square" /></a>
|
|
@@ -15,157 +16,183 @@
|
|
|
15
16
|
<a href="https://xcanwin.github.io/manyoyo/en/">English</a>
|
|
16
17
|
</p>
|
|
17
18
|
<p align="center">
|
|
18
|
-
|
|
19
|
+
文档:<a href="https://xcanwin.github.io/manyoyo/">https://xcanwin.github.io/manyoyo/</a>
|
|
19
20
|
</p>
|
|
20
21
|
|
|
21
22
|
---
|
|
22
23
|
|
|
23
|
-
##
|
|
24
|
+
## 为什么是 MANYOYO
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
AI Agent CLI 往往需要:
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
- 访问代码仓库
|
|
29
|
+
- 执行 shell 命令
|
|
30
|
+
- 读写文件
|
|
31
|
+
- 安装依赖或调用容器能力
|
|
28
32
|
|
|
29
|
-
|
|
33
|
+
直接在宿主机上裸跑这些工具,风险边界通常不清晰。**MANYOYO** 的目标不是替代容器平台,而是把常见 Agent CLI 的运行方式收敛到一个更清晰、可复现、可审计的沙箱入口。
|
|
30
34
|
|
|
31
|
-
|
|
35
|
+
你可以把它理解为:
|
|
32
36
|
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
- **便捷操作**:快速进入 `/bin/bash`
|
|
37
|
-
- **会话恢复**:安装 Skills Marketplace 可快速恢复会话
|
|
38
|
-
- **灵活自定义**:支持配置各 CLI 的 `*_BASE_URL` / `*_AUTH_TOKEN` / `*_API_KEY` 等变量
|
|
39
|
-
- **配置管理**:快捷导入配置文件
|
|
40
|
-
- **高级模式**:支持危险容器嵌套(mount-docker-socket)、自定义沙箱镜像
|
|
37
|
+
- 面向 Agent CLI 的运行包装层
|
|
38
|
+
- 面向团队协作的配置与镜像约定
|
|
39
|
+
- 面向高风险模式的显式边界说明
|
|
41
40
|
|
|
42
|
-
|
|
41
|
+
## 核心能力
|
|
42
|
+
|
|
43
|
+
- **多 Agent 支持**:支持 `claude`、`gemini`、`codex`、`opencode`
|
|
44
|
+
- **容器隔离**:基于 Docker / Podman 运行,降低宿主机暴露面
|
|
45
|
+
- **YOLO / SOLO 工作流**:适配跳过权限确认的高效率模式
|
|
46
|
+
- **统一配置入口**:集中管理 `runs.<name>`、环境变量、挂载与镜像参数
|
|
47
|
+
- **命令可预览**:支持查看配置合并结果与最终命令拼装
|
|
48
|
+
- **会话与 Web 模式**:支持容器会话管理与网页访问入口
|
|
49
|
+
- **镜像可定制**:支持 common / full / 自定义工具集镜像
|
|
43
50
|
|
|
44
51
|
## 快速开始
|
|
45
52
|
|
|
46
53
|
```bash
|
|
47
|
-
npm install -g @xcanwin/manyoyo
|
|
54
|
+
npm install -g @xcanwin/manyoyo
|
|
48
55
|
podman pull ubuntu:24.04 # 仅 Podman 需要
|
|
49
|
-
manyoyo build --iv 1.8.4-common
|
|
50
|
-
manyoyo init all
|
|
51
|
-
manyoyo run -r claude
|
|
56
|
+
manyoyo build --iv 1.8.4-common
|
|
57
|
+
manyoyo init all
|
|
58
|
+
manyoyo run -r claude
|
|
52
59
|
```
|
|
53
60
|
|
|
54
|
-
|
|
61
|
+
系统要求:
|
|
55
62
|
|
|
56
|
-
|
|
63
|
+
- Node.js >= 22
|
|
64
|
+
- Podman(推荐)或 Docker
|
|
57
65
|
|
|
58
|
-
|
|
66
|
+
注意:
|
|
59
67
|
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
|
|
63
|
-
|
|
68
|
+
- `YOLO / SOLO` 会跳过权限确认,只适合在可控环境中使用
|
|
69
|
+
- `sock` 模式会暴露宿主机 Docker socket,不属于强隔离
|
|
70
|
+
|
|
71
|
+
## 适合什么场景
|
|
72
|
+
|
|
73
|
+
- 在容器中运行 **Claude Code YOLO / SOLO**
|
|
74
|
+
- 为 **Codex CLI** 提供独立于宿主机的运行边界
|
|
75
|
+
- 隔离运行 **Gemini CLI / OpenCode** 的代码任务
|
|
76
|
+
- 用统一镜像和配置管理团队 Agent 环境
|
|
77
|
+
- 在调试和自动化任务中快速切换 Agent 与 `/bin/bash`
|
|
64
78
|
|
|
65
79
|
## 裸跑 vs MANYOYO
|
|
66
80
|
|
|
67
81
|
| 对比项 | 裸跑 Agent CLI | MANYOYO |
|
|
68
82
|
| --- | --- | --- |
|
|
69
|
-
|
|
|
70
|
-
|
|
|
71
|
-
|
|
|
72
|
-
|
|
|
83
|
+
| 宿主机暴露面 | 高 | 更低 |
|
|
84
|
+
| 运行边界 | 分散 | 集中到容器与配置 |
|
|
85
|
+
| 环境复现 | 弱 | 强(镜像 + 配置) |
|
|
86
|
+
| 高风险模式说明 | 通常依赖工具自身 | 明确提示 YOLO / SOLO / sock 风险 |
|
|
87
|
+
| 团队统一性 | 弱 | 更强 |
|
|
73
88
|
|
|
74
|
-
|
|
89
|
+
## 安全边界
|
|
75
90
|
|
|
76
|
-
|
|
91
|
+
MANYOYO 可以降低风险,但不是“绝对安全”:
|
|
77
92
|
|
|
78
|
-
-
|
|
79
|
-
-
|
|
93
|
+
- 它的主要隔离手段是容器,不是虚拟机
|
|
94
|
+
- `YOLO / SOLO` 仍然可能执行危险命令
|
|
95
|
+
- `sock` 模式本质上会把宿主机容器控制权暴露给容器
|
|
96
|
+
- 自定义挂载、环境变量和网络访问会直接影响实际安全边界
|
|
80
97
|
|
|
81
|
-
|
|
98
|
+
相关文档:
|
|
82
99
|
|
|
83
|
-
|
|
100
|
+
- [AI 智能体说明](https://xcanwin.github.io/manyoyo/zh/reference/agents)
|
|
101
|
+
- [容器模式说明](https://xcanwin.github.io/manyoyo/zh/reference/container-modes)
|
|
102
|
+
- [网页认证与安全](https://xcanwin.github.io/manyoyo/zh/advanced/web-server-auth)
|
|
103
|
+
|
|
104
|
+
## 常用命令
|
|
84
105
|
|
|
85
106
|
```bash
|
|
86
|
-
|
|
87
|
-
|
|
107
|
+
# 初始化与迁移
|
|
108
|
+
manyoyo init all
|
|
109
|
+
|
|
110
|
+
# 启动常见 Agent
|
|
111
|
+
manyoyo run -y c
|
|
112
|
+
manyoyo run -y gm
|
|
113
|
+
manyoyo run -y cx
|
|
114
|
+
manyoyo run -y oc
|
|
88
115
|
|
|
89
|
-
|
|
116
|
+
# 更新
|
|
117
|
+
manyoyo update
|
|
118
|
+
|
|
119
|
+
# 容器与调试
|
|
120
|
+
manyoyo ps
|
|
121
|
+
manyoyo images
|
|
122
|
+
manyoyo run -n my-dev -x /bin/bash
|
|
123
|
+
manyoyo rm my-dev
|
|
90
124
|
|
|
91
|
-
|
|
92
|
-
|
|
125
|
+
# Web 模式
|
|
126
|
+
manyoyo serve 127.0.0.1:3000
|
|
127
|
+
manyoyo serve 127.0.0.1:3000 -U admin -P 123456
|
|
93
128
|
|
|
94
|
-
|
|
129
|
+
# 查看配置与命令拼装
|
|
130
|
+
manyoyo config show
|
|
131
|
+
manyoyo config command
|
|
132
|
+
```
|
|
95
133
|
|
|
96
|
-
##
|
|
134
|
+
## 镜像构建
|
|
97
135
|
|
|
98
136
|
```bash
|
|
99
|
-
#
|
|
137
|
+
# common 版本
|
|
100
138
|
manyoyo build --iv 1.8.4-common
|
|
101
139
|
|
|
102
|
-
#
|
|
140
|
+
# full 版本
|
|
103
141
|
manyoyo build --iv 1.8.4-full
|
|
104
142
|
|
|
105
|
-
#
|
|
143
|
+
# 自定义工具集
|
|
106
144
|
manyoyo build --iba TOOL=go,codex,java,gemini
|
|
107
145
|
```
|
|
108
146
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
## 常用命令
|
|
147
|
+
说明:
|
|
112
148
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
149
|
+
- 首次构建会把依赖缓存到 `docker/cache/`
|
|
150
|
+
- 在缓存有效期内重复构建,通常会更快
|
|
151
|
+
- `imageVersion` 格式必须为 `x.y.z-后缀`
|
|
116
152
|
|
|
117
|
-
|
|
118
|
-
manyoyo run -y c # Claude Code(或 claude / cc)
|
|
119
|
-
manyoyo run -y gm # Gemini(或 gemini / g)
|
|
120
|
-
manyoyo run -y cx # Codex(或 codex)
|
|
121
|
-
manyoyo run -y oc # OpenCode(或 opencode)
|
|
122
|
-
manyoyo update # 更新 MANYOYO(全局 npm 安装场景)
|
|
153
|
+
## 配置模型
|
|
123
154
|
|
|
124
|
-
|
|
125
|
-
manyoyo ps
|
|
126
|
-
manyoyo images
|
|
127
|
-
manyoyo run -n my-dev -x /bin/bash
|
|
128
|
-
manyoyo rm my-dev
|
|
129
|
-
manyoyo serve 127.0.0.1:3000
|
|
130
|
-
manyoyo serve 127.0.0.1:3000 -U admin -P 123456
|
|
155
|
+
MANYOYO 的配置重点不是“多”,而是“可预测”:
|
|
131
156
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
```
|
|
157
|
+
- 标量值按 `命令行参数 > runs.<name> > 全局配置 > 默认值` 覆盖
|
|
158
|
+
- 数组值按 `全局配置 -> runs.<name> -> 命令行参数` 追加合并
|
|
159
|
+
- `env` 使用 map 合并,按 key 覆盖
|
|
136
160
|
|
|
137
|
-
|
|
161
|
+
相关文档:
|
|
138
162
|
|
|
139
|
-
配置优先级:命令行参数 > runs.<name> > 全局配置 > 默认值
|
|
140
|
-
详细说明请参考:
|
|
141
163
|
- [配置系统概览](https://xcanwin.github.io/manyoyo/zh/configuration/)
|
|
142
|
-
- [环境变量详解](https://xcanwin.github.io/manyoyo/zh/configuration/environment)
|
|
143
164
|
- [配置文件详解](https://xcanwin.github.io/manyoyo/zh/configuration/config-files)
|
|
165
|
+
- [环境变量详解](https://xcanwin.github.io/manyoyo/zh/configuration/environment)
|
|
144
166
|
|
|
145
|
-
##
|
|
167
|
+
## 文档入口
|
|
146
168
|
|
|
147
|
-
|
|
169
|
+
中文文档:
|
|
148
170
|
|
|
149
|
-
**中文文档:**
|
|
150
171
|
- [快速开始](https://xcanwin.github.io/manyoyo/zh/guide/quick-start)
|
|
151
172
|
- [安装详解](https://xcanwin.github.io/manyoyo/zh/guide/installation)
|
|
152
|
-
- [
|
|
173
|
+
- [CLI 选项](https://xcanwin.github.io/manyoyo/zh/reference/cli-options)
|
|
153
174
|
- [故障排查](https://xcanwin.github.io/manyoyo/zh/troubleshooting/)
|
|
154
175
|
|
|
155
|
-
|
|
176
|
+
English Documentation:
|
|
177
|
+
|
|
156
178
|
- [Quick Start](https://xcanwin.github.io/manyoyo/en/guide/quick-start)
|
|
157
179
|
- [Installation](https://xcanwin.github.io/manyoyo/en/guide/installation)
|
|
158
|
-
- [
|
|
180
|
+
- [CLI Options](https://xcanwin.github.io/manyoyo/en/reference/cli-options)
|
|
159
181
|
- [Troubleshooting](https://xcanwin.github.io/manyoyo/en/troubleshooting/)
|
|
160
182
|
|
|
161
|
-
##
|
|
183
|
+
## 安装与卸载
|
|
184
|
+
|
|
185
|
+
安装:
|
|
162
186
|
|
|
163
187
|
```bash
|
|
164
|
-
|
|
165
|
-
|
|
188
|
+
npm install -g @xcanwin/manyoyo
|
|
189
|
+
```
|
|
166
190
|
|
|
167
|
-
|
|
168
|
-
|
|
191
|
+
卸载:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
npm uninstall -g @xcanwin/manyoyo
|
|
195
|
+
rm -rf ~/.manyoyo/ # 可选
|
|
169
196
|
```
|
|
170
197
|
|
|
171
198
|
## 许可证
|
|
@@ -174,6 +201,7 @@ MIT
|
|
|
174
201
|
|
|
175
202
|
## 贡献
|
|
176
203
|
|
|
177
|
-
欢迎提交 Issue 和 Pull Request
|
|
204
|
+
欢迎提交 Issue 和 Pull Request。
|
|
178
205
|
|
|
179
|
-
|
|
206
|
+
- Issues: <https://github.com/xcanwin/manyoyo/issues>
|
|
207
|
+
- Repository: <https://github.com/xcanwin/manyoyo>
|
package/bin/manyoyo.js
CHANGED
|
@@ -15,6 +15,7 @@ const { initAgentConfigs } = require('../lib/init-config');
|
|
|
15
15
|
const { buildImage } = require('../lib/image-build');
|
|
16
16
|
const { resolveAgentResumeArg, buildAgentResumeCommand } = require('../lib/agent-resume');
|
|
17
17
|
const { runPluginCommand } = require('../lib/plugin');
|
|
18
|
+
const { buildManyoyoLogPath } = require('../lib/log-path');
|
|
18
19
|
const { version: BIN_VERSION, imageVersion: IMAGE_VERSION_DEFAULT } = require('../package.json');
|
|
19
20
|
const IMAGE_VERSION_BASE = String(IMAGE_VERSION_DEFAULT || '1.0.0').split('-')[0];
|
|
20
21
|
const IMAGE_VERSION_HELP_EXAMPLE = IMAGE_VERSION_DEFAULT || `${IMAGE_VERSION_BASE}-common`;
|
|
@@ -277,37 +278,26 @@ function getServeProcessSnapshot() {
|
|
|
277
278
|
}
|
|
278
279
|
|
|
279
280
|
function createServeLogger() {
|
|
280
|
-
function pad2(n) {
|
|
281
|
-
return String(n).padStart(2, '0');
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
function getLocalDateTag(date = new Date()) {
|
|
285
|
-
const y = date.getFullYear();
|
|
286
|
-
const m = pad2(date.getMonth() + 1);
|
|
287
|
-
const d = pad2(date.getDate());
|
|
288
|
-
return `${y}-${m}-${d}`;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
281
|
function formatLocalTimestamp(date = new Date()) {
|
|
292
282
|
const y = date.getFullYear();
|
|
293
|
-
const m =
|
|
294
|
-
const d =
|
|
295
|
-
const hh =
|
|
296
|
-
const mm =
|
|
297
|
-
const ss =
|
|
283
|
+
const m = String(date.getMonth() + 1).padStart(2, '0');
|
|
284
|
+
const d = String(date.getDate()).padStart(2, '0');
|
|
285
|
+
const hh = String(date.getHours()).padStart(2, '0');
|
|
286
|
+
const mm = String(date.getMinutes()).padStart(2, '0');
|
|
287
|
+
const ss = String(date.getSeconds()).padStart(2, '0');
|
|
298
288
|
const ms = String(date.getMilliseconds()).padStart(3, '0');
|
|
299
289
|
const offsetMinutes = -date.getTimezoneOffset();
|
|
300
290
|
const sign = offsetMinutes >= 0 ? '+' : '-';
|
|
301
291
|
const abs = Math.abs(offsetMinutes);
|
|
302
|
-
const offH =
|
|
303
|
-
const offM =
|
|
292
|
+
const offH = String(Math.floor(abs / 60)).padStart(2, '0');
|
|
293
|
+
const offM = String(abs % 60).padStart(2, '0');
|
|
304
294
|
return `${y}-${m}-${d}T${hh}:${mm}:${ss}.${ms}${sign}${offH}:${offM}`;
|
|
305
295
|
}
|
|
306
296
|
|
|
307
|
-
const
|
|
297
|
+
const serveLog = buildManyoyoLogPath('serve');
|
|
298
|
+
const logDir = serveLog.dir;
|
|
308
299
|
fs.mkdirSync(logDir, { recursive: true });
|
|
309
|
-
const
|
|
310
|
-
const logPath = path.join(logDir, `serve-${dateTag}.log`);
|
|
300
|
+
const logPath = serveLog.path;
|
|
311
301
|
|
|
312
302
|
function write(level, message, extra) {
|
|
313
303
|
const ts = formatLocalTimestamp();
|
package/lib/log-path.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const os = require('os');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
function pad2(n) {
|
|
5
|
+
return String(n).padStart(2, '0');
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function getLocalDateTag(date = new Date()) {
|
|
9
|
+
const y = date.getFullYear();
|
|
10
|
+
const m = pad2(date.getMonth() + 1);
|
|
11
|
+
const d = pad2(date.getDate());
|
|
12
|
+
return `${y}-${m}-${d}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function normalizeLogScope(scope) {
|
|
16
|
+
return String(scope || 'general')
|
|
17
|
+
.trim()
|
|
18
|
+
.replace(/[^A-Za-z0-9_.-]+/g, '-')
|
|
19
|
+
.replace(/^-+|-+$/g, '') || 'general';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function buildManyoyoLogPath(scope, date = new Date(), homeDir = os.homedir()) {
|
|
23
|
+
const safeScope = normalizeLogScope(scope);
|
|
24
|
+
const rootDir = path.join(homeDir, '.manyoyo', 'logs');
|
|
25
|
+
const dir = path.join(rootDir, safeScope);
|
|
26
|
+
const file = `${safeScope}-${getLocalDateTag(date)}.log`;
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
rootDir,
|
|
30
|
+
dir,
|
|
31
|
+
path: path.join(dir, file),
|
|
32
|
+
scope: safeScope,
|
|
33
|
+
file
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = {
|
|
38
|
+
getLocalDateTag,
|
|
39
|
+
normalizeLogScope,
|
|
40
|
+
buildManyoyoLogPath
|
|
41
|
+
};
|
package/lib/web/server.js
CHANGED
|
@@ -1788,7 +1788,7 @@ async function startWebServer(options) {
|
|
|
1788
1788
|
};
|
|
1789
1789
|
|
|
1790
1790
|
if (!ctx.authUser || !ctx.authPass) {
|
|
1791
|
-
throw new Error('Web 认证配置缺失,请设置 serve -
|
|
1791
|
+
throw new Error('Web 认证配置缺失,请设置 serve -U / serve -P');
|
|
1792
1792
|
}
|
|
1793
1793
|
|
|
1794
1794
|
const state = {
|