@workclaw/cli 1.0.22 → 1.0.25
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.
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as fsSync from "node:fs";
|
|
1
2
|
import { readFileSync } from "node:fs";
|
|
2
3
|
import path, { resolve, dirname } from "node:path";
|
|
3
4
|
import process$1 from "node:process";
|
|
@@ -32,7 +33,9 @@ const ERROR_CODES$1 = {
|
|
|
32
33
|
NODE_NOT_FOUND: "NODE_NOT_FOUND",
|
|
33
34
|
NPM_NOT_FOUND: "NPM_NOT_FOUND",
|
|
34
35
|
NPM_INSTALL_FAILED: "NPM_INSTALL_FAILED",
|
|
35
|
-
CONFIG_WRITE_FAILED: "CONFIG_WRITE_FAILED"
|
|
36
|
+
CONFIG_WRITE_FAILED: "CONFIG_WRITE_FAILED",
|
|
37
|
+
HTTP_ERROR: "HTTP_ERROR",
|
|
38
|
+
NETWORK_ERROR: "NETWORK_ERROR"
|
|
36
39
|
};
|
|
37
40
|
let AppError$1 = class AppError extends Error {
|
|
38
41
|
constructor(code, message) {
|
|
@@ -111,20 +114,20 @@ async function httpPost(url, data, config) {
|
|
|
111
114
|
debugLog(`[HTTP POST] 响应状态文本: ${axiosError.response.statusText}`);
|
|
112
115
|
debugLog(`[HTTP POST] 响应数据: ${JSON.stringify(responseData)}`);
|
|
113
116
|
if (typeof responseData === "string") {
|
|
114
|
-
throw new
|
|
117
|
+
throw new AppError$1(ERROR_CODES$1.HTTP_ERROR, `请求失败 (${axiosError.response.status}): ${responseData}`);
|
|
115
118
|
} else if (responseData && typeof responseData === "object" && "message" in responseData) {
|
|
116
|
-
throw new
|
|
119
|
+
throw new AppError$1(ERROR_CODES$1.HTTP_ERROR, `请求失败 (${axiosError.response.status}): ${responseData.message}`);
|
|
117
120
|
} else {
|
|
118
|
-
throw new
|
|
121
|
+
throw new AppError$1(ERROR_CODES$1.HTTP_ERROR, `请求失败 (${axiosError.response.status}): ${axiosError.response.statusText}`);
|
|
119
122
|
}
|
|
120
123
|
} else if (axiosError.request) {
|
|
121
124
|
debugLog(`[HTTP POST] 未收到响应`);
|
|
122
125
|
debugLog(`[HTTP POST] 错误信息: ${axiosError.message}`);
|
|
123
|
-
throw new
|
|
126
|
+
throw new AppError$1(ERROR_CODES$1.NETWORK_ERROR, `网络错误: ${axiosError.message}`);
|
|
124
127
|
} else {
|
|
125
128
|
debugLog(`[HTTP POST] 请求配置错误`);
|
|
126
129
|
debugLog(`[HTTP POST] 错误信息: ${axiosError.message}`);
|
|
127
|
-
throw new
|
|
130
|
+
throw new AppError$1(ERROR_CODES$1.HTTP_ERROR, `请求配置错误: ${axiosError.message}`);
|
|
128
131
|
}
|
|
129
132
|
}
|
|
130
133
|
}
|
|
@@ -4135,6 +4138,74 @@ class LocalInstaller {
|
|
|
4135
4138
|
}
|
|
4136
4139
|
debugLog("[验证配置] 配置验证通过");
|
|
4137
4140
|
}
|
|
4141
|
+
async installDependencies(targetPath) {
|
|
4142
|
+
this.spinner.prefixText = this.prefixText;
|
|
4143
|
+
this.spinner.text = `${chalk.cyan("安装依赖")} ${chalk.dim("→")} ${chalk.yellow("正在安装...")}`;
|
|
4144
|
+
const checkDependencies = () => {
|
|
4145
|
+
try {
|
|
4146
|
+
const nodeModulesPath = path.join(targetPath, "node_modules");
|
|
4147
|
+
const packageJsonPath = path.join(targetPath, "package.json");
|
|
4148
|
+
try {
|
|
4149
|
+
fsSync.accessSync(nodeModulesPath);
|
|
4150
|
+
} catch {
|
|
4151
|
+
return false;
|
|
4152
|
+
}
|
|
4153
|
+
const packageJson = JSON.parse(fsSync.readFileSync(packageJsonPath, "utf-8"));
|
|
4154
|
+
const dependencies = Object.keys(packageJson.dependencies || {});
|
|
4155
|
+
for (const dep of dependencies) {
|
|
4156
|
+
const depPath = path.join(nodeModulesPath, dep);
|
|
4157
|
+
if (!fsSync.existsSync(depPath)) {
|
|
4158
|
+
debugLog(`[依赖检查] 缺少依赖: ${dep}`);
|
|
4159
|
+
return false;
|
|
4160
|
+
}
|
|
4161
|
+
}
|
|
4162
|
+
return true;
|
|
4163
|
+
} catch {
|
|
4164
|
+
return false;
|
|
4165
|
+
}
|
|
4166
|
+
};
|
|
4167
|
+
const runInstall = () => {
|
|
4168
|
+
try {
|
|
4169
|
+
debugLog("[安装依赖] 执行 npm install");
|
|
4170
|
+
execSync("npm install --production", {
|
|
4171
|
+
cwd: targetPath,
|
|
4172
|
+
stdio: "pipe",
|
|
4173
|
+
timeout: 12e4
|
|
4174
|
+
});
|
|
4175
|
+
debugLog("[安装依赖] npm install 执行成功");
|
|
4176
|
+
return true;
|
|
4177
|
+
} catch (error) {
|
|
4178
|
+
const errorMsg = error.stderr?.toString() || error.message || "未知错误";
|
|
4179
|
+
debugLog(`[安装依赖] npm install 失败: ${errorMsg}`);
|
|
4180
|
+
return false;
|
|
4181
|
+
}
|
|
4182
|
+
};
|
|
4183
|
+
if (checkDependencies()) {
|
|
4184
|
+
debugLog("[安装依赖] 依赖检查通过");
|
|
4185
|
+
this.prefixText += chalk.green(`✓ 依赖检查通过
|
|
4186
|
+
`);
|
|
4187
|
+
return;
|
|
4188
|
+
}
|
|
4189
|
+
debugLog("[安装依赖] 依赖检查失败,尝试重新安装...");
|
|
4190
|
+
if (runInstall()) {
|
|
4191
|
+
if (checkDependencies()) {
|
|
4192
|
+
this.prefixText += chalk.green(`✓ 依赖安装成功
|
|
4193
|
+
`);
|
|
4194
|
+
return;
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
4197
|
+
debugLog("[安装依赖] 第一次安装失败,尝试完整安装...");
|
|
4198
|
+
if (runInstall()) {
|
|
4199
|
+
if (checkDependencies()) {
|
|
4200
|
+
this.prefixText += chalk.green(`✓ 依赖安装成功
|
|
4201
|
+
`);
|
|
4202
|
+
return;
|
|
4203
|
+
}
|
|
4204
|
+
}
|
|
4205
|
+
this.prefixText += chalk.red(`✗ 依赖安装失败
|
|
4206
|
+
`);
|
|
4207
|
+
throw new AppError$1(ERROR_CODES$1.NPM_INSTALL_FAILED, "插件依赖安装失败,请检查网络和 npm 配置");
|
|
4208
|
+
}
|
|
4138
4209
|
async install() {
|
|
4139
4210
|
try {
|
|
4140
4211
|
debugLog("[安装开始]");
|
|
@@ -4279,6 +4350,7 @@ class LocalInstaller {
|
|
|
4279
4350
|
throw new AppError$1(ERROR_CODES$1.NPM_INSTALL_FAILED, "插件解压后未找到 package.json");
|
|
4280
4351
|
}
|
|
4281
4352
|
debugLog("[下载插件] 插件解压成功");
|
|
4353
|
+
await this.installDependencies(paths.target);
|
|
4282
4354
|
this.prefixText += chalk.green(`✓ 插件下载完成
|
|
4283
4355
|
`);
|
|
4284
4356
|
try {
|
|
@@ -4455,9 +4527,14 @@ class LocalInstaller {
|
|
|
4455
4527
|
allowInsecureTls: true,
|
|
4456
4528
|
// 允许原始 JSON 载荷
|
|
4457
4529
|
allowRawJsonPayload: true,
|
|
4530
|
+
// 用户 ID
|
|
4531
|
+
userId: boundConfig.userId,
|
|
4458
4532
|
accounts: {
|
|
4459
4533
|
// 账户配置(agentId 从服务器获取)
|
|
4460
|
-
default: {
|
|
4534
|
+
default: {
|
|
4535
|
+
enabled: true,
|
|
4536
|
+
agentId: boundConfig.agentId
|
|
4537
|
+
}
|
|
4461
4538
|
}
|
|
4462
4539
|
}
|
|
4463
4540
|
},
|
|
@@ -4468,9 +4545,11 @@ class LocalInstaller {
|
|
|
4468
4545
|
// 网关端口
|
|
4469
4546
|
port: 18789,
|
|
4470
4547
|
// 绑定地址:'loopback' | 'lan' | 'all'
|
|
4471
|
-
bind: "
|
|
4472
|
-
//
|
|
4473
|
-
auth: {
|
|
4548
|
+
bind: "lan",
|
|
4549
|
+
// 认证模式(token字段未设置,是因为需要使用原始配置的token)
|
|
4550
|
+
auth: {
|
|
4551
|
+
mode: "token"
|
|
4552
|
+
},
|
|
4474
4553
|
// Tailscale 配置
|
|
4475
4554
|
tailscale: { mode: "off", resetOnExit: false },
|
|
4476
4555
|
nodes: {
|
|
@@ -4481,9 +4560,7 @@ class LocalInstaller {
|
|
|
4481
4560
|
"screen.record",
|
|
4482
4561
|
"contacts.add",
|
|
4483
4562
|
"calendar.add",
|
|
4484
|
-
"reminders.add"
|
|
4485
|
-
"sms.send",
|
|
4486
|
-
"sms.search"
|
|
4563
|
+
"reminders.add"
|
|
4487
4564
|
]
|
|
4488
4565
|
},
|
|
4489
4566
|
controlUi: {
|
|
@@ -4505,9 +4582,9 @@ class LocalInstaller {
|
|
|
4505
4582
|
// logging: 日志配置
|
|
4506
4583
|
logging: {
|
|
4507
4584
|
// 日志级别:'debug' | 'info' | 'warn' | 'error'
|
|
4508
|
-
level: "
|
|
4585
|
+
level: "trace",
|
|
4509
4586
|
// 控制台日志级别
|
|
4510
|
-
consoleLevel: "
|
|
4587
|
+
consoleLevel: "trace",
|
|
4511
4588
|
// 控制台样式:'pretty' | 'basic' | 'raw'
|
|
4512
4589
|
consoleStyle: "pretty",
|
|
4513
4590
|
// 敏感信息脱敏:'off' | 'keys' | 'all'
|
|
@@ -4521,15 +4598,21 @@ class LocalInstaller {
|
|
|
4521
4598
|
plugins: {
|
|
4522
4599
|
// 允许的插件列表
|
|
4523
4600
|
allow: [config.PLUGIN_NAME],
|
|
4524
|
-
//
|
|
4601
|
+
// 插件安装跟踪(支持 openclaw plugins update 命令)
|
|
4525
4602
|
installs: {
|
|
4526
4603
|
[config.PLUGIN_NAME]: {
|
|
4604
|
+
// 安装来源
|
|
4605
|
+
source: "npm",
|
|
4527
4606
|
// npm 包名
|
|
4528
|
-
|
|
4607
|
+
spec: PLUGIN_PACKAGE_NAME$1,
|
|
4529
4608
|
// 安装路径
|
|
4530
4609
|
installPath: paths.target
|
|
4531
4610
|
}
|
|
4532
4611
|
},
|
|
4612
|
+
// 插件加载路径(本地开发或自定义安装位置)
|
|
4613
|
+
load: {
|
|
4614
|
+
paths: [paths.target]
|
|
4615
|
+
},
|
|
4533
4616
|
// 插件条目启用状态
|
|
4534
4617
|
entries: {
|
|
4535
4618
|
[config.PLUGIN_NAME]: { enabled: true }
|
|
@@ -4696,8 +4779,11 @@ const ERROR_CODES = {
|
|
|
4696
4779
|
APP_KEY_REQUIRED: "APP_KEY_REQUIRED",
|
|
4697
4780
|
APP_SECRET_REQUIRED: "APP_SECRET_REQUIRED",
|
|
4698
4781
|
NODE_VERSION_LOW: "NODE_VERSION_LOW",
|
|
4782
|
+
NODE_NOT_FOUND: "NODE_NOT_FOUND",
|
|
4699
4783
|
NPM_NOT_FOUND: "NPM_NOT_FOUND",
|
|
4700
|
-
NPM_INSTALL_FAILED: "NPM_INSTALL_FAILED"
|
|
4784
|
+
NPM_INSTALL_FAILED: "NPM_INSTALL_FAILED",
|
|
4785
|
+
CONFIG_WRITE_FAILED: "CONFIG_WRITE_FAILED",
|
|
4786
|
+
PLUGIN_EXTRACT_FAILED: "PLUGIN_EXTRACT_FAILED"
|
|
4701
4787
|
};
|
|
4702
4788
|
class AppError2 extends Error {
|
|
4703
4789
|
constructor(code, message) {
|
|
@@ -4746,6 +4832,74 @@ class BoxInstaller {
|
|
|
4746
4832
|
}
|
|
4747
4833
|
debugLog("[验证配置] 配置检查通过");
|
|
4748
4834
|
}
|
|
4835
|
+
async installDependencies(targetPath) {
|
|
4836
|
+
this.spinner.prefixText = this.prefixText;
|
|
4837
|
+
this.spinner.text = `${chalk.cyan("安装依赖")} ${chalk.dim("→")} ${chalk.yellow("正在安装...")}`;
|
|
4838
|
+
const checkDependencies = () => {
|
|
4839
|
+
try {
|
|
4840
|
+
const nodeModulesPath = path.join(targetPath, "node_modules");
|
|
4841
|
+
const packageJsonPath = path.join(targetPath, "package.json");
|
|
4842
|
+
try {
|
|
4843
|
+
fsSync.accessSync(nodeModulesPath);
|
|
4844
|
+
} catch {
|
|
4845
|
+
return false;
|
|
4846
|
+
}
|
|
4847
|
+
const packageJson = JSON.parse(fsSync.readFileSync(packageJsonPath, "utf-8"));
|
|
4848
|
+
const dependencies = Object.keys(packageJson.dependencies || {});
|
|
4849
|
+
for (const dep of dependencies) {
|
|
4850
|
+
const depPath = path.join(nodeModulesPath, dep);
|
|
4851
|
+
if (!fsSync.existsSync(depPath)) {
|
|
4852
|
+
debugLog(`[依赖检查] 缺少依赖: ${dep}`);
|
|
4853
|
+
return false;
|
|
4854
|
+
}
|
|
4855
|
+
}
|
|
4856
|
+
return true;
|
|
4857
|
+
} catch {
|
|
4858
|
+
return false;
|
|
4859
|
+
}
|
|
4860
|
+
};
|
|
4861
|
+
const runInstall = () => {
|
|
4862
|
+
try {
|
|
4863
|
+
debugLog("[安装依赖] 执行 npm install");
|
|
4864
|
+
execSync("npm install --production", {
|
|
4865
|
+
cwd: targetPath,
|
|
4866
|
+
stdio: "pipe",
|
|
4867
|
+
timeout: 12e4
|
|
4868
|
+
});
|
|
4869
|
+
debugLog("[安装依赖] npm install 执行成功");
|
|
4870
|
+
return true;
|
|
4871
|
+
} catch (error) {
|
|
4872
|
+
const errorMsg = error.stderr?.toString() || error.message || "未知错误";
|
|
4873
|
+
debugLog(`[安装依赖] npm install 失败: ${errorMsg}`);
|
|
4874
|
+
return false;
|
|
4875
|
+
}
|
|
4876
|
+
};
|
|
4877
|
+
if (checkDependencies()) {
|
|
4878
|
+
debugLog("[安装依赖] 依赖检查通过");
|
|
4879
|
+
this.prefixText += chalk.green(`✓ 依赖检查通过
|
|
4880
|
+
`);
|
|
4881
|
+
return;
|
|
4882
|
+
}
|
|
4883
|
+
debugLog("[安装依赖] 依赖检查失败,尝试重新安装...");
|
|
4884
|
+
if (runInstall()) {
|
|
4885
|
+
if (checkDependencies()) {
|
|
4886
|
+
this.prefixText += chalk.green(`✓ 依赖安装成功
|
|
4887
|
+
`);
|
|
4888
|
+
return;
|
|
4889
|
+
}
|
|
4890
|
+
}
|
|
4891
|
+
debugLog("[安装依赖] 第一次安装失败,尝试完整安装...");
|
|
4892
|
+
if (runInstall()) {
|
|
4893
|
+
if (checkDependencies()) {
|
|
4894
|
+
this.prefixText += chalk.green(`✓ 依赖安装成功
|
|
4895
|
+
`);
|
|
4896
|
+
return;
|
|
4897
|
+
}
|
|
4898
|
+
}
|
|
4899
|
+
this.prefixText += chalk.red(`✗ 依赖安装失败
|
|
4900
|
+
`);
|
|
4901
|
+
throw new AppError2(ERROR_CODES.NPM_INSTALL_FAILED, "插件依赖安装失败,请检查网络和 npm 配置");
|
|
4902
|
+
}
|
|
4749
4903
|
getPaths() {
|
|
4750
4904
|
const home = getHomeDir();
|
|
4751
4905
|
const openclawDir = path.join(home, ".openclaw");
|
|
@@ -4869,12 +5023,13 @@ class BoxInstaller {
|
|
|
4869
5023
|
debugLog(`[解压插件] 插件解压成功: ${paths.target}`);
|
|
4870
5024
|
this.prefixText += chalk.green(`✓ 插件解压成功
|
|
4871
5025
|
`);
|
|
5026
|
+
await this.installDependencies(paths.target);
|
|
4872
5027
|
await fs.rm(paths.temp, { recursive: true, force: true });
|
|
4873
5028
|
debugLog(`[解压插件] 清理临时文件成功`);
|
|
4874
5029
|
this.prefixText += chalk.green(`✓ 清理临时文件成功
|
|
4875
5030
|
`);
|
|
4876
5031
|
} else {
|
|
4877
|
-
throw new
|
|
5032
|
+
throw new AppError2(ERROR_CODES.PLUGIN_EXTRACT_FAILED, "解压失败:package 目录不存在");
|
|
4878
5033
|
}
|
|
4879
5034
|
} catch (error) {
|
|
4880
5035
|
debugLog(`[解压插件] 解压失败: ${error.message}`);
|
|
@@ -5046,6 +5201,8 @@ class BoxInstaller {
|
|
|
5046
5201
|
allowInsecureTls: true,
|
|
5047
5202
|
// 允许原始 JSON 载荷
|
|
5048
5203
|
allowRawJsonPayload: true,
|
|
5204
|
+
// 用户 ID
|
|
5205
|
+
userId: "",
|
|
5049
5206
|
accounts: {
|
|
5050
5207
|
// 账户配置(agentId 为空表示待分配)
|
|
5051
5208
|
default: { enabled: true, agentId: "" }
|
|
@@ -5114,15 +5271,21 @@ class BoxInstaller {
|
|
|
5114
5271
|
plugins: {
|
|
5115
5272
|
// 允许的插件列表
|
|
5116
5273
|
allow: [config.PLUGIN_NAME],
|
|
5117
|
-
//
|
|
5274
|
+
// 插件安装跟踪(支持 openclaw plugins update 命令)
|
|
5118
5275
|
installs: {
|
|
5119
5276
|
[config.PLUGIN_NAME]: {
|
|
5277
|
+
// 安装来源
|
|
5278
|
+
source: "npm",
|
|
5120
5279
|
// npm 包名
|
|
5121
|
-
|
|
5280
|
+
spec: PLUGIN_PACKAGE_NAME,
|
|
5122
5281
|
// 安装路径
|
|
5123
5282
|
installPath: paths.target
|
|
5124
5283
|
}
|
|
5125
5284
|
},
|
|
5285
|
+
// 插件加载路径
|
|
5286
|
+
load: {
|
|
5287
|
+
paths: [paths.target]
|
|
5288
|
+
},
|
|
5126
5289
|
// 插件条目启用状态
|
|
5127
5290
|
entries: {
|
|
5128
5291
|
[config.PLUGIN_NAME]: { enabled: true }
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workclaw/cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.25",
|
|
5
5
|
"description": "WorkClaw CLI 工具 - 用于初始化和配置 WorkClaw 插件",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"keywords": [
|
|
@@ -38,4 +38,4 @@
|
|
|
38
38
|
"semver": "^7.7.1",
|
|
39
39
|
"tar": "^7.4.0"
|
|
40
40
|
}
|
|
41
|
-
}
|
|
41
|
+
}
|