@workclaw/cli 1.0.315 → 1.0.316
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 +69 -23
- package/dist/box/index.d.ts.map +1 -1
- package/dist/box/installer/installer.d.ts.map +1 -1
- package/dist/box/src/box.d.ts.map +1 -1
- package/dist/box/types/index.d.ts +3 -1
- package/dist/box/types/index.d.ts.map +1 -1
- package/dist/{index-CkTwizLH.js → index-ChF0VChB.js} +86 -19
- package/dist/index.js +1 -1
- package/dist/local/index.d.ts.map +1 -1
- package/dist/local/installer/installer.d.ts.map +1 -1
- package/dist/local/src/local.d.ts.map +1 -1
- package/dist/local/types/index.d.ts +3 -1
- package/dist/local/types/index.d.ts.map +1 -1
- package/dist/shared/config/index.d.ts +4 -2
- package/dist/shared/config/index.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -52,12 +52,14 @@ workclaw box
|
|
|
52
52
|
**适用场景**:个人电脑或需要用户登录的设备
|
|
53
53
|
|
|
54
54
|
**特点**:
|
|
55
|
+
|
|
55
56
|
- ✅ 需要用户登录(手机号 + 密码)
|
|
56
57
|
- ✅ 自动获取 appKey 和 appSecret
|
|
57
58
|
- ✅ 支持多账号管理
|
|
58
59
|
- ✅ 自动创建和管理配置
|
|
59
60
|
|
|
60
61
|
**安装流程**:
|
|
62
|
+
|
|
61
63
|
1. 用户登录(RSA 加密密码)
|
|
62
64
|
2. 获取绑定配置
|
|
63
65
|
3. 通过手机号补全配置
|
|
@@ -69,12 +71,14 @@ workclaw box
|
|
|
69
71
|
**适用场景**:专用设备或无需用户登录的环境
|
|
70
72
|
|
|
71
73
|
**特点**:
|
|
74
|
+
|
|
72
75
|
- ✅ 无需登录(直接使用 appKey + appSecret)
|
|
73
76
|
- ✅ 适合批量部署
|
|
74
77
|
- ✅ 配置文件默认设置为开放策略
|
|
75
78
|
- ✅ 更快的安装速度
|
|
76
79
|
|
|
77
80
|
**安装流程**:
|
|
81
|
+
|
|
78
82
|
1. 清理旧版本插件
|
|
79
83
|
2. 下载并安装插件
|
|
80
84
|
3. 更新配置文件(`dmPolicy: "open"`)
|
|
@@ -96,25 +100,27 @@ npx @workclaw/cli --help
|
|
|
96
100
|
|
|
97
101
|
### local 命令参数
|
|
98
102
|
|
|
99
|
-
| 参数 | 说明
|
|
100
|
-
|
|
|
101
|
-
| --phone
|
|
102
|
-
| --user-pass
|
|
103
|
-
| --env
|
|
103
|
+
| 参数 | 说明 |
|
|
104
|
+
| ---------------- | ----------------------------------- |
|
|
105
|
+
| --phone | 手机号码(登录账号),未填写时会交互式提示输入 |
|
|
106
|
+
| --user-pass | 用户密码,未填写时会交互式提示输入 |
|
|
107
|
+
| --env | 环境 (test/prod/custom),默认 test,未填写时会交互式提示选择 |
|
|
108
|
+
| --customIp | 自定义环境后端 IP,仅当 env 为 custom 时使用 |
|
|
104
109
|
| --plugin-version | 插件版本号(默认安装最新版) |
|
|
105
|
-
| --openclaw-path
|
|
106
|
-
| --debug
|
|
110
|
+
| --openclaw-path | OpenClaw 安装目录(默认 \~/.openclaw) |
|
|
111
|
+
| --debug | 开启调试日志 |
|
|
107
112
|
|
|
108
113
|
### box 命令参数
|
|
109
114
|
|
|
110
|
-
| 参数 | 说明
|
|
111
|
-
|
|
|
112
|
-
| --app-key
|
|
113
|
-
| --app-secret
|
|
114
|
-
| --env
|
|
115
|
+
| 参数 | 说明 |
|
|
116
|
+
| ---------------- | ----------------------------------- |
|
|
117
|
+
| --app-key | App Key,未填写时会交互式提示输入 |
|
|
118
|
+
| --app-secret | App Secret,未填写时会交互式提示输入 |
|
|
119
|
+
| --env | 环境 (test/prod/custom),默认 test,未填写时会交互式提示选择 |
|
|
120
|
+
| --customIp | 自定义环境后端 IP,仅当 env 为 custom 时使用 |
|
|
115
121
|
| --plugin-version | 插件版本号(默认安装最新版) |
|
|
116
|
-
| --openclaw-path
|
|
117
|
-
| --debug
|
|
122
|
+
| --openclaw-path | OpenClaw 安装目录(默认 \~/.openclaw) |
|
|
123
|
+
| --debug | 开启调试日志 |
|
|
118
124
|
|
|
119
125
|
## 💡 使用示例
|
|
120
126
|
|
|
@@ -125,16 +131,25 @@ npx @workclaw/cli --help
|
|
|
125
131
|
npx @workclaw/cli local
|
|
126
132
|
|
|
127
133
|
# 指定手机号和密码
|
|
128
|
-
npx @workclaw/cli local --phone
|
|
134
|
+
npx @workclaw/cli local --phone your_phone --user-pass your_password
|
|
129
135
|
|
|
130
136
|
# 指定正式环境
|
|
131
|
-
npx @workclaw/cli local --env prod --phone
|
|
137
|
+
npx @workclaw/cli local --env prod --phone your_phone --user-pass your_password
|
|
132
138
|
|
|
133
139
|
# 自定义安装路径
|
|
134
|
-
npx @workclaw/cli local --openclaw-path "C:\CustomPath\OpenClaw" --phone
|
|
140
|
+
npx @workclaw/cli local --openclaw-path "C:\CustomPath\OpenClaw" --phone your_phone --user-pass your_password
|
|
135
141
|
|
|
136
142
|
# 开启调试模式
|
|
137
|
-
npx @workclaw/cli local --debug --phone
|
|
143
|
+
npx @workclaw/cli local --debug --phone your_phone --user-pass your_password
|
|
144
|
+
|
|
145
|
+
# 自定义环境(使用本地后端服务)
|
|
146
|
+
npx @workclaw/cli local --env custom --phone your_phone --user-pass your_password
|
|
147
|
+
|
|
148
|
+
# 自定义环境(命令行直接传入 IP)
|
|
149
|
+
npx @workclaw/cli local --env custom --customIp 192.168.1.100:32005 --phone your_phone --user-pass your_password
|
|
150
|
+
|
|
151
|
+
# 自定义环境(带协议完整地址)
|
|
152
|
+
npx @workclaw/cli local --env custom --customIp http://127.0.0.1:32005 --phone your_phone --user-pass your_password
|
|
138
153
|
```
|
|
139
154
|
|
|
140
155
|
### 盒子设备安装
|
|
@@ -154,6 +169,12 @@ npx @workclaw/cli box --openclaw-path "/custom/path" --app-key your-app-key --ap
|
|
|
154
169
|
|
|
155
170
|
# 开启调试模式
|
|
156
171
|
npx @workclaw/cli box --debug --app-key your-app-key --app-secret your-app-secret
|
|
172
|
+
|
|
173
|
+
# 自定义环境(使用本地后端服务)
|
|
174
|
+
npx @workclaw/cli box --env custom --app-key your-app-key --app-secret your-app-secret
|
|
175
|
+
|
|
176
|
+
# 自定义环境(命令行直接传入 IP)
|
|
177
|
+
npx @workclaw/cli box --env custom --customIp 192.168.1.100:32005 --app-key your-app-key --app-secret your-app-secret
|
|
157
178
|
```
|
|
158
179
|
|
|
159
180
|
## 🔧 技术实现
|
|
@@ -164,11 +185,9 @@ npx @workclaw/cli box --debug --app-key your-app-key --app-secret your-app-secre
|
|
|
164
185
|
- 使用 `npm pack` 从 npm 镜像源下载插件包
|
|
165
186
|
- 默认使用腾讯云 npm 镜像:`https://mirrors.tencent.com/npm/`
|
|
166
187
|
- 支持重试机制(最多 3 次)
|
|
167
|
-
|
|
168
188
|
2. **文件解压**
|
|
169
189
|
- 使用 `tar.extract()` 解压到目标目录
|
|
170
190
|
- 自动创建必要的目录结构
|
|
171
|
-
|
|
172
191
|
3. **依赖安装**
|
|
173
192
|
- 使用 `npm install --omit=dev` 安装生产依赖
|
|
174
193
|
- 自动跳过开发依赖,减小安装体积
|
|
@@ -190,6 +209,7 @@ npx @workclaw/cli box --debug --app-key your-app-key --app-secret your-app-secre
|
|
|
190
209
|
### 路径验证
|
|
191
210
|
|
|
192
211
|
工具会自动验证用户输入的 `--openclaw-path` 参数:
|
|
212
|
+
|
|
193
213
|
- ✅ 必须是绝对路径
|
|
194
214
|
- ✅ 不能包含非法字符:`< > : " | ? *`
|
|
195
215
|
|
|
@@ -198,35 +218,52 @@ npx @workclaw/cli box --debug --app-key your-app-key --app-secret your-app-secre
|
|
|
198
218
|
### Q: 安装失败,提示"网络错误"?
|
|
199
219
|
|
|
200
220
|
**A**: 检查网络连接,可以尝试:
|
|
221
|
+
|
|
201
222
|
- 使用代理或 VPN
|
|
202
223
|
- 配置 npm 镜像源:`npm config set registry https://registry.npmmirror.com`
|
|
203
224
|
|
|
204
225
|
### Q: 提示"路径必须是绝对路径"?
|
|
205
226
|
|
|
206
227
|
**A**: `--openclaw-path` 需要使用绝对路径,例如:
|
|
228
|
+
|
|
207
229
|
- Windows: `C:\OpenClaw` 或 `C:/OpenClaw`
|
|
208
230
|
- Linux/macOS: `/opt/openclaw`
|
|
209
231
|
|
|
210
232
|
### Q: 如何查看详细日志?
|
|
211
233
|
|
|
212
234
|
**A**: 使用 `--debug` 参数:
|
|
235
|
+
|
|
213
236
|
```bash
|
|
214
|
-
npx @workclaw/cli local --debug --phone
|
|
237
|
+
npx @workclaw/cli local --debug --phone your_phone --user-pass your_password
|
|
215
238
|
```
|
|
216
239
|
|
|
217
240
|
### Q: 如何指定插件版本?
|
|
218
241
|
|
|
219
242
|
**A**: 使用 `--plugin-version` 参数:
|
|
243
|
+
|
|
220
244
|
```bash
|
|
221
|
-
npx @workclaw/cli local --plugin-version 1.0.100 --phone
|
|
245
|
+
npx @workclaw/cli local --plugin-version 1.0.100 --phone your_phone --user-pass your_password
|
|
222
246
|
```
|
|
223
247
|
|
|
224
248
|
### Q: local 和 box 命令有什么区别?
|
|
225
249
|
|
|
226
|
-
**A**:
|
|
250
|
+
**A**:
|
|
251
|
+
|
|
227
252
|
- **local**: 需要用户登录,适合个人设备,支持多账号
|
|
228
253
|
- **box**: 无需登录,直接使用 appKey+appSecret,适合专用设备
|
|
229
254
|
|
|
255
|
+
### Q: 什么是自定义环境(custom)?
|
|
256
|
+
|
|
257
|
+
**A**:
|
|
258
|
+
|
|
259
|
+
自定义环境允许你连接到自己本地或私有部署的后端服务,适合前后端联调测试场景。使用方式:
|
|
260
|
+
|
|
261
|
+
1. 选择 `custom` 环境
|
|
262
|
+
2. 输入你的后端 IP 地址(支持 `192.168.1.100:32005` 或 `http://127.0.0.1:32005` 格式)
|
|
263
|
+
3. 工具会自动适配协议和路径
|
|
264
|
+
|
|
265
|
+
`MODEL_BASE_URL` 始终保持为固定值,不会随自定义环境改变。
|
|
266
|
+
|
|
230
267
|
## 🛠 开发
|
|
231
268
|
|
|
232
269
|
### 项目结构
|
|
@@ -267,6 +304,14 @@ pnpm lint:fix
|
|
|
267
304
|
|
|
268
305
|
## 📝 更新日志
|
|
269
306
|
|
|
307
|
+
### v1.0.314 (2026-04-27)
|
|
308
|
+
|
|
309
|
+
- ✨ 新增自定义环境(custom)- 支持连接私有部署后端服务
|
|
310
|
+
- 🔧 新增 `--customIp` 参数 - 命令行直接传入自定义后端 IP
|
|
311
|
+
- 🎨 优化交互体验 - 仅选择 custom 环境时才提示输入 IP
|
|
312
|
+
- 📝 更新文档 - 添加自定义环境使用说明和示例
|
|
313
|
+
- 🔒 `MODEL_BASE_URL` 保持固定,不随自定义环境改变
|
|
314
|
+
|
|
270
315
|
### v1.0.313 (2026-04-23)
|
|
271
316
|
|
|
272
317
|
- ✨ 新增 `--openclaw-path` 参数 - 支持自定义安装路径
|
|
@@ -306,3 +351,4 @@ MIT License
|
|
|
306
351
|
- [ora](https://github.com/sindresorhus/ora) - 加载动画
|
|
307
352
|
- [axios](https://github.com/axios/axios) - HTTP 客户端
|
|
308
353
|
- [tar](https://github.com/isaacs/node-tar) - tar 文件解压
|
|
354
|
+
|
package/dist/box/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/box/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGxC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/box/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGxC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAYvD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../../src/box/installer/installer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAgB,MAAM,UAAU,CAAA;AAqDhE,qBAAa,YAAY;IAIX,OAAO,CAAC,MAAM;IAH1B,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,UAAU,CAAa;gBAEX,MAAM,EAAE,kBAAkB;IAI9C,cAAc,IAAI,IAAI;IAatB,OAAO,CAAC,QAAQ;
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../../src/box/installer/installer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAgB,MAAM,UAAU,CAAA;AAqDhE,qBAAa,YAAY;IAIX,OAAO,CAAC,MAAM;IAH1B,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,UAAU,CAAa;gBAEX,MAAM,EAAE,kBAAkB;IAI9C,cAAc,IAAI,IAAI;IAatB,OAAO,CAAC,QAAQ;IAkChB,OAAO,CAAC,aAAa;IAMrB,aAAa,IAAI,MAAM;IAIvB,OAAO,CAAC,cAAc;IAOhB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YA0BhB,eAAe;YA0Bf,iBAAiB;YAoHjB,cAAc;CAiR7B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"box.d.ts","sourceRoot":"","sources":["../../../src/box/src/box.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAgC1C,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"box.d.ts","sourceRoot":"","sources":["../../../src/box/src/box.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAgC1C,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAgJzE"}
|
|
@@ -3,13 +3,15 @@ export interface BoxOptions {
|
|
|
3
3
|
env?: string;
|
|
4
4
|
appKey?: string;
|
|
5
5
|
appSecret?: string;
|
|
6
|
+
customIp?: string;
|
|
7
|
+
wsUrl?: string;
|
|
6
8
|
pluginVersion?: string;
|
|
7
9
|
openclawPath?: string;
|
|
8
10
|
debug?: boolean;
|
|
9
11
|
}
|
|
10
12
|
export interface BoxInstallerConfig {
|
|
11
13
|
env: Environment;
|
|
12
|
-
|
|
14
|
+
customIp?: string;
|
|
13
15
|
wsUrl?: string;
|
|
14
16
|
appKey: string;
|
|
15
17
|
appSecret: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/box/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAElD,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,WAAW,CAAA;IAChB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/box/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAElD,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,WAAW,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb"}
|
|
@@ -89,8 +89,26 @@ const TEST_CONFIG = {
|
|
|
89
89
|
TIMEOUT: 1e4
|
|
90
90
|
}
|
|
91
91
|
};
|
|
92
|
-
function getConfig(env) {
|
|
93
|
-
|
|
92
|
+
function getConfig(env, customIp) {
|
|
93
|
+
if (env === "test") {
|
|
94
|
+
return TEST_CONFIG;
|
|
95
|
+
}
|
|
96
|
+
if (env === "custom") {
|
|
97
|
+
if (!customIp) {
|
|
98
|
+
throw new Error("自定义环境必须提供 customIp");
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
...TEST_CONFIG,
|
|
102
|
+
DEFAULT_BASE_URL: TEST_CONFIG.DEFAULT_BASE_URL.replace("172.168.80.30", customIp),
|
|
103
|
+
DEFAULT_WS_URL: TEST_CONFIG.DEFAULT_WS_URL.replace("172.168.80.30", customIp),
|
|
104
|
+
API: {
|
|
105
|
+
...TEST_CONFIG.API,
|
|
106
|
+
TUZAI_BASE_URL: TEST_CONFIG.API.TUZAI_BASE_URL.replace("172.168.80.30", customIp),
|
|
107
|
+
BASE_URL: TEST_CONFIG.API.BASE_URL.replace("172.168.80.30", customIp)
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
return CONFIG;
|
|
94
112
|
}
|
|
95
113
|
function getHomeDir$1() {
|
|
96
114
|
return process$1.env.HOME || process$1.env.USERPROFILE || "";
|
|
@@ -138,7 +156,8 @@ class BoxInstaller {
|
|
|
138
156
|
debugLog("[验证配置] 配置检查通过");
|
|
139
157
|
}
|
|
140
158
|
getPaths() {
|
|
141
|
-
const
|
|
159
|
+
const env = this.config.env || "test";
|
|
160
|
+
const config = getConfig(env, this.config.customIp);
|
|
142
161
|
let baseDir;
|
|
143
162
|
if (this.config.openclawPath) {
|
|
144
163
|
debugLog(`[路径验证] 验证自定义路径: ${this.config.openclawPath}`);
|
|
@@ -473,7 +492,7 @@ class BoxInstaller {
|
|
|
473
492
|
// 应用密钥
|
|
474
493
|
appSecret: this.config.appSecret,
|
|
475
494
|
// API 基础 URL
|
|
476
|
-
baseUrl: this.config.
|
|
495
|
+
baseUrl: this.config.customIp || config.DEFAULT_BASE_URL,
|
|
477
496
|
// WebSocket URL
|
|
478
497
|
websocketUrl: this.config.wsUrl || config.DEFAULT_WS_URL,
|
|
479
498
|
// 允许不安全的 TLS 连接
|
|
@@ -594,13 +613,14 @@ function checkEnv$1() {
|
|
|
594
613
|
async function createBoxCommand(options) {
|
|
595
614
|
setDebug(!!options.debug);
|
|
596
615
|
debugLog("[盒子安装] 开始处理...");
|
|
597
|
-
debugLog(`[盒子安装] 参数: env=${options.env}, appKey=${options.appKey ? "***" : "未提供"}, debug=${options.debug}`);
|
|
616
|
+
debugLog(`[盒子安装] 参数: env=${options.env}, appKey=${options.appKey ? "***" : "未提供"}, customIp=${options.customIp}, debug=${options.debug}`);
|
|
598
617
|
checkEnv$1();
|
|
599
618
|
debugLog("[盒子安装] 环境检查通过");
|
|
600
619
|
try {
|
|
601
620
|
let env = options.env;
|
|
602
621
|
let appKey = options.appKey;
|
|
603
622
|
let appSecret = options.appSecret;
|
|
623
|
+
let customIp = options.customIp;
|
|
604
624
|
const questions = [];
|
|
605
625
|
if (!env) {
|
|
606
626
|
debugLog("[盒子安装] 需要选择环境");
|
|
@@ -611,7 +631,8 @@ async function createBoxCommand(options) {
|
|
|
611
631
|
default: "test",
|
|
612
632
|
choices: [
|
|
613
633
|
{ name: `${chalk.green("测试环境")} ${chalk.dim("(test)")}`, value: "test" },
|
|
614
|
-
{ name: `${chalk.red("正式环境")} ${chalk.dim("(prod)")}`, value: "prod" }
|
|
634
|
+
{ name: `${chalk.red("正式环境")} ${chalk.dim("(prod)")}`, value: "prod" },
|
|
635
|
+
{ name: `${chalk.yellow("自定义环境")} ${chalk.dim("(custom) - 需要输入后端 IP")}`, value: "custom" }
|
|
615
636
|
]
|
|
616
637
|
});
|
|
617
638
|
} else {
|
|
@@ -657,12 +678,33 @@ async function createBoxCommand(options) {
|
|
|
657
678
|
appKey = appKey || answers.appKey;
|
|
658
679
|
appSecret = appSecret || answers.appSecret;
|
|
659
680
|
}
|
|
660
|
-
|
|
681
|
+
if (env === "custom" && !customIp) {
|
|
682
|
+
debugLog("[盒子安装] 自定义环境需要输入后端 IP");
|
|
683
|
+
const answer = await inquirer.prompt([{
|
|
684
|
+
type: "input",
|
|
685
|
+
name: "customIp",
|
|
686
|
+
message: chalk.cyan("请输入后端 IP:"),
|
|
687
|
+
default: "127.0.0.1",
|
|
688
|
+
validate: (value) => {
|
|
689
|
+
if (!value || value.trim() === "") {
|
|
690
|
+
return chalk.red("后端 IP 不能为空");
|
|
691
|
+
}
|
|
692
|
+
return true;
|
|
693
|
+
}
|
|
694
|
+
}]);
|
|
695
|
+
customIp = answer.customIp;
|
|
696
|
+
debugLog("[盒子安装] 获取自定义 customIp");
|
|
697
|
+
} else if (env === "custom" && customIp) {
|
|
698
|
+
debugLog(`[盒子安装] 使用命令行参数: customIp=${customIp}`);
|
|
699
|
+
}
|
|
700
|
+
debugLog(`[盒子安装] 最终参数: env=${env}, customIp=${customIp}, openclawPath=${options.openclawPath}`);
|
|
661
701
|
debugLog("[盒子安装] 创建 BoxInstaller 实例...");
|
|
662
702
|
const installer = new BoxInstaller({
|
|
663
703
|
appKey,
|
|
664
704
|
appSecret,
|
|
665
705
|
env,
|
|
706
|
+
customIp,
|
|
707
|
+
wsUrl: options.wsUrl,
|
|
666
708
|
pluginVersion: options.pluginVersion,
|
|
667
709
|
openclawPath: options.openclawPath
|
|
668
710
|
});
|
|
@@ -699,7 +741,7 @@ async function createBoxCommand(options) {
|
|
|
699
741
|
}
|
|
700
742
|
}
|
|
701
743
|
function registerCommands$1(program2) {
|
|
702
|
-
program2.command("box").description("盒子设备安装(无需登录)").option("-e, --env <env>", "环境 (test/prod)").option("--app-key <appKey>", "App Key").option("--app-secret <appSecret>", "App Secret").option("--plugin-version <plugin-version>", "插件版本号(默认最新版)").option("--openclaw-path <path>", "OpenClaw 安装目录路径(默认 ~/.openclaw)").option("--debug", "开启调试日志").action(createBoxCommand);
|
|
744
|
+
program2.command("box").description("盒子设备安装(无需登录)").option("-e, --env <env>", "环境 (test/prod/custom)").option("--app-key <appKey>", "App Key").option("--app-secret <appSecret>", "App Secret").option("--base-url <url>", "自定义后端基础 URL(仅 custom 环境生效)").option("--ws-url <url>", "自定义 WebSocket URL(仅 custom 环境生效,默认自动从 base-url 转换)").option("--plugin-version <plugin-version>", "插件版本号(默认最新版)").option("--openclaw-path <path>", "OpenClaw 安装目录路径(默认 ~/.openclaw)").option("--debug", "开启调试日志").action(createBoxCommand);
|
|
703
745
|
}
|
|
704
746
|
const ERROR_CODES = {
|
|
705
747
|
PHONE_REQUIRED: "PHONE_REQUIRED",
|
|
@@ -4785,7 +4827,7 @@ class LocalInstaller {
|
|
|
4785
4827
|
debugLog("[安装开始]");
|
|
4786
4828
|
this.validateConfig();
|
|
4787
4829
|
const env = this.config.env || "test";
|
|
4788
|
-
const config = getConfig(env);
|
|
4830
|
+
const config = getConfig(env, this.config.customIp);
|
|
4789
4831
|
let baseDir;
|
|
4790
4832
|
if (this.config.openclawPath) {
|
|
4791
4833
|
debugLog(`[路径验证] 验证自定义路径: ${this.config.openclawPath}`);
|
|
@@ -4813,8 +4855,8 @@ class LocalInstaller {
|
|
|
4813
4855
|
debugLog(`[路径配置] target=${paths.target}`);
|
|
4814
4856
|
debugLog(`[路径配置] config=${paths.config}`);
|
|
4815
4857
|
debugLog(`[路径配置] workspace=${paths.workspace}`);
|
|
4816
|
-
const token = await this.doLogin(
|
|
4817
|
-
const boundConfig = await this.doFetchBoundConfig(
|
|
4858
|
+
const token = await this.doLogin();
|
|
4859
|
+
const boundConfig = await this.doFetchBoundConfig(token);
|
|
4818
4860
|
await this.doCleanOldFiles(paths.target);
|
|
4819
4861
|
await this.doDownloadFromNpm(paths);
|
|
4820
4862
|
await this.doUpdateConfig(paths, boundConfig, env);
|
|
@@ -4833,7 +4875,8 @@ class LocalInstaller {
|
|
|
4833
4875
|
}
|
|
4834
4876
|
return PLUGIN_PACKAGE_NAME;
|
|
4835
4877
|
}
|
|
4836
|
-
async doLogin(
|
|
4878
|
+
async doLogin() {
|
|
4879
|
+
const env = this.config.env || "test";
|
|
4837
4880
|
this.spinner.prefixText = this.prefixText;
|
|
4838
4881
|
this.spinner.text = chalk.cyan("正在验证账号...");
|
|
4839
4882
|
debugLog(`[用户登录] 手机号: ${this.config.phone}`);
|
|
@@ -4850,7 +4893,8 @@ class LocalInstaller {
|
|
|
4850
4893
|
debugLog("[用户登录] 登录成功");
|
|
4851
4894
|
return token;
|
|
4852
4895
|
}
|
|
4853
|
-
async doFetchBoundConfig(
|
|
4896
|
+
async doFetchBoundConfig(token) {
|
|
4897
|
+
const env = this.config.env || "test";
|
|
4854
4898
|
this.spinner.prefixText = this.prefixText;
|
|
4855
4899
|
this.spinner.text = chalk.cyan("正在获取绑定信息...");
|
|
4856
4900
|
debugLog("[获取配置] 调用绑定配置接口...");
|
|
@@ -4988,7 +5032,7 @@ class LocalInstaller {
|
|
|
4988
5032
|
} catch {
|
|
4989
5033
|
debugLog("[更新配置] 无原有配置");
|
|
4990
5034
|
}
|
|
4991
|
-
const config = getConfig(env);
|
|
5035
|
+
const config = getConfig(env, this.config.customIp);
|
|
4992
5036
|
const newConfig = {
|
|
4993
5037
|
// diagnostics: 诊断配置
|
|
4994
5038
|
diagnostics: {
|
|
@@ -5084,7 +5128,7 @@ class LocalInstaller {
|
|
|
5084
5128
|
connectionMode: "websocket",
|
|
5085
5129
|
appKey: boundConfig.appKey,
|
|
5086
5130
|
appSecret: boundConfig.appSecret,
|
|
5087
|
-
baseUrl: this.config.
|
|
5131
|
+
baseUrl: this.config.customIp || config.DEFAULT_BASE_URL,
|
|
5088
5132
|
websocketUrl: this.config.wsUrl || config.DEFAULT_WS_URL,
|
|
5089
5133
|
allowInsecureTls: true,
|
|
5090
5134
|
allowRawJsonPayload: true,
|
|
@@ -5180,13 +5224,14 @@ function checkEnv() {
|
|
|
5180
5224
|
async function createLocalCommand(options) {
|
|
5181
5225
|
setDebug(!!options.debug);
|
|
5182
5226
|
debugLog("[初始化] 开始处理...");
|
|
5183
|
-
debugLog(`[初始化] 参数: env=${options.env}, phone=${options.phone}, debug=${options.debug}`);
|
|
5227
|
+
debugLog(`[初始化] 参数: env=${options.env}, phone=${options.phone}, customIp=${options.customIp}, debug=${options.debug}`);
|
|
5184
5228
|
checkEnv();
|
|
5185
5229
|
debugLog("[初始化] 环境检查通过");
|
|
5186
5230
|
try {
|
|
5187
5231
|
let env = options.env;
|
|
5188
5232
|
let phone = options.phone;
|
|
5189
5233
|
let userPass = options.userPass;
|
|
5234
|
+
let customIp = options.customIp;
|
|
5190
5235
|
const questions = [];
|
|
5191
5236
|
if (!env) {
|
|
5192
5237
|
debugLog("[初始化] 需要选择环境");
|
|
@@ -5197,7 +5242,8 @@ async function createLocalCommand(options) {
|
|
|
5197
5242
|
default: "test",
|
|
5198
5243
|
choices: [
|
|
5199
5244
|
{ name: `${chalk.green("测试环境")} ${chalk.dim("(test)")}`, value: "test" },
|
|
5200
|
-
{ name: `${chalk.red("正式环境")} ${chalk.dim("(prod)")}`, value: "prod" }
|
|
5245
|
+
{ name: `${chalk.red("正式环境")} ${chalk.dim("(prod)")}`, value: "prod" },
|
|
5246
|
+
{ name: `${chalk.yellow("自定义环境")} ${chalk.dim("(custom) - 需要输入后端 IP")}`, value: "custom" }
|
|
5201
5247
|
]
|
|
5202
5248
|
});
|
|
5203
5249
|
} else {
|
|
@@ -5246,12 +5292,33 @@ async function createLocalCommand(options) {
|
|
|
5246
5292
|
phone = phone || answers.phone;
|
|
5247
5293
|
userPass = userPass || answers.userPass;
|
|
5248
5294
|
}
|
|
5249
|
-
|
|
5295
|
+
if (env === "custom" && !customIp) {
|
|
5296
|
+
debugLog("[初始化] 自定义环境需要输入后端 IP");
|
|
5297
|
+
const answer = await inquirer.prompt([{
|
|
5298
|
+
type: "input",
|
|
5299
|
+
name: "customIp",
|
|
5300
|
+
message: chalk.cyan("请输入后端 IP:"),
|
|
5301
|
+
default: "127.0.0.1",
|
|
5302
|
+
validate: (value) => {
|
|
5303
|
+
if (!value || value.trim() === "") {
|
|
5304
|
+
return chalk.red("后端 IP 不能为空");
|
|
5305
|
+
}
|
|
5306
|
+
return true;
|
|
5307
|
+
}
|
|
5308
|
+
}]);
|
|
5309
|
+
customIp = answer.customIp;
|
|
5310
|
+
debugLog("[初始化] 获取自定义 customIp");
|
|
5311
|
+
} else if (env === "custom" && customIp) {
|
|
5312
|
+
debugLog(`[初始化] 使用命令行参数: customIp=${customIp}`);
|
|
5313
|
+
}
|
|
5314
|
+
debugLog(`[初始化] 最终参数: env=${env}, phone=${phone}, customIp=${customIp}, pluginVersion=${options.pluginVersion}, openclawPath=${options.openclawPath}`);
|
|
5250
5315
|
debugLog("[初始化] 创建 LocalInstaller 实例...");
|
|
5251
5316
|
const installer = new LocalInstaller({
|
|
5252
5317
|
phone,
|
|
5253
5318
|
userPass,
|
|
5254
5319
|
env,
|
|
5320
|
+
customIp,
|
|
5321
|
+
wsUrl: options.wsUrl,
|
|
5255
5322
|
pluginVersion: options.pluginVersion,
|
|
5256
5323
|
openclawPath: options.openclawPath
|
|
5257
5324
|
});
|
|
@@ -5288,7 +5355,7 @@ async function createLocalCommand(options) {
|
|
|
5288
5355
|
}
|
|
5289
5356
|
}
|
|
5290
5357
|
function registerCommands(program2) {
|
|
5291
|
-
program2.command("local").description("本地账户安装(需要登录)").option("-e, --env <env>", "环境 (test/prod)").option("--phone <phone>", "手机号码").option("--user-pass <userPass>", "用户密码").option("--plugin-version <plugin-version>", "插件版本号(默认最新版)").option("--openclaw-path <path>", "OpenClaw 安装目录路径(默认 ~/.openclaw)").option("--debug", "开启调试日志").action(createLocalCommand);
|
|
5358
|
+
program2.command("local").description("本地账户安装(需要登录)").option("-e, --env <env>", "环境 (test/prod/custom)").option("--phone <phone>", "手机号码").option("--user-pass <userPass>", "用户密码").option("--base-url <url>", "自定义后端基础 URL(仅 custom 环境生效)").option("--ws-url <url>", "自定义 WebSocket URL(仅 custom 环境生效,默认自动从 base-url 转换)").option("--plugin-version <plugin-version>", "插件版本号(默认最新版)").option("--openclaw-path <path>", "OpenClaw 安装目录路径(默认 ~/.openclaw)").option("--debug", "开启调试日志").action(createLocalCommand);
|
|
5292
5359
|
}
|
|
5293
5360
|
const __filename$1 = fileURLToPath(import.meta.url);
|
|
5294
5361
|
const __dirname$1 = dirname(__filename$1);
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/local/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGxC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/local/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGxC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAYvD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../../src/local/installer/installer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAA6B,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAuD/E,qBAAa,cAAc;IAIb,OAAO,CAAC,MAAM;IAH1B,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,UAAU,CAAa;gBAEX,MAAM,EAAE,oBAAoB;IAIhD,cAAc,IAAI,IAAI;IAYhB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAkD9B,aAAa,IAAI,MAAM;IAIvB,OAAO,CAAC,cAAc;YAOR,OAAO;
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../../src/local/installer/installer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAA6B,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAuD/E,qBAAa,cAAc;IAIb,OAAO,CAAC,MAAM;IAH1B,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,UAAU,CAAa;gBAEX,MAAM,EAAE,oBAAoB;IAIhD,cAAc,IAAI,IAAI;IAYhB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAkD9B,aAAa,IAAI,MAAM;IAIvB,OAAO,CAAC,cAAc;YAOR,OAAO;YAqBP,kBAAkB;YAclB,eAAe;YAmBf,iBAAiB;YAmHjB,cAAc;CA+M7B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../../src/local/src/local.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAgC5C,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../../src/local/src/local.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAgC5C,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAgJ7E"}
|
|
@@ -3,13 +3,15 @@ export interface LocalOptions {
|
|
|
3
3
|
env?: string;
|
|
4
4
|
phone?: string;
|
|
5
5
|
userPass?: string;
|
|
6
|
+
customIp?: string;
|
|
7
|
+
wsUrl?: string;
|
|
6
8
|
pluginVersion?: string;
|
|
7
9
|
openclawPath?: string;
|
|
8
10
|
debug?: boolean;
|
|
9
11
|
}
|
|
10
12
|
export interface LocalInstallerConfig {
|
|
11
13
|
env?: Environment;
|
|
12
|
-
|
|
14
|
+
customIp?: string;
|
|
13
15
|
wsUrl?: string;
|
|
14
16
|
phone: string;
|
|
15
17
|
userPass: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/local/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAElD,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,EAAE,WAAW,CAAA;IACjB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/local/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAElD,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,EAAE,WAAW,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 环境类型
|
|
3
3
|
*/
|
|
4
|
-
export type Environment = 'test' | 'prod';
|
|
4
|
+
export type Environment = 'test' | 'prod' | 'custom';
|
|
5
5
|
/**
|
|
6
6
|
* 配置接口
|
|
7
7
|
*/
|
|
@@ -44,6 +44,8 @@ export declare const CONFIG: ConfigInterface;
|
|
|
44
44
|
export declare const TEST_CONFIG: ConfigInterface;
|
|
45
45
|
/**
|
|
46
46
|
* 根据环境获取配置
|
|
47
|
+
* @param env - 环境
|
|
48
|
+
* @param customIp - 自定义环境的 IP 地址,仅当 env 为 custom 时使用
|
|
47
49
|
*/
|
|
48
|
-
export declare function getConfig(env: Environment): ConfigInterface;
|
|
50
|
+
export declare function getConfig(env: Environment, customIp?: string): ConfigInterface;
|
|
49
51
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/config/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/config/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAA;AAEpD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW;IACX,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe;IACf,gBAAgB,EAAE,MAAM,CAAA;IACxB,oBAAoB;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,eAAe;IACf,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW;IACX,IAAI,EAAE;QACJ,QAAQ,EAAE,MAAM,CAAA;QAChB,UAAU,EAAE,MAAM,CAAA;QAClB,OAAO,EAAE,MAAM,CAAA;QACf,WAAW,EAAE,MAAM,CAAA;QACnB,SAAS,EAAE,MAAM,CAAA;QACjB,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;IACD,WAAW;IACX,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,aAAa;IACb,GAAG,EAAE;QACH,cAAc,EAAE,MAAM,CAAA;QACtB,QAAQ,EAAE,MAAM,CAAA;QAChB,OAAO,EAAE,MAAM,CAAA;KAChB,CAAA;CACF;AAED;;;GAGG;AACH,eAAO,MAAM,MAAM,EAAE,eAmBpB,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,eAmBzB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,eAAe,CAsB9E"}
|