@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 Error(`请求失败 (${axiosError.response.status}): ${responseData}`);
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 Error(`请求失败 (${axiosError.response.status}): ${responseData.message}`);
119
+ throw new AppError$1(ERROR_CODES$1.HTTP_ERROR, `请求失败 (${axiosError.response.status}): ${responseData.message}`);
117
120
  } else {
118
- throw new Error(`请求失败 (${axiosError.response.status}): ${axiosError.response.statusText}`);
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 Error(`网络错误: ${axiosError.message}`);
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 Error(`请求配置错误: ${axiosError.message}`);
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: { enabled: true, agentId: boundConfig.agentId }
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: "loopback",
4472
- // 认证模式
4473
- auth: { mode: "token", token: "" },
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: "info",
4585
+ level: "trace",
4509
4586
  // 控制台日志级别
4510
- consoleLevel: "info",
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
- installSource: PLUGIN_PACKAGE_NAME$1,
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 Error("解压失败:package 目录不存在");
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
- installSource: PLUGIN_PACKAGE_NAME,
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
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import("./index-CznpA35l.js").then((cli) => {
2
+ import("./index-C1oCz010.js").then((cli) => {
3
3
  cli.default();
4
4
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@workclaw/cli",
3
3
  "type": "module",
4
- "version": "1.0.22",
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
+ }