@workclaw/cli 1.0.27 → 1.0.30
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 +119 -161
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/box/error/index.d.ts +30 -0
- package/dist/box/error/index.d.ts.map +1 -0
- package/dist/box/index.d.ts +3 -0
- package/dist/box/index.d.ts.map +1 -0
- package/dist/box/installer/index.d.ts +2 -0
- package/dist/box/installer/index.d.ts.map +1 -0
- package/dist/box/installer/installer.d.ts +16 -0
- package/dist/box/installer/installer.d.ts.map +1 -0
- package/dist/box/src/box.d.ts +3 -0
- package/dist/box/src/box.d.ts.map +1 -0
- package/dist/box/types/index.d.ts +30 -0
- package/dist/box/types/index.d.ts.map +1 -0
- package/dist/box/utils/index.d.ts +2 -0
- package/dist/box/utils/index.d.ts.map +1 -0
- package/dist/box/utils/path.d.ts +2 -0
- package/dist/box/utils/path.d.ts.map +1 -0
- package/dist/command/index.d.ts +3 -0
- package/dist/command/index.d.ts.map +1 -0
- package/dist/command/src/base-command.d.ts +12 -0
- package/dist/command/src/base-command.d.ts.map +1 -0
- package/dist/command/types/index.d.ts +14 -0
- package/dist/command/types/index.d.ts.map +1 -0
- package/dist/{index-BWLa_Wav.js → index-DCWFh-f4.js} +1461 -1689
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/lib/command/base-command.d.ts +16 -0
- package/dist/lib/command/base-command.d.ts.map +1 -0
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/local/apis/index.d.ts +11 -0
- package/dist/local/apis/index.d.ts.map +1 -0
- package/dist/local/error/index.d.ts +33 -0
- package/dist/local/error/index.d.ts.map +1 -0
- package/dist/local/index.d.ts +3 -0
- package/dist/local/index.d.ts.map +1 -0
- package/dist/local/installer/index.d.ts +2 -0
- package/dist/local/installer/index.d.ts.map +1 -0
- package/dist/local/installer/installer.d.ts +16 -0
- package/dist/local/installer/installer.d.ts.map +1 -0
- package/dist/local/src/local.d.ts +3 -0
- package/dist/local/src/local.d.ts.map +1 -0
- package/dist/local/types/index.d.ts +41 -0
- package/dist/local/types/index.d.ts.map +1 -0
- package/dist/local/utils/crypto.d.ts +2 -0
- package/dist/local/utils/crypto.d.ts.map +1 -0
- package/dist/local/utils/index.d.ts +4 -0
- package/dist/local/utils/index.d.ts.map +1 -0
- package/dist/local/utils/path.d.ts +9 -0
- package/dist/local/utils/path.d.ts.map +1 -0
- package/dist/shared/config/index.d.ts +48 -0
- package/dist/shared/config/index.d.ts.map +1 -0
- package/dist/shared/utils/debug.d.ts +4 -0
- package/dist/shared/utils/debug.d.ts.map +1 -0
- package/dist/shared/utils/index.d.ts +4 -0
- package/dist/shared/utils/index.d.ts.map +1 -0
- package/dist/shared/utils/logger.d.ts +14 -0
- package/dist/shared/utils/logger.d.ts.map +1 -0
- package/dist/utils/config-default.d.ts +28 -0
- package/dist/utils/config-default.d.ts.map +1 -0
- package/dist/utils/config.d.ts +21 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/crypto.d.ts +13 -0
- package/dist/utils/crypto.d.ts.map +1 -0
- package/dist/utils/error.d.ts +34 -0
- package/dist/utils/error.d.ts.map +1 -0
- package/dist/utils/http.d.ts +27 -0
- package/dist/utils/http.d.ts.map +1 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/path.d.ts +23 -0
- package/dist/utils/path.d.ts.map +1 -0
- package/package.json +2 -4
|
@@ -3,15 +3,13 @@ import path, { resolve, dirname } from "node:path";
|
|
|
3
3
|
import process$1 from "node:process";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { Command } from "commander";
|
|
6
|
-
import { execSync } from "node:child_process";
|
|
6
|
+
import { exec, execSync } from "node:child_process";
|
|
7
7
|
import boxen from "boxen";
|
|
8
8
|
import chalk from "chalk";
|
|
9
9
|
import inquirer from "inquirer";
|
|
10
|
-
import * as nodeEmoji from "node-emoji";
|
|
11
10
|
import semver from "semver";
|
|
12
11
|
import fs from "node:fs/promises";
|
|
13
12
|
import ora from "ora";
|
|
14
|
-
import * as tar from "tar";
|
|
15
13
|
import axios from "axios";
|
|
16
14
|
import "node:os";
|
|
17
15
|
let isDebug = false;
|
|
@@ -24,17 +22,11 @@ function debugLog(...args) {
|
|
|
24
22
|
}
|
|
25
23
|
}
|
|
26
24
|
const ERROR_CODES$1 = {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
LOGIN_FAILED: "LOGIN_FAILED",
|
|
30
|
-
GET_BOUND_CONFIG_FAILED: "GET_BOUND_CONFIG_FAILED",
|
|
25
|
+
APP_KEY_REQUIRED: "APP_KEY_REQUIRED",
|
|
26
|
+
APP_SECRET_REQUIRED: "APP_SECRET_REQUIRED",
|
|
31
27
|
NODE_VERSION_LOW: "NODE_VERSION_LOW",
|
|
32
|
-
NODE_NOT_FOUND: "NODE_NOT_FOUND",
|
|
33
28
|
NPM_NOT_FOUND: "NPM_NOT_FOUND",
|
|
34
|
-
NPM_INSTALL_FAILED: "NPM_INSTALL_FAILED"
|
|
35
|
-
CONFIG_WRITE_FAILED: "CONFIG_WRITE_FAILED",
|
|
36
|
-
HTTP_ERROR: "HTTP_ERROR",
|
|
37
|
-
NETWORK_ERROR: "NETWORK_ERROR"
|
|
29
|
+
NPM_INSTALL_FAILED: "NPM_INSTALL_FAILED"
|
|
38
30
|
};
|
|
39
31
|
let AppError$1 = class AppError extends Error {
|
|
40
32
|
constructor(code, message) {
|
|
@@ -84,305 +76,829 @@ const TEST_CONFIG = {
|
|
|
84
76
|
function getConfig(env) {
|
|
85
77
|
return env === "test" ? TEST_CONFIG : CONFIG;
|
|
86
78
|
}
|
|
87
|
-
function
|
|
88
|
-
return
|
|
89
|
-
timeout: 1e4,
|
|
90
|
-
headers: {
|
|
91
|
-
"Content-Type": "application/json"
|
|
92
|
-
}
|
|
93
|
-
});
|
|
79
|
+
function getHomeDir$1() {
|
|
80
|
+
return process$1.env.HOME || process$1.env.USERPROFILE || "";
|
|
94
81
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const response = await client.post(url, data, config);
|
|
102
|
-
debugLog(`[HTTP POST] 响应状态: ${response.status}`);
|
|
103
|
-
debugLog(`[HTTP POST] 响应内容: ${JSON.stringify(response.data)}`);
|
|
104
|
-
return {
|
|
105
|
-
status: response.status,
|
|
106
|
-
data: response.data
|
|
107
|
-
};
|
|
108
|
-
} catch (error) {
|
|
109
|
-
const axiosError = error;
|
|
110
|
-
if (axiosError.response) {
|
|
111
|
-
const responseData = axiosError.response.data;
|
|
112
|
-
debugLog(`[HTTP POST] 响应状态: ${axiosError.response.status}`);
|
|
113
|
-
debugLog(`[HTTP POST] 响应状态文本: ${axiosError.response.statusText}`);
|
|
114
|
-
debugLog(`[HTTP POST] 响应数据: ${JSON.stringify(responseData)}`);
|
|
115
|
-
if (typeof responseData === "string") {
|
|
116
|
-
throw new AppError$1(ERROR_CODES$1.HTTP_ERROR, `请求失败 (${axiosError.response.status}): ${responseData}`);
|
|
117
|
-
} else if (responseData && typeof responseData === "object" && "message" in responseData) {
|
|
118
|
-
throw new AppError$1(ERROR_CODES$1.HTTP_ERROR, `请求失败 (${axiosError.response.status}): ${responseData.message}`);
|
|
82
|
+
const PLUGIN_PACKAGE_NAME$1 = "@workclaw/openclaw-workclaw";
|
|
83
|
+
function execAsync$1(command, options) {
|
|
84
|
+
return new Promise((resolve2, reject) => {
|
|
85
|
+
exec(command, { cwd: options.cwd, timeout: options.timeout }, (error, stdout, stderr) => {
|
|
86
|
+
if (error) {
|
|
87
|
+
reject(new Error(stderr || error.message));
|
|
119
88
|
} else {
|
|
120
|
-
|
|
89
|
+
resolve2(stdout);
|
|
121
90
|
}
|
|
122
|
-
} else if (axiosError.request) {
|
|
123
|
-
debugLog(`[HTTP POST] 未收到响应`);
|
|
124
|
-
debugLog(`[HTTP POST] 错误信息: ${axiosError.message}`);
|
|
125
|
-
throw new AppError$1(ERROR_CODES$1.NETWORK_ERROR, `网络错误: ${axiosError.message}`);
|
|
126
|
-
} else {
|
|
127
|
-
debugLog(`[HTTP POST] 请求配置错误`);
|
|
128
|
-
debugLog(`[HTTP POST] 错误信息: ${axiosError.message}`);
|
|
129
|
-
throw new AppError$1(ERROR_CODES$1.HTTP_ERROR, `请求配置错误: ${axiosError.message}`);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
async function login(phone, password, env) {
|
|
134
|
-
const config = getConfig(env);
|
|
135
|
-
const url = `${config.API.TUZAI_BASE_URL}/user/login/pass`;
|
|
136
|
-
debugLog("[登录] 开始登录...");
|
|
137
|
-
debugLog(`[登录] 请求地址: ${url}`);
|
|
138
|
-
debugLog(`[登录] 请求参数: phone=${phone}, password=***`);
|
|
139
|
-
try {
|
|
140
|
-
const response = await httpPost(url, {
|
|
141
|
-
phone,
|
|
142
|
-
userPass: password
|
|
143
91
|
});
|
|
144
|
-
|
|
145
|
-
debugLog(`[登录] 响应数据: ${JSON.stringify(data)}`);
|
|
146
|
-
if (data.code === 200 && data.data?.token) {
|
|
147
|
-
debugLog("[登录] 登录成功,获取到 token");
|
|
148
|
-
return data.data.token;
|
|
149
|
-
}
|
|
150
|
-
debugLog("[登录] 登录失败");
|
|
151
|
-
throw new AppError$1(ERROR_CODES$1.LOGIN_FAILED, data.message || "登录失败");
|
|
152
|
-
} catch (error) {
|
|
153
|
-
if (error instanceof AppError$1) {
|
|
154
|
-
throw error;
|
|
155
|
-
}
|
|
156
|
-
debugLog(`[登录] 发生错误: ${error.message}`);
|
|
157
|
-
throw new AppError$1(ERROR_CODES$1.LOGIN_FAILED, error.message);
|
|
158
|
-
}
|
|
92
|
+
});
|
|
159
93
|
}
|
|
160
|
-
|
|
161
|
-
const
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
phone,
|
|
170
|
-
localCode: "001"
|
|
171
|
-
}, {
|
|
172
|
-
headers: {
|
|
173
|
-
Authorization: token
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
const data = response.data;
|
|
177
|
-
debugLog(`[获取绑定配置] 响应数据: ${JSON.stringify(data)}`);
|
|
178
|
-
if (data.code === 200 && data.data) {
|
|
179
|
-
const boundConfig = {
|
|
180
|
-
appKey: data.data.app_key,
|
|
181
|
-
appSecret: data.data.app_secret,
|
|
182
|
-
userId: data.data.user_id,
|
|
183
|
-
agentId: data.data.agent_id || data.data.agents?.[0]?.id,
|
|
184
|
-
modelApiKey: data.data.model_api_key,
|
|
185
|
-
modelApiBaseUrl: data.data.model_api_base_url
|
|
186
|
-
};
|
|
187
|
-
debugLog("[获取绑定配置] 获取绑定配置成功");
|
|
188
|
-
debugLog(`[获取绑定配置] appKey: ${boundConfig.appKey}`);
|
|
189
|
-
debugLog(`[获取绑定配置] appSecret: ${boundConfig.appSecret ? "***" : "undefined"}`);
|
|
190
|
-
debugLog(`[获取绑定配置] userId: ${boundConfig.userId}`);
|
|
191
|
-
debugLog(`[获取绑定配置] agentId: ${boundConfig.agentId}`);
|
|
192
|
-
debugLog(`[获取绑定配置] modelApiKey: ${boundConfig.modelApiKey || "undefined"}`);
|
|
193
|
-
debugLog(`[获取绑定配置] modelApiBaseUrl: ${boundConfig.modelApiBaseUrl || "undefined"}`);
|
|
194
|
-
if (!boundConfig.appKey || !boundConfig.appSecret || !boundConfig.agentId) {
|
|
195
|
-
debugLog("[获取绑定配置] 缺少必要字段");
|
|
196
|
-
throw new AppError$1(ERROR_CODES$1.GET_BOUND_CONFIG_FAILED, "获取绑定配置失败:缺少必要字段");
|
|
197
|
-
}
|
|
198
|
-
return boundConfig;
|
|
199
|
-
}
|
|
200
|
-
debugLog("[获取绑定配置] 获取绑定配置失败");
|
|
201
|
-
throw new AppError$1(ERROR_CODES$1.GET_BOUND_CONFIG_FAILED, data.message || data.msg || "获取绑定配置失败");
|
|
202
|
-
} catch (error) {
|
|
203
|
-
if (error instanceof AppError$1) {
|
|
204
|
-
throw error;
|
|
94
|
+
function deepMerge$1(target, source) {
|
|
95
|
+
const result = { ...target };
|
|
96
|
+
for (const key in source) {
|
|
97
|
+
const sourceValue = source[key];
|
|
98
|
+
const targetValue = target[key];
|
|
99
|
+
if (sourceValue !== void 0 && sourceValue !== null && typeof sourceValue === "object" && !Array.isArray(sourceValue) && typeof targetValue === "object" && targetValue !== null && !Array.isArray(targetValue)) {
|
|
100
|
+
result[key] = deepMerge$1(targetValue, sourceValue);
|
|
101
|
+
} else if (sourceValue !== void 0) {
|
|
102
|
+
result[key] = sourceValue;
|
|
205
103
|
}
|
|
206
|
-
debugLog(`[获取绑定配置] 发生错误: ${error.message}`);
|
|
207
|
-
throw new AppError$1(ERROR_CODES$1.GET_BOUND_CONFIG_FAILED, error.message);
|
|
208
104
|
}
|
|
105
|
+
return result;
|
|
209
106
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
function op_and(x, y) {
|
|
215
|
-
return x & y;
|
|
216
|
-
}
|
|
217
|
-
function op_or(x, y) {
|
|
218
|
-
return x | y;
|
|
219
|
-
}
|
|
220
|
-
function op_xor(x, y) {
|
|
221
|
-
return x ^ y;
|
|
222
|
-
}
|
|
223
|
-
function op_andnot(x, y) {
|
|
224
|
-
return x & ~y;
|
|
225
|
-
}
|
|
226
|
-
function lbit(x) {
|
|
227
|
-
if (x == 0) {
|
|
228
|
-
return -1;
|
|
107
|
+
class BoxInstaller {
|
|
108
|
+
constructor(config) {
|
|
109
|
+
this.config = config;
|
|
110
|
+
this.spinner = ora({ color: "cyan" }).start();
|
|
229
111
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
112
|
+
spinner;
|
|
113
|
+
prefixText = "";
|
|
114
|
+
validateConfig() {
|
|
115
|
+
debugLog("[验证配置] 检查 appKey 和 appSecret...");
|
|
116
|
+
if (!this.config.appKey) {
|
|
117
|
+
throw new AppError$1(ERROR_CODES$1.APP_KEY_REQUIRED, "AppKey 不能为空,请使用 --app-key 参数");
|
|
118
|
+
}
|
|
119
|
+
if (!this.config.appSecret) {
|
|
120
|
+
throw new AppError$1(ERROR_CODES$1.APP_SECRET_REQUIRED, "AppSecret 不能为空,请使用 --app-secret 参数");
|
|
121
|
+
}
|
|
122
|
+
debugLog("[验证配置] 配置检查通过");
|
|
234
123
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
124
|
+
getPaths() {
|
|
125
|
+
const home = getHomeDir$1();
|
|
126
|
+
const openclawDir = path.join(home, ".openclaw");
|
|
127
|
+
const extensionsDir = path.join(openclawDir, "extensions");
|
|
128
|
+
const targetDir = path.join(extensionsDir, "openclaw-workclaw");
|
|
129
|
+
const configFile = path.join(openclawDir, "openclaw.json");
|
|
130
|
+
const workspaceDir = path.join(openclawDir, "workspace");
|
|
131
|
+
const tempDir = path.join(openclawDir, ".temp");
|
|
132
|
+
return {
|
|
133
|
+
home,
|
|
134
|
+
extensions: extensionsDir,
|
|
135
|
+
target: targetDir,
|
|
136
|
+
config: configFile,
|
|
137
|
+
workspace: workspaceDir,
|
|
138
|
+
temp: tempDir
|
|
139
|
+
};
|
|
238
140
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
141
|
+
updateSpinner(text) {
|
|
142
|
+
this.spinner.prefixText = this.prefixText;
|
|
143
|
+
this.spinner.text = chalk.cyan(text);
|
|
144
|
+
debugLog(`[Spinner] ${text}`);
|
|
242
145
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
r += 2;
|
|
146
|
+
getPrefixText() {
|
|
147
|
+
return this.prefixText;
|
|
246
148
|
}
|
|
247
|
-
|
|
248
|
-
|
|
149
|
+
async install() {
|
|
150
|
+
try {
|
|
151
|
+
debugLog("[盒子安装] 开始安装...");
|
|
152
|
+
this.validateConfig();
|
|
153
|
+
this.prefixText += chalk.green(` ✓ 配置验证完成
|
|
154
|
+
`);
|
|
155
|
+
this.updateSpinner("配置验证完成");
|
|
156
|
+
const paths = this.getPaths();
|
|
157
|
+
await this.doCleanOldFiles(paths);
|
|
158
|
+
await this.doDownloadFromNpm();
|
|
159
|
+
await this.doUpdateConfig(paths);
|
|
160
|
+
this.spinner.stop();
|
|
161
|
+
debugLog("[盒子安装] 安装完成");
|
|
162
|
+
} catch (error) {
|
|
163
|
+
this.spinner.stop();
|
|
164
|
+
debugLog(`[盒子安装] 安装失败: ${error.message}`);
|
|
165
|
+
throw error;
|
|
166
|
+
}
|
|
249
167
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
168
|
+
async doCleanOldFiles(paths) {
|
|
169
|
+
debugLog("[清理旧版本] 开始清理旧版本...");
|
|
170
|
+
this.prefixText += chalk.green(` ✓ 开始清理旧版本
|
|
171
|
+
`);
|
|
172
|
+
this.updateSpinner("正在清理旧版本...");
|
|
173
|
+
try {
|
|
174
|
+
await fs.access(paths.target);
|
|
175
|
+
debugLog("[清理旧版本] 删除旧版本目录...");
|
|
176
|
+
await fs.rm(paths.target, { recursive: true, force: true });
|
|
177
|
+
this.prefixText += chalk.green(` ✓ 旧版本清理成功
|
|
178
|
+
`);
|
|
179
|
+
debugLog("[清理旧版本] 旧版本清理成功");
|
|
180
|
+
} catch {
|
|
181
|
+
debugLog("[清理旧版本] 无旧版本需要清理");
|
|
182
|
+
this.prefixText += chalk.green(` ✓ 无旧版本需要清理
|
|
183
|
+
`);
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
await fs.access(paths.temp);
|
|
187
|
+
await fs.rm(paths.temp, { recursive: true, force: true });
|
|
188
|
+
} catch {
|
|
189
|
+
debugLog("[清理旧版本] 无临时目录需要清理");
|
|
190
|
+
}
|
|
257
191
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
192
|
+
async doDownloadFromNpm() {
|
|
193
|
+
debugLog("[安装插件] 开始安装插件...");
|
|
194
|
+
this.prefixText += chalk.green(` ✓ 开始安装插件
|
|
195
|
+
`);
|
|
196
|
+
this.spinner.prefixText = this.prefixText;
|
|
197
|
+
this.spinner.text = chalk.cyan("正在安装插件...");
|
|
198
|
+
try {
|
|
199
|
+
await execAsync$1(
|
|
200
|
+
`openclaw plugins install ${PLUGIN_PACKAGE_NAME$1} --dangerously-force-unsafe-install`,
|
|
201
|
+
{ timeout: 12e4 }
|
|
202
|
+
);
|
|
203
|
+
debugLog("[安装插件] openclaw plugins install 执行成功");
|
|
204
|
+
this.prefixText += chalk.green(` ✓ 插件安装完成
|
|
205
|
+
`);
|
|
206
|
+
} catch (error) {
|
|
207
|
+
const errorMsg = error.message || "未知错误";
|
|
208
|
+
debugLog(`[安装插件] 安装失败: ${errorMsg}`);
|
|
209
|
+
this.prefixText += chalk.red(`✗ 安装失败
|
|
210
|
+
`);
|
|
211
|
+
throw new AppError$1(ERROR_CODES$1.NPM_INSTALL_FAILED, `插件安装失败: ${errorMsg}`);
|
|
212
|
+
}
|
|
269
213
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
214
|
+
async doUpdateConfig(paths) {
|
|
215
|
+
debugLog("[更新配置] 开始更新配置...");
|
|
216
|
+
this.prefixText += chalk.green(` ✓ 开始更新配置
|
|
217
|
+
`);
|
|
218
|
+
this.updateSpinner("正在生成配置...");
|
|
219
|
+
let originalConfig = {};
|
|
220
|
+
try {
|
|
221
|
+
const content = await fs.readFile(paths.config, "utf-8");
|
|
222
|
+
originalConfig = JSON.parse(content);
|
|
223
|
+
debugLog("[更新配置] 读取原有配置成功");
|
|
224
|
+
} catch {
|
|
225
|
+
debugLog("[更新配置] 无原有配置");
|
|
226
|
+
}
|
|
227
|
+
const config = getConfig(this.config.env);
|
|
228
|
+
const newConfig = {
|
|
229
|
+
// diagnostics: 诊断配置
|
|
230
|
+
diagnostics: {
|
|
231
|
+
// 启用诊断功能
|
|
232
|
+
enabled: true,
|
|
233
|
+
// 启用所有诊断标志 ['*'] 表示全部,[] 表示禁用所有
|
|
234
|
+
flags: ["*"]
|
|
235
|
+
},
|
|
236
|
+
// browser: 浏览器配置
|
|
237
|
+
browser: {
|
|
238
|
+
// 禁用浏览器工具
|
|
239
|
+
enabled: false
|
|
240
|
+
},
|
|
241
|
+
// models: 模型配置
|
|
242
|
+
models: {
|
|
243
|
+
// 配置合并模式:'merge' 合并 | 'replace' 替换
|
|
244
|
+
mode: "merge",
|
|
245
|
+
providers: {
|
|
246
|
+
"siliconflow-minimax": {
|
|
247
|
+
// 模型 API 基础地址
|
|
248
|
+
baseUrl: config.MODEL_BASE_URL,
|
|
249
|
+
// API 密钥(留空,由外部提供)
|
|
250
|
+
apiKey: "",
|
|
251
|
+
// API 类型:'openai-completions' | 'openai-chat' 等
|
|
252
|
+
api: "openai-completions",
|
|
253
|
+
// 是否使用 Authorization header 认证
|
|
254
|
+
authHeader: true,
|
|
255
|
+
models: [{
|
|
256
|
+
// 模型 ID(provider/model 格式)
|
|
257
|
+
id: "Pro/MiniMaxAI/MiniMax-M2.5",
|
|
258
|
+
// 模型显示名称
|
|
259
|
+
name: "MiniMax-M2.5",
|
|
260
|
+
// 是否启用推理能力
|
|
261
|
+
reasoning: false,
|
|
262
|
+
// 支持的输入类型:['text'] | ['text', 'image']
|
|
263
|
+
input: ["text"],
|
|
264
|
+
// 价格(0 表示免费或未设置)
|
|
265
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
266
|
+
// 上下文窗口大小(token)
|
|
267
|
+
contextWindow: 2e5,
|
|
268
|
+
// 最大输出 token 数
|
|
269
|
+
maxTokens: 65536
|
|
270
|
+
}]
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
// agents: 代理配置
|
|
275
|
+
agents: {
|
|
276
|
+
defaults: {
|
|
277
|
+
// 默认使用的模型
|
|
278
|
+
model: { primary: "siliconflow-minimax/Pro/MiniMaxAI/MiniMax-M2.5" },
|
|
279
|
+
models: {
|
|
280
|
+
"siliconflow-minimax/Pro/MiniMaxAI/MiniMax-M2.5": {
|
|
281
|
+
// 模型别名,用于显示
|
|
282
|
+
alias: "Pro/MiniMaxAI/MiniMax-M2.5"
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
// 工作区目录路径
|
|
286
|
+
workspace: paths.workspace,
|
|
287
|
+
// 会话压缩模式:'safeguard' 保守模式
|
|
288
|
+
compaction: { mode: "safeguard" },
|
|
289
|
+
// 详细程度:'full' | 'short' | 'off'
|
|
290
|
+
verboseDefault: "full",
|
|
291
|
+
// 最大并发任务数
|
|
292
|
+
maxConcurrent: 4,
|
|
293
|
+
// 子代理最大并发数
|
|
294
|
+
subagents: { maxConcurrent: 8 }
|
|
295
|
+
},
|
|
296
|
+
// 代理列表
|
|
297
|
+
list: [{ id: "main", workspace: paths.workspace }]
|
|
298
|
+
},
|
|
299
|
+
// tools: 工具配置
|
|
300
|
+
tools: {
|
|
301
|
+
// 禁用的工具列表(优先于 allow)
|
|
302
|
+
deny: ["image", "web_search", "web_fetch"],
|
|
303
|
+
// 图像分析工具
|
|
304
|
+
media: { image: { enabled: false } },
|
|
305
|
+
// 网络搜索和抓取工具
|
|
306
|
+
web: { search: { enabled: false }, fetch: { enabled: false } },
|
|
307
|
+
// 提升权限工具(host=gateway)
|
|
308
|
+
elevated: { enabled: true, allowFrom: { webchat: ["*"] } },
|
|
309
|
+
// exec 工具安全级别:'deny' | 'allowlist' | 'full'
|
|
310
|
+
exec: { security: "full" }
|
|
311
|
+
},
|
|
312
|
+
// bindings: 绑定配置
|
|
313
|
+
bindings: [{
|
|
314
|
+
// 绑定的代理 ID
|
|
315
|
+
agentId: "main",
|
|
316
|
+
// 匹配的通道和账户
|
|
317
|
+
match: { channel: "openclaw-workclaw", accountId: "default" }
|
|
318
|
+
}],
|
|
319
|
+
// messages: 消息配置
|
|
320
|
+
messages: {
|
|
321
|
+
// 消息确认范围
|
|
322
|
+
ackReactionScope: "group-mentions"
|
|
323
|
+
},
|
|
324
|
+
// commands: 命令配置
|
|
325
|
+
commands: {
|
|
326
|
+
// 本机命令:'auto' | 'on' | 'off'
|
|
327
|
+
native: "auto",
|
|
328
|
+
// 本机技能:'auto' | 'on' | 'off'
|
|
329
|
+
nativeSkills: "auto",
|
|
330
|
+
// 是否允许重启命令
|
|
331
|
+
restart: true,
|
|
332
|
+
// 所有者显示格式:'raw' | 'name' | 'hidden'
|
|
333
|
+
ownerDisplay: "raw"
|
|
334
|
+
},
|
|
335
|
+
// session: 会话配置
|
|
336
|
+
session: {
|
|
337
|
+
// DM 作用域
|
|
338
|
+
dmScope: "per-account-channel-peer"
|
|
339
|
+
},
|
|
340
|
+
// hooks: 钩子配置
|
|
341
|
+
hooks: {
|
|
342
|
+
internal: {
|
|
343
|
+
// 启用内部钩子
|
|
344
|
+
enabled: true,
|
|
345
|
+
entries: {
|
|
346
|
+
// 启动 Markdown 钩子
|
|
347
|
+
"boot-md": { enabled: true },
|
|
348
|
+
// 引导额外文件钩子
|
|
349
|
+
"bootstrap-extra-files": { enabled: true },
|
|
350
|
+
// 命令日志钩子
|
|
351
|
+
"command-logger": { enabled: true },
|
|
352
|
+
// 会话记忆钩子
|
|
353
|
+
"session-memory": { enabled: true }
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
// channels: 通道配置
|
|
358
|
+
channels: {
|
|
359
|
+
"openclaw-workclaw": {
|
|
360
|
+
// 启用通道
|
|
361
|
+
enabled: true,
|
|
362
|
+
// 连接模式:'websocket' | 'http'
|
|
363
|
+
connectionMode: "websocket",
|
|
364
|
+
// 应用密钥
|
|
365
|
+
appKey: this.config.appKey,
|
|
366
|
+
// 应用密钥
|
|
367
|
+
appSecret: this.config.appSecret,
|
|
368
|
+
// API 基础 URL
|
|
369
|
+
baseUrl: this.config.baseUrl || config.DEFAULT_BASE_URL,
|
|
370
|
+
// WebSocket URL
|
|
371
|
+
websocketUrl: this.config.wsUrl || config.DEFAULT_WS_URL,
|
|
372
|
+
// 允许不安全的 TLS 连接
|
|
373
|
+
allowInsecureTls: true,
|
|
374
|
+
// 允许原始 JSON 载荷
|
|
375
|
+
allowRawJsonPayload: true,
|
|
376
|
+
// 用户 ID
|
|
377
|
+
userId: "",
|
|
378
|
+
// DM 策略
|
|
379
|
+
dmPolicy: "open",
|
|
380
|
+
// 允许所有来源
|
|
381
|
+
allowFrom: ["*"],
|
|
382
|
+
accounts: {
|
|
383
|
+
// 账户配置(agentId 为空表示待分配)
|
|
384
|
+
default: { enabled: true, agentId: "" }
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
// gateway: 网关配置
|
|
389
|
+
gateway: {
|
|
390
|
+
// 网关模式:'local' | 'hosted'
|
|
391
|
+
mode: "local",
|
|
392
|
+
// 网关端口
|
|
393
|
+
port: 18789,
|
|
394
|
+
// 绑定地址:'loopback' | 'lan' | 'all'
|
|
395
|
+
bind: "loopback",
|
|
396
|
+
// 认证模式(token字段未设置,是因为需要使用原始配置的token)
|
|
397
|
+
auth: {
|
|
398
|
+
mode: "token"
|
|
399
|
+
},
|
|
400
|
+
// Tailscale 配置
|
|
401
|
+
tailscale: { mode: "off", resetOnExit: false },
|
|
402
|
+
nodes: {
|
|
403
|
+
// 节点上禁止的命令
|
|
404
|
+
denyCommands: [
|
|
405
|
+
"camera.snap",
|
|
406
|
+
"camera.clip",
|
|
407
|
+
"screen.record",
|
|
408
|
+
"contacts.add",
|
|
409
|
+
"calendar.add",
|
|
410
|
+
"reminders.add",
|
|
411
|
+
"sms.send",
|
|
412
|
+
"sms.search"
|
|
413
|
+
]
|
|
414
|
+
},
|
|
415
|
+
controlUi: {
|
|
416
|
+
// 允许不安全认证
|
|
417
|
+
allowInsecureAuth: true,
|
|
418
|
+
// 禁用设备认证(仅用于开发)
|
|
419
|
+
dangerouslyDisableDeviceAuth: true,
|
|
420
|
+
// 允许 Host 头源回退
|
|
421
|
+
dangerouslyAllowHostHeaderOriginFallback: true,
|
|
422
|
+
// 允许的源
|
|
423
|
+
allowedOrigins: ["http://localhost:18789", "http://127.0.0.1:18789"]
|
|
424
|
+
}
|
|
425
|
+
},
|
|
426
|
+
// skills: 技能配置
|
|
427
|
+
skills: {
|
|
428
|
+
// 技能加载监视模式
|
|
429
|
+
load: { watch: true }
|
|
430
|
+
},
|
|
431
|
+
// logging: 日志配置
|
|
432
|
+
logging: {
|
|
433
|
+
// 日志级别:'debug' | 'info' | 'warn' | 'error'
|
|
434
|
+
level: "info",
|
|
435
|
+
// 控制台日志级别
|
|
436
|
+
consoleLevel: "info",
|
|
437
|
+
// 控制台样式:'pretty' | 'basic' | 'raw'
|
|
438
|
+
consoleStyle: "pretty",
|
|
439
|
+
// 敏感信息脱敏:'off' | 'keys' | 'all'
|
|
440
|
+
redactSensitive: "off",
|
|
441
|
+
// 日志文件路径(空表示不写入文件)
|
|
442
|
+
file: "",
|
|
443
|
+
// 脱敏模式(正则表达式)
|
|
444
|
+
redactPatterns: ["sk-.*"]
|
|
445
|
+
},
|
|
446
|
+
// plugins: 插件配置
|
|
447
|
+
plugins: {}
|
|
448
|
+
};
|
|
449
|
+
const finalConfig = deepMerge$1(originalConfig, newConfig);
|
|
450
|
+
this.updateSpinner("正在写入配置...");
|
|
451
|
+
debugLog("[更新配置] 写入配置文件...");
|
|
452
|
+
await fs.writeFile(paths.config, JSON.stringify(finalConfig, null, 2), "utf-8");
|
|
453
|
+
this.prefixText += chalk.green(` ✓ 配置文件更新成功
|
|
454
|
+
`);
|
|
455
|
+
debugLog(`[更新配置] 配置文件写入成功: ${paths.config}`);
|
|
276
456
|
}
|
|
277
|
-
|
|
278
|
-
|
|
457
|
+
}
|
|
458
|
+
function checkEnv$1() {
|
|
459
|
+
debugLog("[环境检查] 检测 Node.js 版本...");
|
|
460
|
+
const nodeVersion = execSync("node --version", { stdio: "pipe" }).toString().trim();
|
|
461
|
+
debugLog(`[环境检查] Node.js 版本: ${nodeVersion}`);
|
|
462
|
+
if (!semver.gte(nodeVersion, "18.0.0")) {
|
|
463
|
+
throw new AppError$1(ERROR_CODES$1.NODE_VERSION_LOW, `Node.js 版本需要 >= 18.0.0,当前版本: ${nodeVersion}`);
|
|
464
|
+
}
|
|
465
|
+
debugLog("[环境检查] Node.js 版本检查通过");
|
|
466
|
+
debugLog("[环境检查] 检测 npm...");
|
|
467
|
+
try {
|
|
468
|
+
const npmVersion = execSync("npm --version", { stdio: "pipe" }).toString().trim();
|
|
469
|
+
debugLog(`[环境检查] npm 版本: ${npmVersion}`);
|
|
470
|
+
debugLog("[环境检查] npm 检测通过");
|
|
471
|
+
} catch {
|
|
472
|
+
throw new AppError$1(ERROR_CODES$1.NPM_NOT_FOUND, "未检测到 npm,请先安装 Node.js 和 npm");
|
|
279
473
|
}
|
|
280
|
-
return ret;
|
|
281
474
|
}
|
|
282
|
-
function
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
475
|
+
async function createBoxCommand(options) {
|
|
476
|
+
setDebug(!!options.debug);
|
|
477
|
+
debugLog("[盒子安装] 开始处理...");
|
|
478
|
+
debugLog(`[盒子安装] 参数: env=${options.env}, appKey=${options.appKey ? "***" : "未提供"}, debug=${options.debug}`);
|
|
479
|
+
checkEnv$1();
|
|
480
|
+
debugLog("[盒子安装] 环境检查通过");
|
|
481
|
+
try {
|
|
482
|
+
let env = options.env;
|
|
483
|
+
let appKey = options.appKey;
|
|
484
|
+
let appSecret = options.appSecret;
|
|
485
|
+
const questions = [];
|
|
486
|
+
if (!env) {
|
|
487
|
+
debugLog("[盒子安装] 需要选择环境");
|
|
488
|
+
questions.push({
|
|
489
|
+
type: "list",
|
|
490
|
+
name: "env",
|
|
491
|
+
message: chalk.cyan("请选择环境:"),
|
|
492
|
+
default: "test",
|
|
493
|
+
choices: [
|
|
494
|
+
{ name: `${chalk.green("测试环境")} ${chalk.dim("(test)")}`, value: "test" },
|
|
495
|
+
{ name: `${chalk.red("正式环境")} ${chalk.dim("(prod)")}`, value: "prod" }
|
|
496
|
+
]
|
|
497
|
+
});
|
|
498
|
+
} else {
|
|
499
|
+
debugLog(`[盒子安装] 使用命令行参数: env=${env}`);
|
|
290
500
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
501
|
+
if (!appKey) {
|
|
502
|
+
debugLog("[盒子安装] 需要输入 AppKey");
|
|
503
|
+
questions.push({
|
|
504
|
+
type: "input",
|
|
505
|
+
name: "appKey",
|
|
506
|
+
message: chalk.cyan("请输入 AppKey:"),
|
|
507
|
+
validate: (value) => {
|
|
508
|
+
if (!value || value.trim() === "") {
|
|
509
|
+
return chalk.red("AppKey 不能为空");
|
|
510
|
+
}
|
|
511
|
+
return true;
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
} else {
|
|
515
|
+
debugLog("[盒子安装] 使用命令行参数: appKey");
|
|
294
516
|
}
|
|
295
|
-
if (
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
517
|
+
if (!appSecret) {
|
|
518
|
+
debugLog("[盒子安装] 需要输入 AppSecret");
|
|
519
|
+
questions.push({
|
|
520
|
+
type: "input",
|
|
521
|
+
name: "appSecret",
|
|
522
|
+
message: chalk.cyan("请输入 AppSecret:"),
|
|
523
|
+
validate: (value) => {
|
|
524
|
+
if (!value || value.trim() === "") {
|
|
525
|
+
return chalk.red("AppSecret 不能为空");
|
|
526
|
+
}
|
|
527
|
+
return true;
|
|
528
|
+
}
|
|
529
|
+
});
|
|
308
530
|
} else {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
531
|
+
debugLog("[盒子安装] 使用命令行参数: appSecret");
|
|
532
|
+
}
|
|
533
|
+
if (questions.length > 0) {
|
|
534
|
+
debugLog(`[盒子安装] 开始交互式问答,共 ${questions.length} 个问题`);
|
|
535
|
+
const answers = await inquirer.prompt(questions);
|
|
536
|
+
debugLog("[盒子安装] 交互式问答完成");
|
|
537
|
+
env = env || answers.env || "test";
|
|
538
|
+
appKey = appKey || answers.appKey;
|
|
539
|
+
appSecret = appSecret || answers.appSecret;
|
|
312
540
|
}
|
|
541
|
+
debugLog(`[盒子安装] 最终参数: env=${env}`);
|
|
542
|
+
debugLog("[盒子安装] 创建 BoxInstaller 实例...");
|
|
543
|
+
const installer = new BoxInstaller({
|
|
544
|
+
appKey,
|
|
545
|
+
appSecret,
|
|
546
|
+
env
|
|
547
|
+
});
|
|
548
|
+
debugLog("[盒子安装] 开始安装...");
|
|
549
|
+
await installer.install();
|
|
550
|
+
debugLog("[盒子安装] 安装完成");
|
|
551
|
+
console.log(installer.getPrefixText() + boxen(
|
|
552
|
+
`${chalk.green("✦")} 插件初始化成功!`,
|
|
553
|
+
{
|
|
554
|
+
title: `${chalk.bold.green("初始化成功")}`,
|
|
555
|
+
titleAlignment: "center",
|
|
556
|
+
padding: { top: 1, bottom: 1, left: 5, right: 5 },
|
|
557
|
+
margin: 1,
|
|
558
|
+
borderStyle: "round",
|
|
559
|
+
borderColor: "green",
|
|
560
|
+
textAlignment: "center"
|
|
561
|
+
}
|
|
562
|
+
));
|
|
563
|
+
} catch (error) {
|
|
564
|
+
debugLog(`[盒子安装] 发生错误: ${error.message}`);
|
|
565
|
+
console.error(boxen(
|
|
566
|
+
`${chalk.yellow(error.message)}`,
|
|
567
|
+
{
|
|
568
|
+
title: `${chalk.bold.red("初始化失败")}`,
|
|
569
|
+
titleAlignment: "center",
|
|
570
|
+
padding: { top: 1, bottom: 1, left: 5, right: 5 },
|
|
571
|
+
margin: 1,
|
|
572
|
+
borderStyle: "round",
|
|
573
|
+
borderColor: "red",
|
|
574
|
+
textAlignment: "center"
|
|
575
|
+
}
|
|
576
|
+
));
|
|
577
|
+
process$1.exit(1);
|
|
313
578
|
}
|
|
314
|
-
|
|
315
|
-
|
|
579
|
+
}
|
|
580
|
+
function registerCommands$1(program2) {
|
|
581
|
+
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("--debug", "开启调试日志").action(createBoxCommand);
|
|
582
|
+
}
|
|
583
|
+
const ERROR_CODES = {
|
|
584
|
+
PHONE_REQUIRED: "PHONE_REQUIRED",
|
|
585
|
+
USER_PASS_REQUIRED: "USER_PASS_REQUIRED",
|
|
586
|
+
LOGIN_FAILED: "LOGIN_FAILED",
|
|
587
|
+
GET_BOUND_CONFIG_FAILED: "GET_BOUND_CONFIG_FAILED",
|
|
588
|
+
NODE_VERSION_LOW: "NODE_VERSION_LOW",
|
|
589
|
+
NODE_NOT_FOUND: "NODE_NOT_FOUND",
|
|
590
|
+
NPM_NOT_FOUND: "NPM_NOT_FOUND",
|
|
591
|
+
NPM_INSTALL_FAILED: "NPM_INSTALL_FAILED",
|
|
592
|
+
CONFIG_WRITE_FAILED: "CONFIG_WRITE_FAILED",
|
|
593
|
+
HTTP_ERROR: "HTTP_ERROR",
|
|
594
|
+
NETWORK_ERROR: "NETWORK_ERROR"
|
|
595
|
+
};
|
|
596
|
+
class AppError2 extends Error {
|
|
597
|
+
constructor(code, message) {
|
|
598
|
+
super(message);
|
|
599
|
+
this.code = code;
|
|
600
|
+
this.name = "AppError";
|
|
316
601
|
}
|
|
317
|
-
return ret;
|
|
318
602
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
var hex = "0123456789ABCDEF";
|
|
325
|
-
var ignore = " \f\n\r \u2028\u2029";
|
|
326
|
-
decoder$1 = {};
|
|
327
|
-
for (i = 0; i < 16; ++i) {
|
|
328
|
-
decoder$1[hex.charAt(i)] = i;
|
|
329
|
-
}
|
|
330
|
-
hex = hex.toLowerCase();
|
|
331
|
-
for (i = 10; i < 16; ++i) {
|
|
332
|
-
decoder$1[hex.charAt(i)] = i;
|
|
333
|
-
}
|
|
334
|
-
for (i = 0; i < ignore.length; ++i) {
|
|
335
|
-
decoder$1[ignore.charAt(i)] = -1;
|
|
336
|
-
}
|
|
603
|
+
function createHttpClient() {
|
|
604
|
+
return axios.create({
|
|
605
|
+
timeout: 1e4,
|
|
606
|
+
headers: {
|
|
607
|
+
"Content-Type": "application/json"
|
|
337
608
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
async function httpPost(url, data, config) {
|
|
612
|
+
const client = createHttpClient();
|
|
613
|
+
debugLog(`[HTTP POST] 请求地址: ${url}`);
|
|
614
|
+
debugLog(`[HTTP POST] 请求参数: ${JSON.stringify(data)}`);
|
|
615
|
+
debugLog(`[HTTP POST] 请求头: ${JSON.stringify(config?.headers || {})}`);
|
|
616
|
+
try {
|
|
617
|
+
const response = await client.post(url, data, config);
|
|
618
|
+
debugLog(`[HTTP POST] 响应状态: ${response.status}`);
|
|
619
|
+
debugLog(`[HTTP POST] 响应内容: ${JSON.stringify(response.data)}`);
|
|
620
|
+
return {
|
|
621
|
+
status: response.status,
|
|
622
|
+
data: response.data
|
|
623
|
+
};
|
|
624
|
+
} catch (error) {
|
|
625
|
+
const axiosError = error;
|
|
626
|
+
if (axiosError.response) {
|
|
627
|
+
const responseData = axiosError.response.data;
|
|
628
|
+
debugLog(`[HTTP POST] 响应状态: ${axiosError.response.status}`);
|
|
629
|
+
debugLog(`[HTTP POST] 响应状态文本: ${axiosError.response.statusText}`);
|
|
630
|
+
debugLog(`[HTTP POST] 响应数据: ${JSON.stringify(responseData)}`);
|
|
631
|
+
if (typeof responseData === "string") {
|
|
632
|
+
throw new AppError2(ERROR_CODES.HTTP_ERROR, `请求失败 (${axiosError.response.status}): ${responseData}`);
|
|
633
|
+
} else if (responseData && typeof responseData === "object" && "message" in responseData) {
|
|
634
|
+
throw new AppError2(ERROR_CODES.HTTP_ERROR, `请求失败 (${axiosError.response.status}): ${responseData.message}`);
|
|
358
635
|
} else {
|
|
359
|
-
|
|
636
|
+
throw new AppError2(ERROR_CODES.HTTP_ERROR, `请求失败 (${axiosError.response.status}): ${axiosError.response.statusText}`);
|
|
360
637
|
}
|
|
638
|
+
} else if (axiosError.request) {
|
|
639
|
+
debugLog(`[HTTP POST] 未收到响应`);
|
|
640
|
+
debugLog(`[HTTP POST] 错误信息: ${axiosError.message}`);
|
|
641
|
+
throw new AppError2(ERROR_CODES.NETWORK_ERROR, `网络错误: ${axiosError.message}`);
|
|
642
|
+
} else {
|
|
643
|
+
debugLog(`[HTTP POST] 请求配置错误`);
|
|
644
|
+
debugLog(`[HTTP POST] 错误信息: ${axiosError.message}`);
|
|
645
|
+
throw new AppError2(ERROR_CODES.HTTP_ERROR, `请求配置错误: ${axiosError.message}`);
|
|
361
646
|
}
|
|
362
|
-
if (char_count) {
|
|
363
|
-
throw new Error("Hex encoding incomplete: 4 bits missing");
|
|
364
|
-
}
|
|
365
|
-
return out;
|
|
366
647
|
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
648
|
+
}
|
|
649
|
+
async function login(phone, password, env) {
|
|
650
|
+
const config = getConfig(env);
|
|
651
|
+
const url = `${config.API.TUZAI_BASE_URL}/user/login/pass`;
|
|
652
|
+
debugLog("[登录] 开始登录...");
|
|
653
|
+
debugLog(`[登录] 请求地址: ${url}`);
|
|
654
|
+
debugLog(`[登录] 请求参数: phone=${phone}, password=***`);
|
|
655
|
+
try {
|
|
656
|
+
const response = await httpPost(url, {
|
|
657
|
+
phone,
|
|
658
|
+
userPass: password
|
|
659
|
+
});
|
|
660
|
+
const data = response.data;
|
|
661
|
+
debugLog(`[登录] 响应数据: ${JSON.stringify(data)}`);
|
|
662
|
+
if (data.code === 200 && data.data?.token) {
|
|
663
|
+
debugLog("[登录] 登录成功,获取到 token");
|
|
664
|
+
return data.data.token;
|
|
384
665
|
}
|
|
385
|
-
|
|
666
|
+
debugLog("[登录] 登录失败");
|
|
667
|
+
throw new AppError2(ERROR_CODES.LOGIN_FAILED, data.message || "登录失败");
|
|
668
|
+
} catch (error) {
|
|
669
|
+
if (error instanceof AppError2) {
|
|
670
|
+
throw error;
|
|
671
|
+
}
|
|
672
|
+
debugLog(`[登录] 发生错误: ${error.message}`);
|
|
673
|
+
throw new AppError2(ERROR_CODES.LOGIN_FAILED, error.message);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
async function fetchBoundConfig(token, phone, env) {
|
|
677
|
+
const config = getConfig(env);
|
|
678
|
+
const url = `${config.API.TUZAI_BASE_URL}/work-bot/local/bound/init`;
|
|
679
|
+
debugLog("[获取绑定配置] 开始获取绑定配置...");
|
|
680
|
+
debugLog(`[获取绑定配置] 请求地址: ${url}`);
|
|
681
|
+
debugLog(`[获取绑定配置] 请求参数: phone=${phone}, localCode=001`);
|
|
682
|
+
debugLog(`[获取绑定配置] 请求头: Authorization=${token.substring(0, 20)}...`);
|
|
683
|
+
try {
|
|
684
|
+
const response = await httpPost(url, {
|
|
685
|
+
phone,
|
|
686
|
+
localCode: "001"
|
|
687
|
+
}, {
|
|
688
|
+
headers: {
|
|
689
|
+
Authorization: token
|
|
690
|
+
}
|
|
691
|
+
});
|
|
692
|
+
const data = response.data;
|
|
693
|
+
debugLog(`[获取绑定配置] 响应数据: ${JSON.stringify(data)}`);
|
|
694
|
+
if (data.code === 200 && data.data) {
|
|
695
|
+
const boundConfig = {
|
|
696
|
+
appKey: data.data.app_key,
|
|
697
|
+
appSecret: data.data.app_secret,
|
|
698
|
+
userId: data.data.user_id,
|
|
699
|
+
agentId: data.data.agent_id || data.data.agents?.[0]?.id,
|
|
700
|
+
modelApiKey: data.data.model_api_key,
|
|
701
|
+
modelApiBaseUrl: data.data.model_api_base_url
|
|
702
|
+
};
|
|
703
|
+
debugLog("[获取绑定配置] 获取绑定配置成功");
|
|
704
|
+
debugLog(`[获取绑定配置] appKey: ${boundConfig.appKey}`);
|
|
705
|
+
debugLog(`[获取绑定配置] appSecret: ${boundConfig.appSecret ? "***" : "undefined"}`);
|
|
706
|
+
debugLog(`[获取绑定配置] userId: ${boundConfig.userId}`);
|
|
707
|
+
debugLog(`[获取绑定配置] agentId: ${boundConfig.agentId}`);
|
|
708
|
+
debugLog(`[获取绑定配置] modelApiKey: ${boundConfig.modelApiKey || "undefined"}`);
|
|
709
|
+
debugLog(`[获取绑定配置] modelApiBaseUrl: ${boundConfig.modelApiBaseUrl || "undefined"}`);
|
|
710
|
+
if (!boundConfig.appKey || !boundConfig.appSecret || !boundConfig.agentId) {
|
|
711
|
+
debugLog("[获取绑定配置] 缺少必要字段");
|
|
712
|
+
throw new AppError2(ERROR_CODES.GET_BOUND_CONFIG_FAILED, "获取绑定配置失败:缺少必要字段");
|
|
713
|
+
}
|
|
714
|
+
return boundConfig;
|
|
715
|
+
}
|
|
716
|
+
debugLog("[获取绑定配置] 获取绑定配置失败");
|
|
717
|
+
throw new AppError2(ERROR_CODES.GET_BOUND_CONFIG_FAILED, data.message || data.msg || "获取绑定配置失败");
|
|
718
|
+
} catch (error) {
|
|
719
|
+
if (error instanceof AppError2) {
|
|
720
|
+
throw error;
|
|
721
|
+
}
|
|
722
|
+
debugLog(`[获取绑定配置] 发生错误: ${error.message}`);
|
|
723
|
+
throw new AppError2(ERROR_CODES.GET_BOUND_CONFIG_FAILED, error.message);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
|
|
727
|
+
function int2char(n) {
|
|
728
|
+
return BI_RM.charAt(n);
|
|
729
|
+
}
|
|
730
|
+
function op_and(x, y) {
|
|
731
|
+
return x & y;
|
|
732
|
+
}
|
|
733
|
+
function op_or(x, y) {
|
|
734
|
+
return x | y;
|
|
735
|
+
}
|
|
736
|
+
function op_xor(x, y) {
|
|
737
|
+
return x ^ y;
|
|
738
|
+
}
|
|
739
|
+
function op_andnot(x, y) {
|
|
740
|
+
return x & ~y;
|
|
741
|
+
}
|
|
742
|
+
function lbit(x) {
|
|
743
|
+
if (x == 0) {
|
|
744
|
+
return -1;
|
|
745
|
+
}
|
|
746
|
+
var r = 0;
|
|
747
|
+
if ((x & 65535) == 0) {
|
|
748
|
+
x >>= 16;
|
|
749
|
+
r += 16;
|
|
750
|
+
}
|
|
751
|
+
if ((x & 255) == 0) {
|
|
752
|
+
x >>= 8;
|
|
753
|
+
r += 8;
|
|
754
|
+
}
|
|
755
|
+
if ((x & 15) == 0) {
|
|
756
|
+
x >>= 4;
|
|
757
|
+
r += 4;
|
|
758
|
+
}
|
|
759
|
+
if ((x & 3) == 0) {
|
|
760
|
+
x >>= 2;
|
|
761
|
+
r += 2;
|
|
762
|
+
}
|
|
763
|
+
if ((x & 1) == 0) {
|
|
764
|
+
++r;
|
|
765
|
+
}
|
|
766
|
+
return r;
|
|
767
|
+
}
|
|
768
|
+
function cbit(x) {
|
|
769
|
+
var r = 0;
|
|
770
|
+
while (x != 0) {
|
|
771
|
+
x &= x - 1;
|
|
772
|
+
++r;
|
|
773
|
+
}
|
|
774
|
+
return r;
|
|
775
|
+
}
|
|
776
|
+
var b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
777
|
+
var b64pad = "=";
|
|
778
|
+
function hex2b64(h) {
|
|
779
|
+
var i;
|
|
780
|
+
var c;
|
|
781
|
+
var ret = "";
|
|
782
|
+
for (i = 0; i + 3 <= h.length; i += 3) {
|
|
783
|
+
c = parseInt(h.substring(i, i + 3), 16);
|
|
784
|
+
ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
|
|
785
|
+
}
|
|
786
|
+
if (i + 1 == h.length) {
|
|
787
|
+
c = parseInt(h.substring(i, i + 1), 16);
|
|
788
|
+
ret += b64map.charAt(c << 2);
|
|
789
|
+
} else if (i + 2 == h.length) {
|
|
790
|
+
c = parseInt(h.substring(i, i + 2), 16);
|
|
791
|
+
ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
|
|
792
|
+
}
|
|
793
|
+
while ((ret.length & 3) > 0) {
|
|
794
|
+
ret += b64pad;
|
|
795
|
+
}
|
|
796
|
+
return ret;
|
|
797
|
+
}
|
|
798
|
+
function b64tohex(s) {
|
|
799
|
+
var ret = "";
|
|
800
|
+
var i;
|
|
801
|
+
var k = 0;
|
|
802
|
+
var slop = 0;
|
|
803
|
+
for (i = 0; i < s.length; ++i) {
|
|
804
|
+
if (s.charAt(i) == b64pad) {
|
|
805
|
+
break;
|
|
806
|
+
}
|
|
807
|
+
var v = b64map.indexOf(s.charAt(i));
|
|
808
|
+
if (v < 0) {
|
|
809
|
+
continue;
|
|
810
|
+
}
|
|
811
|
+
if (k == 0) {
|
|
812
|
+
ret += int2char(v >> 2);
|
|
813
|
+
slop = v & 3;
|
|
814
|
+
k = 1;
|
|
815
|
+
} else if (k == 1) {
|
|
816
|
+
ret += int2char(slop << 2 | v >> 4);
|
|
817
|
+
slop = v & 15;
|
|
818
|
+
k = 2;
|
|
819
|
+
} else if (k == 2) {
|
|
820
|
+
ret += int2char(slop);
|
|
821
|
+
ret += int2char(v >> 2);
|
|
822
|
+
slop = v & 3;
|
|
823
|
+
k = 3;
|
|
824
|
+
} else {
|
|
825
|
+
ret += int2char(slop << 2 | v >> 4);
|
|
826
|
+
ret += int2char(v & 15);
|
|
827
|
+
k = 0;
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
if (k == 1) {
|
|
831
|
+
ret += int2char(slop << 2);
|
|
832
|
+
}
|
|
833
|
+
return ret;
|
|
834
|
+
}
|
|
835
|
+
var decoder$1;
|
|
836
|
+
var Hex = {
|
|
837
|
+
decode: function(a) {
|
|
838
|
+
var i;
|
|
839
|
+
if (decoder$1 === void 0) {
|
|
840
|
+
var hex = "0123456789ABCDEF";
|
|
841
|
+
var ignore = " \f\n\r \u2028\u2029";
|
|
842
|
+
decoder$1 = {};
|
|
843
|
+
for (i = 0; i < 16; ++i) {
|
|
844
|
+
decoder$1[hex.charAt(i)] = i;
|
|
845
|
+
}
|
|
846
|
+
hex = hex.toLowerCase();
|
|
847
|
+
for (i = 10; i < 16; ++i) {
|
|
848
|
+
decoder$1[hex.charAt(i)] = i;
|
|
849
|
+
}
|
|
850
|
+
for (i = 0; i < ignore.length; ++i) {
|
|
851
|
+
decoder$1[ignore.charAt(i)] = -1;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
var out = [];
|
|
855
|
+
var bits = 0;
|
|
856
|
+
var char_count = 0;
|
|
857
|
+
for (i = 0; i < a.length; ++i) {
|
|
858
|
+
var c = a.charAt(i);
|
|
859
|
+
if (c == "=") {
|
|
860
|
+
break;
|
|
861
|
+
}
|
|
862
|
+
c = decoder$1[c];
|
|
863
|
+
if (c == -1) {
|
|
864
|
+
continue;
|
|
865
|
+
}
|
|
866
|
+
if (c === void 0) {
|
|
867
|
+
throw new Error("Illegal character at offset " + i);
|
|
868
|
+
}
|
|
869
|
+
bits |= c;
|
|
870
|
+
if (++char_count >= 2) {
|
|
871
|
+
out[out.length] = bits;
|
|
872
|
+
bits = 0;
|
|
873
|
+
char_count = 0;
|
|
874
|
+
} else {
|
|
875
|
+
bits <<= 4;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
if (char_count) {
|
|
879
|
+
throw new Error("Hex encoding incomplete: 4 bits missing");
|
|
880
|
+
}
|
|
881
|
+
return out;
|
|
882
|
+
}
|
|
883
|
+
};
|
|
884
|
+
var decoder;
|
|
885
|
+
var Base64 = {
|
|
886
|
+
decode: function(a) {
|
|
887
|
+
var i;
|
|
888
|
+
if (decoder === void 0) {
|
|
889
|
+
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
890
|
+
var ignore = "= \f\n\r \u2028\u2029";
|
|
891
|
+
decoder = /* @__PURE__ */ Object.create(null);
|
|
892
|
+
for (i = 0; i < 64; ++i) {
|
|
893
|
+
decoder[b64.charAt(i)] = i;
|
|
894
|
+
}
|
|
895
|
+
decoder["-"] = 62;
|
|
896
|
+
decoder["_"] = 63;
|
|
897
|
+
for (i = 0; i < ignore.length; ++i) {
|
|
898
|
+
decoder[ignore.charAt(i)] = -1;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
var out = [];
|
|
386
902
|
var bits = 0;
|
|
387
903
|
var char_count = 0;
|
|
388
904
|
for (i = 0; i < a.length; ++i) {
|
|
@@ -3578,1167 +4094,540 @@ KJUR.asn1.DERObjectIdentifier = function(params) {
|
|
|
3578
4094
|
for (var i = 0; i < a.length; i++) {
|
|
3579
4095
|
h += roidtox(a[i]);
|
|
3580
4096
|
}
|
|
3581
|
-
this.hTLV = null;
|
|
3582
|
-
this.isModified = true;
|
|
3583
|
-
this.s = null;
|
|
3584
|
-
this.hV = h;
|
|
3585
|
-
};
|
|
3586
|
-
this.setValueName = function(oidName) {
|
|
3587
|
-
var oid = KJUR.asn1.x509.OID.name2oid(oidName);
|
|
3588
|
-
if (oid !== "") {
|
|
3589
|
-
this.setValueOidString(oid);
|
|
3590
|
-
} else {
|
|
3591
|
-
throw "DERObjectIdentifier oidName undefined: " + oidName;
|
|
3592
|
-
}
|
|
3593
|
-
};
|
|
3594
|
-
this.getFreshValueHex = function() {
|
|
3595
|
-
return this.hV;
|
|
3596
|
-
};
|
|
3597
|
-
if (params !== void 0) {
|
|
3598
|
-
if (typeof params === "string") {
|
|
3599
|
-
if (params.match(/^[0-2].[0-9.]+$/)) {
|
|
3600
|
-
this.setValueOidString(params);
|
|
3601
|
-
} else {
|
|
3602
|
-
this.setValueName(params);
|
|
3603
|
-
}
|
|
3604
|
-
} else if (params.oid !== void 0) {
|
|
3605
|
-
this.setValueOidString(params.oid);
|
|
3606
|
-
} else if (params.hex !== void 0) {
|
|
3607
|
-
this.setValueHex(params.hex);
|
|
3608
|
-
} else if (params.name !== void 0) {
|
|
3609
|
-
this.setValueName(params.name);
|
|
3610
|
-
}
|
|
3611
|
-
}
|
|
3612
|
-
};
|
|
3613
|
-
extendClass(KJUR.asn1.DERObjectIdentifier, KJUR.asn1.ASN1Object);
|
|
3614
|
-
KJUR.asn1.DEREnumerated = function(params) {
|
|
3615
|
-
KJUR.asn1.DEREnumerated.superclass.constructor.call(this);
|
|
3616
|
-
this.hT = "0a";
|
|
3617
|
-
this.setByBigInteger = function(bigIntegerValue) {
|
|
3618
|
-
this.hTLV = null;
|
|
3619
|
-
this.isModified = true;
|
|
3620
|
-
this.hV = KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(bigIntegerValue);
|
|
3621
|
-
};
|
|
3622
|
-
this.setByInteger = function(intValue) {
|
|
3623
|
-
var bi = new BigInteger(String(intValue), 10);
|
|
3624
|
-
this.setByBigInteger(bi);
|
|
3625
|
-
};
|
|
3626
|
-
this.setValueHex = function(newHexString) {
|
|
3627
|
-
this.hV = newHexString;
|
|
3628
|
-
};
|
|
3629
|
-
this.getFreshValueHex = function() {
|
|
3630
|
-
return this.hV;
|
|
3631
|
-
};
|
|
3632
|
-
if (typeof params != "undefined") {
|
|
3633
|
-
if (typeof params["int"] != "undefined") {
|
|
3634
|
-
this.setByInteger(params["int"]);
|
|
3635
|
-
} else if (typeof params == "number") {
|
|
3636
|
-
this.setByInteger(params);
|
|
3637
|
-
} else if (typeof params["hex"] != "undefined") {
|
|
3638
|
-
this.setValueHex(params["hex"]);
|
|
3639
|
-
}
|
|
3640
|
-
}
|
|
3641
|
-
};
|
|
3642
|
-
extendClass(KJUR.asn1.DEREnumerated, KJUR.asn1.ASN1Object);
|
|
3643
|
-
KJUR.asn1.DERUTF8String = function(params) {
|
|
3644
|
-
KJUR.asn1.DERUTF8String.superclass.constructor.call(this, params);
|
|
3645
|
-
this.hT = "0c";
|
|
3646
|
-
};
|
|
3647
|
-
extendClass(KJUR.asn1.DERUTF8String, KJUR.asn1.DERAbstractString);
|
|
3648
|
-
KJUR.asn1.DERNumericString = function(params) {
|
|
3649
|
-
KJUR.asn1.DERNumericString.superclass.constructor.call(this, params);
|
|
3650
|
-
this.hT = "12";
|
|
3651
|
-
};
|
|
3652
|
-
extendClass(KJUR.asn1.DERNumericString, KJUR.asn1.DERAbstractString);
|
|
3653
|
-
KJUR.asn1.DERPrintableString = function(params) {
|
|
3654
|
-
KJUR.asn1.DERPrintableString.superclass.constructor.call(this, params);
|
|
3655
|
-
this.hT = "13";
|
|
3656
|
-
};
|
|
3657
|
-
extendClass(KJUR.asn1.DERPrintableString, KJUR.asn1.DERAbstractString);
|
|
3658
|
-
KJUR.asn1.DERTeletexString = function(params) {
|
|
3659
|
-
KJUR.asn1.DERTeletexString.superclass.constructor.call(this, params);
|
|
3660
|
-
this.hT = "14";
|
|
3661
|
-
};
|
|
3662
|
-
extendClass(KJUR.asn1.DERTeletexString, KJUR.asn1.DERAbstractString);
|
|
3663
|
-
KJUR.asn1.DERIA5String = function(params) {
|
|
3664
|
-
KJUR.asn1.DERIA5String.superclass.constructor.call(this, params);
|
|
3665
|
-
this.hT = "16";
|
|
3666
|
-
};
|
|
3667
|
-
extendClass(KJUR.asn1.DERIA5String, KJUR.asn1.DERAbstractString);
|
|
3668
|
-
KJUR.asn1.DERUTCTime = function(params) {
|
|
3669
|
-
KJUR.asn1.DERUTCTime.superclass.constructor.call(this, params);
|
|
3670
|
-
this.hT = "17";
|
|
3671
|
-
this.setByDate = function(dateObject) {
|
|
3672
|
-
this.hTLV = null;
|
|
3673
|
-
this.isModified = true;
|
|
3674
|
-
this.date = dateObject;
|
|
3675
|
-
this.s = this.formatDate(this.date, "utc");
|
|
3676
|
-
this.hV = stohex(this.s);
|
|
3677
|
-
};
|
|
3678
|
-
this.getFreshValueHex = function() {
|
|
3679
|
-
if (typeof this.date == "undefined" && typeof this.s == "undefined") {
|
|
3680
|
-
this.date = /* @__PURE__ */ new Date();
|
|
3681
|
-
this.s = this.formatDate(this.date, "utc");
|
|
3682
|
-
this.hV = stohex(this.s);
|
|
3683
|
-
}
|
|
3684
|
-
return this.hV;
|
|
3685
|
-
};
|
|
3686
|
-
if (params !== void 0) {
|
|
3687
|
-
if (params.str !== void 0) {
|
|
3688
|
-
this.setString(params.str);
|
|
3689
|
-
} else if (typeof params == "string" && params.match(/^[0-9]{12}Z$/)) {
|
|
3690
|
-
this.setString(params);
|
|
3691
|
-
} else if (params.hex !== void 0) {
|
|
3692
|
-
this.setStringHex(params.hex);
|
|
3693
|
-
} else if (params.date !== void 0) {
|
|
3694
|
-
this.setByDate(params.date);
|
|
3695
|
-
}
|
|
3696
|
-
}
|
|
3697
|
-
};
|
|
3698
|
-
extendClass(KJUR.asn1.DERUTCTime, KJUR.asn1.DERAbstractTime);
|
|
3699
|
-
KJUR.asn1.DERGeneralizedTime = function(params) {
|
|
3700
|
-
KJUR.asn1.DERGeneralizedTime.superclass.constructor.call(this, params);
|
|
3701
|
-
this.hT = "18";
|
|
3702
|
-
this.withMillis = false;
|
|
3703
|
-
this.setByDate = function(dateObject) {
|
|
3704
|
-
this.hTLV = null;
|
|
3705
|
-
this.isModified = true;
|
|
3706
|
-
this.date = dateObject;
|
|
3707
|
-
this.s = this.formatDate(this.date, "gen", this.withMillis);
|
|
3708
|
-
this.hV = stohex(this.s);
|
|
3709
|
-
};
|
|
3710
|
-
this.getFreshValueHex = function() {
|
|
3711
|
-
if (this.date === void 0 && this.s === void 0) {
|
|
3712
|
-
this.date = /* @__PURE__ */ new Date();
|
|
3713
|
-
this.s = this.formatDate(this.date, "gen", this.withMillis);
|
|
3714
|
-
this.hV = stohex(this.s);
|
|
3715
|
-
}
|
|
3716
|
-
return this.hV;
|
|
3717
|
-
};
|
|
3718
|
-
if (params !== void 0) {
|
|
3719
|
-
if (params.str !== void 0) {
|
|
3720
|
-
this.setString(params.str);
|
|
3721
|
-
} else if (typeof params == "string" && params.match(/^[0-9]{14}Z$/)) {
|
|
3722
|
-
this.setString(params);
|
|
3723
|
-
} else if (params.hex !== void 0) {
|
|
3724
|
-
this.setStringHex(params.hex);
|
|
3725
|
-
} else if (params.date !== void 0) {
|
|
3726
|
-
this.setByDate(params.date);
|
|
3727
|
-
}
|
|
3728
|
-
if (params.millis === true) {
|
|
3729
|
-
this.withMillis = true;
|
|
3730
|
-
}
|
|
3731
|
-
}
|
|
3732
|
-
};
|
|
3733
|
-
extendClass(KJUR.asn1.DERGeneralizedTime, KJUR.asn1.DERAbstractTime);
|
|
3734
|
-
KJUR.asn1.DERSequence = function(params) {
|
|
3735
|
-
KJUR.asn1.DERSequence.superclass.constructor.call(this, params);
|
|
3736
|
-
this.hT = "30";
|
|
3737
|
-
this.getFreshValueHex = function() {
|
|
3738
|
-
var h = "";
|
|
3739
|
-
for (var i = 0; i < this.asn1Array.length; i++) {
|
|
3740
|
-
var asn1Obj = this.asn1Array[i];
|
|
3741
|
-
h += asn1Obj.getEncodedHex();
|
|
3742
|
-
}
|
|
3743
|
-
this.hV = h;
|
|
3744
|
-
return this.hV;
|
|
3745
|
-
};
|
|
3746
|
-
};
|
|
3747
|
-
extendClass(KJUR.asn1.DERSequence, KJUR.asn1.DERAbstractStructured);
|
|
3748
|
-
KJUR.asn1.DERSet = function(params) {
|
|
3749
|
-
KJUR.asn1.DERSet.superclass.constructor.call(this, params);
|
|
3750
|
-
this.hT = "31";
|
|
3751
|
-
this.sortFlag = true;
|
|
3752
|
-
this.getFreshValueHex = function() {
|
|
3753
|
-
var a = new Array();
|
|
3754
|
-
for (var i = 0; i < this.asn1Array.length; i++) {
|
|
3755
|
-
var asn1Obj = this.asn1Array[i];
|
|
3756
|
-
a.push(asn1Obj.getEncodedHex());
|
|
3757
|
-
}
|
|
3758
|
-
if (this.sortFlag == true)
|
|
3759
|
-
a.sort();
|
|
3760
|
-
this.hV = a.join("");
|
|
3761
|
-
return this.hV;
|
|
3762
|
-
};
|
|
3763
|
-
if (typeof params != "undefined") {
|
|
3764
|
-
if (typeof params.sortflag != "undefined" && params.sortflag == false)
|
|
3765
|
-
this.sortFlag = false;
|
|
3766
|
-
}
|
|
3767
|
-
};
|
|
3768
|
-
extendClass(KJUR.asn1.DERSet, KJUR.asn1.DERAbstractStructured);
|
|
3769
|
-
KJUR.asn1.DERTaggedObject = function(params) {
|
|
3770
|
-
KJUR.asn1.DERTaggedObject.superclass.constructor.call(this);
|
|
3771
|
-
this.hT = "a0";
|
|
3772
|
-
this.hV = "";
|
|
3773
|
-
this.isExplicit = true;
|
|
3774
|
-
this.asn1Object = null;
|
|
3775
|
-
this.setASN1Object = function(isExplicitFlag, tagNoHex, asn1Object) {
|
|
3776
|
-
this.hT = tagNoHex;
|
|
3777
|
-
this.isExplicit = isExplicitFlag;
|
|
3778
|
-
this.asn1Object = asn1Object;
|
|
3779
|
-
if (this.isExplicit) {
|
|
3780
|
-
this.hV = this.asn1Object.getEncodedHex();
|
|
3781
|
-
this.hTLV = null;
|
|
3782
|
-
this.isModified = true;
|
|
3783
|
-
} else {
|
|
3784
|
-
this.hV = null;
|
|
3785
|
-
this.hTLV = asn1Object.getEncodedHex();
|
|
3786
|
-
this.hTLV = this.hTLV.replace(/^../, tagNoHex);
|
|
3787
|
-
this.isModified = false;
|
|
3788
|
-
}
|
|
3789
|
-
};
|
|
3790
|
-
this.getFreshValueHex = function() {
|
|
3791
|
-
return this.hV;
|
|
3792
|
-
};
|
|
3793
|
-
if (typeof params != "undefined") {
|
|
3794
|
-
if (typeof params["tag"] != "undefined") {
|
|
3795
|
-
this.hT = params["tag"];
|
|
3796
|
-
}
|
|
3797
|
-
if (typeof params["explicit"] != "undefined") {
|
|
3798
|
-
this.isExplicit = params["explicit"];
|
|
3799
|
-
}
|
|
3800
|
-
if (typeof params["obj"] != "undefined") {
|
|
3801
|
-
this.asn1Object = params["obj"];
|
|
3802
|
-
this.setASN1Object(this.isExplicit, this.hT, this.asn1Object);
|
|
3803
|
-
}
|
|
3804
|
-
}
|
|
3805
|
-
};
|
|
3806
|
-
extendClass(KJUR.asn1.DERTaggedObject, KJUR.asn1.ASN1Object);
|
|
3807
|
-
var __extends = /* @__PURE__ */ function() {
|
|
3808
|
-
var extendStatics = function(d, b) {
|
|
3809
|
-
extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) {
|
|
3810
|
-
d2.__proto__ = b2;
|
|
3811
|
-
} || function(d2, b2) {
|
|
3812
|
-
for (var p in b2) if (Object.prototype.hasOwnProperty.call(b2, p)) d2[p] = b2[p];
|
|
3813
|
-
};
|
|
3814
|
-
return extendStatics(d, b);
|
|
3815
|
-
};
|
|
3816
|
-
return function(d, b) {
|
|
3817
|
-
if (typeof b !== "function" && b !== null)
|
|
3818
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
3819
|
-
extendStatics(d, b);
|
|
3820
|
-
function __() {
|
|
3821
|
-
this.constructor = d;
|
|
3822
|
-
}
|
|
3823
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
3824
|
-
};
|
|
3825
|
-
}();
|
|
3826
|
-
var JSEncryptRSAKey = (
|
|
3827
|
-
/** @class */
|
|
3828
|
-
function(_super) {
|
|
3829
|
-
__extends(JSEncryptRSAKey2, _super);
|
|
3830
|
-
function JSEncryptRSAKey2(key) {
|
|
3831
|
-
var _this = _super.call(this) || this;
|
|
3832
|
-
if (key) {
|
|
3833
|
-
if (typeof key === "string") {
|
|
3834
|
-
_this.parseKey(key);
|
|
3835
|
-
} else if (JSEncryptRSAKey2.hasPrivateKeyProperty(key) || JSEncryptRSAKey2.hasPublicKeyProperty(key)) {
|
|
3836
|
-
_this.parsePropertiesFrom(key);
|
|
3837
|
-
}
|
|
3838
|
-
}
|
|
3839
|
-
return _this;
|
|
3840
|
-
}
|
|
3841
|
-
JSEncryptRSAKey2.prototype.parseKey = function(pem) {
|
|
3842
|
-
try {
|
|
3843
|
-
var modulus = 0;
|
|
3844
|
-
var public_exponent = 0;
|
|
3845
|
-
var reHex = /^\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\s*)+$/;
|
|
3846
|
-
var der = reHex.test(pem) ? Hex.decode(pem) : Base64.unarmor(pem);
|
|
3847
|
-
var asn1 = ASN1.decode(der);
|
|
3848
|
-
if (asn1.sub.length === 3) {
|
|
3849
|
-
asn1 = asn1.sub[2].sub[0];
|
|
3850
|
-
}
|
|
3851
|
-
if (asn1.sub.length === 9) {
|
|
3852
|
-
modulus = asn1.sub[1].getHexStringValue();
|
|
3853
|
-
this.n = parseBigInt(modulus, 16);
|
|
3854
|
-
public_exponent = asn1.sub[2].getHexStringValue();
|
|
3855
|
-
this.e = parseInt(public_exponent, 16);
|
|
3856
|
-
var private_exponent = asn1.sub[3].getHexStringValue();
|
|
3857
|
-
this.d = parseBigInt(private_exponent, 16);
|
|
3858
|
-
var prime1 = asn1.sub[4].getHexStringValue();
|
|
3859
|
-
this.p = parseBigInt(prime1, 16);
|
|
3860
|
-
var prime2 = asn1.sub[5].getHexStringValue();
|
|
3861
|
-
this.q = parseBigInt(prime2, 16);
|
|
3862
|
-
var exponent1 = asn1.sub[6].getHexStringValue();
|
|
3863
|
-
this.dmp1 = parseBigInt(exponent1, 16);
|
|
3864
|
-
var exponent2 = asn1.sub[7].getHexStringValue();
|
|
3865
|
-
this.dmq1 = parseBigInt(exponent2, 16);
|
|
3866
|
-
var coefficient = asn1.sub[8].getHexStringValue();
|
|
3867
|
-
this.coeff = parseBigInt(coefficient, 16);
|
|
3868
|
-
} else if (asn1.sub.length === 2) {
|
|
3869
|
-
if (asn1.sub[0].sub) {
|
|
3870
|
-
var bit_string = asn1.sub[1];
|
|
3871
|
-
var sequence = bit_string.sub[0];
|
|
3872
|
-
modulus = sequence.sub[0].getHexStringValue();
|
|
3873
|
-
this.n = parseBigInt(modulus, 16);
|
|
3874
|
-
public_exponent = sequence.sub[1].getHexStringValue();
|
|
3875
|
-
this.e = parseInt(public_exponent, 16);
|
|
3876
|
-
} else {
|
|
3877
|
-
modulus = asn1.sub[0].getHexStringValue();
|
|
3878
|
-
this.n = parseBigInt(modulus, 16);
|
|
3879
|
-
public_exponent = asn1.sub[1].getHexStringValue();
|
|
3880
|
-
this.e = parseInt(public_exponent, 16);
|
|
3881
|
-
}
|
|
3882
|
-
} else {
|
|
3883
|
-
return false;
|
|
3884
|
-
}
|
|
3885
|
-
return true;
|
|
3886
|
-
} catch (ex) {
|
|
3887
|
-
return false;
|
|
3888
|
-
}
|
|
3889
|
-
};
|
|
3890
|
-
JSEncryptRSAKey2.prototype.getPrivateBaseKey = function() {
|
|
3891
|
-
var options = {
|
|
3892
|
-
array: [
|
|
3893
|
-
new KJUR.asn1.DERInteger({ int: 0 }),
|
|
3894
|
-
new KJUR.asn1.DERInteger({ bigint: this.n }),
|
|
3895
|
-
new KJUR.asn1.DERInteger({ int: this.e }),
|
|
3896
|
-
new KJUR.asn1.DERInteger({ bigint: this.d }),
|
|
3897
|
-
new KJUR.asn1.DERInteger({ bigint: this.p }),
|
|
3898
|
-
new KJUR.asn1.DERInteger({ bigint: this.q }),
|
|
3899
|
-
new KJUR.asn1.DERInteger({ bigint: this.dmp1 }),
|
|
3900
|
-
new KJUR.asn1.DERInteger({ bigint: this.dmq1 }),
|
|
3901
|
-
new KJUR.asn1.DERInteger({ bigint: this.coeff })
|
|
3902
|
-
]
|
|
3903
|
-
};
|
|
3904
|
-
var seq = new KJUR.asn1.DERSequence(options);
|
|
3905
|
-
return seq.getEncodedHex();
|
|
3906
|
-
};
|
|
3907
|
-
JSEncryptRSAKey2.prototype.getPrivateBaseKeyB64 = function() {
|
|
3908
|
-
return hex2b64(this.getPrivateBaseKey());
|
|
3909
|
-
};
|
|
3910
|
-
JSEncryptRSAKey2.prototype.getPublicBaseKey = function() {
|
|
3911
|
-
var first_sequence = new KJUR.asn1.DERSequence({
|
|
3912
|
-
array: [
|
|
3913
|
-
new KJUR.asn1.DERObjectIdentifier({ oid: "1.2.840.113549.1.1.1" }),
|
|
3914
|
-
// RSA Encryption pkcs #1 oid
|
|
3915
|
-
new KJUR.asn1.DERNull()
|
|
3916
|
-
]
|
|
3917
|
-
});
|
|
3918
|
-
var second_sequence = new KJUR.asn1.DERSequence({
|
|
3919
|
-
array: [
|
|
3920
|
-
new KJUR.asn1.DERInteger({ bigint: this.n }),
|
|
3921
|
-
new KJUR.asn1.DERInteger({ int: this.e })
|
|
3922
|
-
]
|
|
3923
|
-
});
|
|
3924
|
-
var bit_string = new KJUR.asn1.DERBitString({
|
|
3925
|
-
hex: "00" + second_sequence.getEncodedHex()
|
|
3926
|
-
});
|
|
3927
|
-
var seq = new KJUR.asn1.DERSequence({
|
|
3928
|
-
array: [first_sequence, bit_string]
|
|
3929
|
-
});
|
|
3930
|
-
return seq.getEncodedHex();
|
|
3931
|
-
};
|
|
3932
|
-
JSEncryptRSAKey2.prototype.getPublicBaseKeyB64 = function() {
|
|
3933
|
-
return hex2b64(this.getPublicBaseKey());
|
|
3934
|
-
};
|
|
3935
|
-
JSEncryptRSAKey2.wordwrap = function(str, width) {
|
|
3936
|
-
width = width || 64;
|
|
3937
|
-
if (!str) {
|
|
3938
|
-
return str;
|
|
3939
|
-
}
|
|
3940
|
-
var regex = "(.{1," + width + "})( +|$\n?)|(.{1," + width + "})";
|
|
3941
|
-
return str.match(RegExp(regex, "g")).join("\n");
|
|
3942
|
-
};
|
|
3943
|
-
JSEncryptRSAKey2.prototype.getPrivateKey = function() {
|
|
3944
|
-
var key = "-----BEGIN RSA PRIVATE KEY-----\n";
|
|
3945
|
-
key += JSEncryptRSAKey2.wordwrap(this.getPrivateBaseKeyB64()) + "\n";
|
|
3946
|
-
key += "-----END RSA PRIVATE KEY-----";
|
|
3947
|
-
return key;
|
|
3948
|
-
};
|
|
3949
|
-
JSEncryptRSAKey2.prototype.getPublicKey = function() {
|
|
3950
|
-
var key = "-----BEGIN PUBLIC KEY-----\n";
|
|
3951
|
-
key += JSEncryptRSAKey2.wordwrap(this.getPublicBaseKeyB64()) + "\n";
|
|
3952
|
-
key += "-----END PUBLIC KEY-----";
|
|
3953
|
-
return key;
|
|
3954
|
-
};
|
|
3955
|
-
JSEncryptRSAKey2.hasPublicKeyProperty = function(obj) {
|
|
3956
|
-
obj = obj || {};
|
|
3957
|
-
return obj.hasOwnProperty("n") && obj.hasOwnProperty("e");
|
|
3958
|
-
};
|
|
3959
|
-
JSEncryptRSAKey2.hasPrivateKeyProperty = function(obj) {
|
|
3960
|
-
obj = obj || {};
|
|
3961
|
-
return obj.hasOwnProperty("n") && obj.hasOwnProperty("e") && obj.hasOwnProperty("d") && obj.hasOwnProperty("p") && obj.hasOwnProperty("q") && obj.hasOwnProperty("dmp1") && obj.hasOwnProperty("dmq1") && obj.hasOwnProperty("coeff");
|
|
3962
|
-
};
|
|
3963
|
-
JSEncryptRSAKey2.prototype.parsePropertiesFrom = function(obj) {
|
|
3964
|
-
this.n = obj.n;
|
|
3965
|
-
this.e = obj.e;
|
|
3966
|
-
if (obj.hasOwnProperty("d")) {
|
|
3967
|
-
this.d = obj.d;
|
|
3968
|
-
this.p = obj.p;
|
|
3969
|
-
this.q = obj.q;
|
|
3970
|
-
this.dmp1 = obj.dmp1;
|
|
3971
|
-
this.dmq1 = obj.dmq1;
|
|
3972
|
-
this.coeff = obj.coeff;
|
|
3973
|
-
}
|
|
3974
|
-
};
|
|
3975
|
-
return JSEncryptRSAKey2;
|
|
3976
|
-
}(RSAKey)
|
|
3977
|
-
);
|
|
3978
|
-
var _a;
|
|
3979
|
-
var version = typeof process !== "undefined" ? (_a = process.env) === null || _a === void 0 ? void 0 : _a.npm_package_version : void 0;
|
|
3980
|
-
var JSEncrypt = (
|
|
3981
|
-
/** @class */
|
|
3982
|
-
function() {
|
|
3983
|
-
function JSEncrypt2(options) {
|
|
3984
|
-
if (options === void 0) {
|
|
3985
|
-
options = {};
|
|
3986
|
-
}
|
|
3987
|
-
this.default_key_size = options.default_key_size ? parseInt(options.default_key_size, 10) : 1024;
|
|
3988
|
-
this.default_public_exponent = options.default_public_exponent || "010001";
|
|
3989
|
-
this.log = options.log || false;
|
|
3990
|
-
this.key = options.key || null;
|
|
3991
|
-
}
|
|
3992
|
-
JSEncrypt2.prototype.setKey = function(key) {
|
|
3993
|
-
if (key) {
|
|
3994
|
-
if (this.log && this.key) {
|
|
3995
|
-
console.warn("A key was already set, overriding existing.");
|
|
3996
|
-
}
|
|
3997
|
-
this.key = new JSEncryptRSAKey(key);
|
|
3998
|
-
} else if (!this.key && this.log) {
|
|
3999
|
-
console.error("A key was not set.");
|
|
4000
|
-
}
|
|
4001
|
-
};
|
|
4002
|
-
JSEncrypt2.prototype.setPrivateKey = function(privkey) {
|
|
4003
|
-
this.setKey(privkey);
|
|
4004
|
-
};
|
|
4005
|
-
JSEncrypt2.prototype.setPublicKey = function(pubkey) {
|
|
4006
|
-
this.setKey(pubkey);
|
|
4007
|
-
};
|
|
4008
|
-
JSEncrypt2.prototype.decrypt = function(str) {
|
|
4009
|
-
try {
|
|
4010
|
-
return this.getKey().decrypt(b64tohex(str));
|
|
4011
|
-
} catch (ex) {
|
|
4012
|
-
return false;
|
|
4013
|
-
}
|
|
4014
|
-
};
|
|
4015
|
-
JSEncrypt2.prototype.encrypt = function(str) {
|
|
4016
|
-
try {
|
|
4017
|
-
return hex2b64(this.getKey().encrypt(str));
|
|
4018
|
-
} catch (ex) {
|
|
4019
|
-
return false;
|
|
4020
|
-
}
|
|
4021
|
-
};
|
|
4022
|
-
JSEncrypt2.prototype.encryptOAEP = function(str) {
|
|
4023
|
-
try {
|
|
4024
|
-
return hex2b64(this.getKey().encrypt(str, oaep_pad));
|
|
4025
|
-
} catch (ex) {
|
|
4026
|
-
return false;
|
|
4027
|
-
}
|
|
4028
|
-
};
|
|
4029
|
-
JSEncrypt2.prototype.sign = function(str, digestMethod, digestName) {
|
|
4030
|
-
if (digestMethod === void 0) {
|
|
4031
|
-
digestMethod = function(raw) {
|
|
4032
|
-
return raw;
|
|
4033
|
-
};
|
|
4034
|
-
}
|
|
4035
|
-
if (digestName === void 0) {
|
|
4036
|
-
digestName = "";
|
|
4037
|
-
}
|
|
4038
|
-
try {
|
|
4039
|
-
return hex2b64(this.getKey().sign(str, digestMethod, digestName));
|
|
4040
|
-
} catch (ex) {
|
|
4041
|
-
return false;
|
|
4042
|
-
}
|
|
4043
|
-
};
|
|
4044
|
-
JSEncrypt2.prototype.signSha256 = function(str) {
|
|
4045
|
-
return this.sign(str, function(text) {
|
|
4046
|
-
return rstr2hex(rstr_sha256(text));
|
|
4047
|
-
}, "sha256");
|
|
4048
|
-
};
|
|
4049
|
-
JSEncrypt2.prototype.verify = function(str, signature, digestMethod) {
|
|
4050
|
-
if (digestMethod === void 0) {
|
|
4051
|
-
digestMethod = function(raw) {
|
|
4052
|
-
return raw;
|
|
4053
|
-
};
|
|
4054
|
-
}
|
|
4055
|
-
try {
|
|
4056
|
-
return this.getKey().verify(str, b64tohex(signature), digestMethod);
|
|
4057
|
-
} catch (ex) {
|
|
4058
|
-
return false;
|
|
4059
|
-
}
|
|
4060
|
-
};
|
|
4061
|
-
JSEncrypt2.prototype.verifySha256 = function(str, signature) {
|
|
4062
|
-
return this.verify(str, signature, function(text) {
|
|
4063
|
-
return rstr2hex(rstr_sha256(text));
|
|
4064
|
-
});
|
|
4065
|
-
};
|
|
4066
|
-
JSEncrypt2.prototype.getKey = function(cb) {
|
|
4067
|
-
if (!this.key) {
|
|
4068
|
-
this.key = new JSEncryptRSAKey();
|
|
4069
|
-
if (cb && {}.toString.call(cb) === "[object Function]") {
|
|
4070
|
-
this.key.generateAsync(this.default_key_size, this.default_public_exponent, cb);
|
|
4071
|
-
return;
|
|
4072
|
-
}
|
|
4073
|
-
this.key.generate(this.default_key_size, this.default_public_exponent);
|
|
4074
|
-
}
|
|
4075
|
-
return this.key;
|
|
4076
|
-
};
|
|
4077
|
-
JSEncrypt2.prototype.getPrivateKey = function() {
|
|
4078
|
-
return this.getKey().getPrivateKey();
|
|
4079
|
-
};
|
|
4080
|
-
JSEncrypt2.prototype.getPrivateKeyB64 = function() {
|
|
4081
|
-
return this.getKey().getPrivateBaseKeyB64();
|
|
4082
|
-
};
|
|
4083
|
-
JSEncrypt2.prototype.getPublicKey = function() {
|
|
4084
|
-
return this.getKey().getPublicKey();
|
|
4085
|
-
};
|
|
4086
|
-
JSEncrypt2.prototype.getPublicKeyB64 = function() {
|
|
4087
|
-
return this.getKey().getPublicBaseKeyB64();
|
|
4088
|
-
};
|
|
4089
|
-
JSEncrypt2.version = version;
|
|
4090
|
-
return JSEncrypt2;
|
|
4091
|
-
}()
|
|
4092
|
-
);
|
|
4093
|
-
const PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBSYtNb6neLrrwsuPBsIFjpZBrffdkA8bpp2S35o2TCdhfdxS0nc4pkv9cJLkUvFa+gdQ5nLifnK9B1XoVbIQwY212QAftTDbl77bcHu7GAbv2TZr9pelSeUm1SrtMK5HDr/LzxTutGr4DovVHiDgEn45GQ1X5U+zC0Jp4Awn6ZwIDAQAB";
|
|
4094
|
-
function rsaEncrypt(txt) {
|
|
4095
|
-
const encrypt = new JSEncrypt();
|
|
4096
|
-
encrypt.setPublicKey(PUBLIC_KEY);
|
|
4097
|
-
const result = encrypt.encrypt(txt);
|
|
4098
|
-
return result || null;
|
|
4099
|
-
}
|
|
4100
|
-
function getHomeDir$1() {
|
|
4101
|
-
return process$1.env.HOME || process$1.env.USERPROFILE || "";
|
|
4102
|
-
}
|
|
4103
|
-
const PLUGIN_PACKAGE_NAME$1 = "@workclaw/openclaw-workclaw";
|
|
4104
|
-
function deepMerge$1(target, source) {
|
|
4105
|
-
const result = { ...target };
|
|
4106
|
-
for (const key in source) {
|
|
4107
|
-
const sourceValue = source[key];
|
|
4108
|
-
const targetValue = target[key];
|
|
4109
|
-
if (sourceValue !== void 0 && sourceValue !== null && typeof sourceValue === "object" && !Array.isArray(sourceValue) && typeof targetValue === "object" && targetValue !== null && !Array.isArray(targetValue)) {
|
|
4110
|
-
result[key] = deepMerge$1(targetValue, sourceValue);
|
|
4111
|
-
} else if (sourceValue !== void 0) {
|
|
4112
|
-
result[key] = sourceValue;
|
|
4097
|
+
this.hTLV = null;
|
|
4098
|
+
this.isModified = true;
|
|
4099
|
+
this.s = null;
|
|
4100
|
+
this.hV = h;
|
|
4101
|
+
};
|
|
4102
|
+
this.setValueName = function(oidName) {
|
|
4103
|
+
var oid = KJUR.asn1.x509.OID.name2oid(oidName);
|
|
4104
|
+
if (oid !== "") {
|
|
4105
|
+
this.setValueOidString(oid);
|
|
4106
|
+
} else {
|
|
4107
|
+
throw "DERObjectIdentifier oidName undefined: " + oidName;
|
|
4108
|
+
}
|
|
4109
|
+
};
|
|
4110
|
+
this.getFreshValueHex = function() {
|
|
4111
|
+
return this.hV;
|
|
4112
|
+
};
|
|
4113
|
+
if (params !== void 0) {
|
|
4114
|
+
if (typeof params === "string") {
|
|
4115
|
+
if (params.match(/^[0-2].[0-9.]+$/)) {
|
|
4116
|
+
this.setValueOidString(params);
|
|
4117
|
+
} else {
|
|
4118
|
+
this.setValueName(params);
|
|
4119
|
+
}
|
|
4120
|
+
} else if (params.oid !== void 0) {
|
|
4121
|
+
this.setValueOidString(params.oid);
|
|
4122
|
+
} else if (params.hex !== void 0) {
|
|
4123
|
+
this.setValueHex(params.hex);
|
|
4124
|
+
} else if (params.name !== void 0) {
|
|
4125
|
+
this.setValueName(params.name);
|
|
4113
4126
|
}
|
|
4114
4127
|
}
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
constructor(
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4128
|
+
};
|
|
4129
|
+
extendClass(KJUR.asn1.DERObjectIdentifier, KJUR.asn1.ASN1Object);
|
|
4130
|
+
KJUR.asn1.DEREnumerated = function(params) {
|
|
4131
|
+
KJUR.asn1.DEREnumerated.superclass.constructor.call(this);
|
|
4132
|
+
this.hT = "0a";
|
|
4133
|
+
this.setByBigInteger = function(bigIntegerValue) {
|
|
4134
|
+
this.hTLV = null;
|
|
4135
|
+
this.isModified = true;
|
|
4136
|
+
this.hV = KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(bigIntegerValue);
|
|
4137
|
+
};
|
|
4138
|
+
this.setByInteger = function(intValue) {
|
|
4139
|
+
var bi = new BigInteger(String(intValue), 10);
|
|
4140
|
+
this.setByBigInteger(bi);
|
|
4141
|
+
};
|
|
4142
|
+
this.setValueHex = function(newHexString) {
|
|
4143
|
+
this.hV = newHexString;
|
|
4144
|
+
};
|
|
4145
|
+
this.getFreshValueHex = function() {
|
|
4146
|
+
return this.hV;
|
|
4147
|
+
};
|
|
4148
|
+
if (typeof params != "undefined") {
|
|
4149
|
+
if (typeof params["int"] != "undefined") {
|
|
4150
|
+
this.setByInteger(params["int"]);
|
|
4151
|
+
} else if (typeof params == "number") {
|
|
4152
|
+
this.setByInteger(params);
|
|
4153
|
+
} else if (typeof params["hex"] != "undefined") {
|
|
4154
|
+
this.setValueHex(params["hex"]);
|
|
4127
4155
|
}
|
|
4128
|
-
return PLUGIN_PACKAGE_NAME$1;
|
|
4129
4156
|
}
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4157
|
+
};
|
|
4158
|
+
extendClass(KJUR.asn1.DEREnumerated, KJUR.asn1.ASN1Object);
|
|
4159
|
+
KJUR.asn1.DERUTF8String = function(params) {
|
|
4160
|
+
KJUR.asn1.DERUTF8String.superclass.constructor.call(this, params);
|
|
4161
|
+
this.hT = "0c";
|
|
4162
|
+
};
|
|
4163
|
+
extendClass(KJUR.asn1.DERUTF8String, KJUR.asn1.DERAbstractString);
|
|
4164
|
+
KJUR.asn1.DERNumericString = function(params) {
|
|
4165
|
+
KJUR.asn1.DERNumericString.superclass.constructor.call(this, params);
|
|
4166
|
+
this.hT = "12";
|
|
4167
|
+
};
|
|
4168
|
+
extendClass(KJUR.asn1.DERNumericString, KJUR.asn1.DERAbstractString);
|
|
4169
|
+
KJUR.asn1.DERPrintableString = function(params) {
|
|
4170
|
+
KJUR.asn1.DERPrintableString.superclass.constructor.call(this, params);
|
|
4171
|
+
this.hT = "13";
|
|
4172
|
+
};
|
|
4173
|
+
extendClass(KJUR.asn1.DERPrintableString, KJUR.asn1.DERAbstractString);
|
|
4174
|
+
KJUR.asn1.DERTeletexString = function(params) {
|
|
4175
|
+
KJUR.asn1.DERTeletexString.superclass.constructor.call(this, params);
|
|
4176
|
+
this.hT = "14";
|
|
4177
|
+
};
|
|
4178
|
+
extendClass(KJUR.asn1.DERTeletexString, KJUR.asn1.DERAbstractString);
|
|
4179
|
+
KJUR.asn1.DERIA5String = function(params) {
|
|
4180
|
+
KJUR.asn1.DERIA5String.superclass.constructor.call(this, params);
|
|
4181
|
+
this.hT = "16";
|
|
4182
|
+
};
|
|
4183
|
+
extendClass(KJUR.asn1.DERIA5String, KJUR.asn1.DERAbstractString);
|
|
4184
|
+
KJUR.asn1.DERUTCTime = function(params) {
|
|
4185
|
+
KJUR.asn1.DERUTCTime.superclass.constructor.call(this, params);
|
|
4186
|
+
this.hT = "17";
|
|
4187
|
+
this.setByDate = function(dateObject) {
|
|
4188
|
+
this.hTLV = null;
|
|
4189
|
+
this.isModified = true;
|
|
4190
|
+
this.date = dateObject;
|
|
4191
|
+
this.s = this.formatDate(this.date, "utc");
|
|
4192
|
+
this.hV = stohex(this.s);
|
|
4193
|
+
};
|
|
4194
|
+
this.getFreshValueHex = function() {
|
|
4195
|
+
if (typeof this.date == "undefined" && typeof this.s == "undefined") {
|
|
4196
|
+
this.date = /* @__PURE__ */ new Date();
|
|
4197
|
+
this.s = this.formatDate(this.date, "utc");
|
|
4198
|
+
this.hV = stohex(this.s);
|
|
4134
4199
|
}
|
|
4135
|
-
|
|
4136
|
-
|
|
4200
|
+
return this.hV;
|
|
4201
|
+
};
|
|
4202
|
+
if (params !== void 0) {
|
|
4203
|
+
if (params.str !== void 0) {
|
|
4204
|
+
this.setString(params.str);
|
|
4205
|
+
} else if (typeof params == "string" && params.match(/^[0-9]{12}Z$/)) {
|
|
4206
|
+
this.setString(params);
|
|
4207
|
+
} else if (params.hex !== void 0) {
|
|
4208
|
+
this.setStringHex(params.hex);
|
|
4209
|
+
} else if (params.date !== void 0) {
|
|
4210
|
+
this.setByDate(params.date);
|
|
4137
4211
|
}
|
|
4138
|
-
debugLog("[验证配置] 配置验证通过");
|
|
4139
4212
|
}
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
debugLog(`[路径配置] config=${paths.config}`);
|
|
4159
|
-
debugLog(`[路径配置] workspace=${paths.workspace}`);
|
|
4160
|
-
const token = await this.doLogin(env);
|
|
4161
|
-
const boundConfig = await this.doFetchBoundConfig(env, token);
|
|
4162
|
-
await this.doCleanOldFiles(paths.target);
|
|
4163
|
-
await this.doDownloadFromNpm(paths);
|
|
4164
|
-
await this.doUpdateConfig(paths, boundConfig, env);
|
|
4165
|
-
this.spinner.stop();
|
|
4166
|
-
} catch (error) {
|
|
4167
|
-
this.spinner.stop();
|
|
4168
|
-
throw error;
|
|
4213
|
+
};
|
|
4214
|
+
extendClass(KJUR.asn1.DERUTCTime, KJUR.asn1.DERAbstractTime);
|
|
4215
|
+
KJUR.asn1.DERGeneralizedTime = function(params) {
|
|
4216
|
+
KJUR.asn1.DERGeneralizedTime.superclass.constructor.call(this, params);
|
|
4217
|
+
this.hT = "18";
|
|
4218
|
+
this.withMillis = false;
|
|
4219
|
+
this.setByDate = function(dateObject) {
|
|
4220
|
+
this.hTLV = null;
|
|
4221
|
+
this.isModified = true;
|
|
4222
|
+
this.date = dateObject;
|
|
4223
|
+
this.s = this.formatDate(this.date, "gen", this.withMillis);
|
|
4224
|
+
this.hV = stohex(this.s);
|
|
4225
|
+
};
|
|
4226
|
+
this.getFreshValueHex = function() {
|
|
4227
|
+
if (this.date === void 0 && this.s === void 0) {
|
|
4228
|
+
this.date = /* @__PURE__ */ new Date();
|
|
4229
|
+
this.s = this.formatDate(this.date, "gen", this.withMillis);
|
|
4230
|
+
this.hV = stohex(this.s);
|
|
4169
4231
|
}
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
throw new AppError$1(ERROR_CODES$1.LOGIN_FAILED, "密码加密失败");
|
|
4232
|
+
return this.hV;
|
|
4233
|
+
};
|
|
4234
|
+
if (params !== void 0) {
|
|
4235
|
+
if (params.str !== void 0) {
|
|
4236
|
+
this.setString(params.str);
|
|
4237
|
+
} else if (typeof params == "string" && params.match(/^[0-9]{14}Z$/)) {
|
|
4238
|
+
this.setString(params);
|
|
4239
|
+
} else if (params.hex !== void 0) {
|
|
4240
|
+
this.setStringHex(params.hex);
|
|
4241
|
+
} else if (params.date !== void 0) {
|
|
4242
|
+
this.setByDate(params.date);
|
|
4182
4243
|
}
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
const token = await login(this.config.phone, encryptedPassword, env);
|
|
4186
|
-
this.prefixText += chalk.green(`✓ 用户登录成功
|
|
4187
|
-
`);
|
|
4188
|
-
debugLog("[用户登录] 登录成功");
|
|
4189
|
-
return token;
|
|
4190
|
-
}
|
|
4191
|
-
async doFetchBoundConfig(env, token) {
|
|
4192
|
-
this.spinner.prefixText = this.prefixText;
|
|
4193
|
-
this.spinner.text = `${chalk.cyan("获取配置")} ${chalk.dim("→")} ${chalk.yellow("正在获取绑定配置...")}`;
|
|
4194
|
-
debugLog("[获取配置] 调用绑定配置接口...");
|
|
4195
|
-
const boundConfig = await fetchBoundConfig(token, this.config.phone, env);
|
|
4196
|
-
debugLog(`[获取配置] agentId=${boundConfig.agentId}, appKey=${boundConfig.appKey?.slice(0, 8)}...`);
|
|
4197
|
-
this.prefixText += chalk.green(`✓ 绑定配置获取成功
|
|
4198
|
-
`);
|
|
4199
|
-
debugLog("[获取配置] 获取成功");
|
|
4200
|
-
return boundConfig;
|
|
4201
|
-
}
|
|
4202
|
-
async doCleanOldFiles(targetPath) {
|
|
4203
|
-
this.spinner.prefixText = this.prefixText;
|
|
4204
|
-
this.spinner.text = `${chalk.cyan("清理旧版本")} ${chalk.dim("→")} ${chalk.yellow("检查目录...")}`;
|
|
4205
|
-
debugLog(`[清理旧版本] 检查目录: ${targetPath}`);
|
|
4206
|
-
try {
|
|
4207
|
-
await fs.access(targetPath);
|
|
4208
|
-
debugLog("[清理旧版本] 发现旧版本,开始清理...");
|
|
4209
|
-
this.spinner.prefixText = this.prefixText;
|
|
4210
|
-
this.spinner.text = `${chalk.cyan("清理旧版本")} ${chalk.dim("→")} ${chalk.yellow("正在清理...")}`;
|
|
4211
|
-
await fs.rm(targetPath, { recursive: true, force: true });
|
|
4212
|
-
this.prefixText += chalk.green(`✓ 旧版本清理完成
|
|
4213
|
-
`);
|
|
4214
|
-
debugLog("[清理旧版本] 清理完成");
|
|
4215
|
-
} catch {
|
|
4216
|
-
this.prefixText += chalk.green(`✓ 未发现旧版本
|
|
4217
|
-
`);
|
|
4218
|
-
debugLog("[清理旧版本] 未发现旧版本");
|
|
4244
|
+
if (params.millis === true) {
|
|
4245
|
+
this.withMillis = true;
|
|
4219
4246
|
}
|
|
4220
4247
|
}
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
this.spinner.text = `${chalk.cyan("下载插件")} ${chalk.dim("→")} ${chalk.yellow("下载 tarball")}`;
|
|
4232
|
-
debugLog("[下载插件] 执行 npm pack 下载源码包");
|
|
4233
|
-
debugLog(`[下载插件] 工作目录: ${tempDir}`);
|
|
4234
|
-
const maxRetries = 3;
|
|
4235
|
-
let lastError = "";
|
|
4236
|
-
let tarballPath = "";
|
|
4237
|
-
for (let i = 1; i <= maxRetries; i++) {
|
|
4238
|
-
debugLog(`[下载插件] 第 ${i} 次尝试下载 tarball...`);
|
|
4239
|
-
try {
|
|
4240
|
-
const packageName = this.getPackageName();
|
|
4241
|
-
debugLog(`[下载插件] 下载包名: ${packageName}`);
|
|
4242
|
-
const output = execSync(
|
|
4243
|
-
`npm pack ${packageName} --registry=https://mirrors.tencent.com/npm/ --ignore-scripts`,
|
|
4244
|
-
{ cwd: tempDir, encoding: "utf-8", timeout: 6e4 }
|
|
4245
|
-
);
|
|
4246
|
-
const filename = output.trim().split("\n").pop() || "";
|
|
4247
|
-
tarballPath = path.join(tempDir, filename);
|
|
4248
|
-
debugLog(`[下载插件] tarball 下载成功: ${tarballPath}`);
|
|
4249
|
-
break;
|
|
4250
|
-
} catch (error) {
|
|
4251
|
-
lastError = error.stderr?.toString() || error.message || "未知错误";
|
|
4252
|
-
debugLog(`[下载插件] 第 ${i} 次尝试失败: ${lastError}`);
|
|
4253
|
-
if (i < maxRetries) {
|
|
4254
|
-
debugLog("[下载插件] 等待 3 秒后重试...");
|
|
4255
|
-
await new Promise((resolve2) => setTimeout(resolve2, 3e3));
|
|
4256
|
-
}
|
|
4257
|
-
}
|
|
4248
|
+
};
|
|
4249
|
+
extendClass(KJUR.asn1.DERGeneralizedTime, KJUR.asn1.DERAbstractTime);
|
|
4250
|
+
KJUR.asn1.DERSequence = function(params) {
|
|
4251
|
+
KJUR.asn1.DERSequence.superclass.constructor.call(this, params);
|
|
4252
|
+
this.hT = "30";
|
|
4253
|
+
this.getFreshValueHex = function() {
|
|
4254
|
+
var h = "";
|
|
4255
|
+
for (var i = 0; i < this.asn1Array.length; i++) {
|
|
4256
|
+
var asn1Obj = this.asn1Array[i];
|
|
4257
|
+
h += asn1Obj.getEncodedHex();
|
|
4258
4258
|
}
|
|
4259
|
-
|
|
4260
|
-
|
|
4259
|
+
this.hV = h;
|
|
4260
|
+
return this.hV;
|
|
4261
|
+
};
|
|
4262
|
+
};
|
|
4263
|
+
extendClass(KJUR.asn1.DERSequence, KJUR.asn1.DERAbstractStructured);
|
|
4264
|
+
KJUR.asn1.DERSet = function(params) {
|
|
4265
|
+
KJUR.asn1.DERSet.superclass.constructor.call(this, params);
|
|
4266
|
+
this.hT = "31";
|
|
4267
|
+
this.sortFlag = true;
|
|
4268
|
+
this.getFreshValueHex = function() {
|
|
4269
|
+
var a = new Array();
|
|
4270
|
+
for (var i = 0; i < this.asn1Array.length; i++) {
|
|
4271
|
+
var asn1Obj = this.asn1Array[i];
|
|
4272
|
+
a.push(asn1Obj.getEncodedHex());
|
|
4261
4273
|
}
|
|
4262
|
-
this.
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4274
|
+
if (this.sortFlag == true)
|
|
4275
|
+
a.sort();
|
|
4276
|
+
this.hV = a.join("");
|
|
4277
|
+
return this.hV;
|
|
4278
|
+
};
|
|
4279
|
+
if (typeof params != "undefined") {
|
|
4280
|
+
if (typeof params.sortflag != "undefined" && params.sortflag == false)
|
|
4281
|
+
this.sortFlag = false;
|
|
4282
|
+
}
|
|
4283
|
+
};
|
|
4284
|
+
extendClass(KJUR.asn1.DERSet, KJUR.asn1.DERAbstractStructured);
|
|
4285
|
+
KJUR.asn1.DERTaggedObject = function(params) {
|
|
4286
|
+
KJUR.asn1.DERTaggedObject.superclass.constructor.call(this);
|
|
4287
|
+
this.hT = "a0";
|
|
4288
|
+
this.hV = "";
|
|
4289
|
+
this.isExplicit = true;
|
|
4290
|
+
this.asn1Object = null;
|
|
4291
|
+
this.setASN1Object = function(isExplicitFlag, tagNoHex, asn1Object) {
|
|
4292
|
+
this.hT = tagNoHex;
|
|
4293
|
+
this.isExplicit = isExplicitFlag;
|
|
4294
|
+
this.asn1Object = asn1Object;
|
|
4295
|
+
if (this.isExplicit) {
|
|
4296
|
+
this.hV = this.asn1Object.getEncodedHex();
|
|
4297
|
+
this.hTLV = null;
|
|
4298
|
+
this.isModified = true;
|
|
4299
|
+
} else {
|
|
4300
|
+
this.hV = null;
|
|
4301
|
+
this.hTLV = asn1Object.getEncodedHex();
|
|
4302
|
+
this.hTLV = this.hTLV.replace(/^../, tagNoHex);
|
|
4303
|
+
this.isModified = false;
|
|
4276
4304
|
}
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4305
|
+
};
|
|
4306
|
+
this.getFreshValueHex = function() {
|
|
4307
|
+
return this.hV;
|
|
4308
|
+
};
|
|
4309
|
+
if (typeof params != "undefined") {
|
|
4310
|
+
if (typeof params["tag"] != "undefined") {
|
|
4311
|
+
this.hT = params["tag"];
|
|
4281
4312
|
}
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
this.spinner.text = `${chalk.cyan("下载插件")} ${chalk.dim("→")} ${chalk.yellow("安装依赖")}`;
|
|
4285
|
-
debugLog("[下载插件] 执行 npm install 安装生产环境依赖");
|
|
4286
|
-
try {
|
|
4287
|
-
execSync("npm install --omit=dev --ignore-scripts", {
|
|
4288
|
-
cwd: paths.target,
|
|
4289
|
-
stdio: "pipe",
|
|
4290
|
-
timeout: 12e4
|
|
4291
|
-
});
|
|
4292
|
-
debugLog("[下载插件] npm install 执行成功");
|
|
4293
|
-
} catch (error) {
|
|
4294
|
-
const stderr = error.stderr?.toString() || "";
|
|
4295
|
-
const stdout = error.stdout?.toString() || "";
|
|
4296
|
-
const combinedOutput = stderr + stdout;
|
|
4297
|
-
if (combinedOutput.includes("npm warn") || combinedOutput.includes("deprecated")) {
|
|
4298
|
-
debugLog("[下载插件] npm install 有警告但可能成功,继续流程");
|
|
4299
|
-
} else {
|
|
4300
|
-
debugLog(`[下载插件] npm install 失败: ${combinedOutput}`);
|
|
4301
|
-
}
|
|
4313
|
+
if (typeof params["explicit"] != "undefined") {
|
|
4314
|
+
this.isExplicit = params["explicit"];
|
|
4302
4315
|
}
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
await fs.rm(tempDir, { recursive: true, force: true });
|
|
4307
|
-
debugLog("[下载插件] 清理临时目录完成");
|
|
4308
|
-
} catch {
|
|
4309
|
-
debugLog("[下载插件] 清理临时目录失败(忽略)");
|
|
4316
|
+
if (typeof params["obj"] != "undefined") {
|
|
4317
|
+
this.asn1Object = params["obj"];
|
|
4318
|
+
this.setASN1Object(this.isExplicit, this.hT, this.asn1Object);
|
|
4310
4319
|
}
|
|
4311
4320
|
}
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
// 配置合并模式:'merge' 合并 | 'replace' 替换
|
|
4345
|
-
mode: "merge",
|
|
4346
|
-
providers: {
|
|
4347
|
-
"siliconflow-minimax": {
|
|
4348
|
-
// 模型 API 基础地址
|
|
4349
|
-
baseUrl: boundConfig.modelApiBaseUrl || config.MODEL_BASE_URL,
|
|
4350
|
-
// API 密钥(从服务器获取)
|
|
4351
|
-
apiKey: boundConfig.modelApiKey,
|
|
4352
|
-
// API 类型:'openai-completions' | 'openai-chat' 等
|
|
4353
|
-
api: "openai-completions",
|
|
4354
|
-
// 是否使用 Authorization header 认证
|
|
4355
|
-
authHeader: true,
|
|
4356
|
-
models: [{
|
|
4357
|
-
// 模型 ID(provider/model 格式)
|
|
4358
|
-
id: "Pro/MiniMaxAI/MiniMax-M2.5",
|
|
4359
|
-
// 模型显示名称
|
|
4360
|
-
name: "MiniMax-M2.5",
|
|
4361
|
-
// 是否启用推理能力
|
|
4362
|
-
reasoning: false,
|
|
4363
|
-
// 支持的输入类型:['text'] | ['text', 'image']
|
|
4364
|
-
input: ["text"],
|
|
4365
|
-
// 价格(0 表示免费或未设置)
|
|
4366
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
4367
|
-
// 上下文窗口大小(token)
|
|
4368
|
-
contextWindow: 2e5,
|
|
4369
|
-
// 最大输出 token 数
|
|
4370
|
-
maxTokens: 65536
|
|
4371
|
-
}]
|
|
4372
|
-
}
|
|
4373
|
-
}
|
|
4374
|
-
},
|
|
4375
|
-
// agents: 代理配置
|
|
4376
|
-
agents: {
|
|
4377
|
-
defaults: {
|
|
4378
|
-
// 默认使用的模型
|
|
4379
|
-
model: { primary: "siliconflow-minimax/Pro/MiniMaxAI/MiniMax-M2.5" },
|
|
4380
|
-
models: {
|
|
4381
|
-
"siliconflow-minimax/Pro/MiniMaxAI/MiniMax-M2.5": {
|
|
4382
|
-
// 模型别名,用于显示
|
|
4383
|
-
alias: "Pro/MiniMaxAI/MiniMax-M2.5"
|
|
4384
|
-
}
|
|
4385
|
-
},
|
|
4386
|
-
// 工作区目录路径
|
|
4387
|
-
workspace: paths.workspace,
|
|
4388
|
-
// 会话压缩模式:'safeguard' 保守模式
|
|
4389
|
-
compaction: { mode: "safeguard" },
|
|
4390
|
-
// 详细程度:'full' | 'short' | 'off'
|
|
4391
|
-
verboseDefault: "full",
|
|
4392
|
-
// 最大并发任务数
|
|
4393
|
-
maxConcurrent: 4,
|
|
4394
|
-
// 子代理最大并发数
|
|
4395
|
-
subagents: { maxConcurrent: 8 }
|
|
4396
|
-
},
|
|
4397
|
-
// 代理列表
|
|
4398
|
-
list: [{ id: "main", workspace: paths.workspace }]
|
|
4399
|
-
},
|
|
4400
|
-
// tools: 工具配置
|
|
4401
|
-
tools: {
|
|
4402
|
-
// 禁用的工具列表(优先于 allow)
|
|
4403
|
-
deny: ["image", "web_search", "web_fetch"],
|
|
4404
|
-
// 图像分析工具
|
|
4405
|
-
media: { image: { enabled: false } },
|
|
4406
|
-
// 网络搜索和抓取工具
|
|
4407
|
-
web: { search: { enabled: false }, fetch: { enabled: false } },
|
|
4408
|
-
// 提升权限工具(host=gateway)
|
|
4409
|
-
elevated: { enabled: true, allowFrom: { webchat: ["*"] } },
|
|
4410
|
-
// exec 工具安全级别:'deny' | 'allowlist' | 'full'
|
|
4411
|
-
exec: { security: "full" }
|
|
4412
|
-
},
|
|
4413
|
-
// bindings: 绑定配置
|
|
4414
|
-
bindings: [{
|
|
4415
|
-
// 绑定的代理 ID
|
|
4416
|
-
agentId: "main",
|
|
4417
|
-
// 匹配的通道和账户
|
|
4418
|
-
match: { channel: "openclaw-workclaw", accountId: "default" }
|
|
4419
|
-
}],
|
|
4420
|
-
// messages: 消息配置
|
|
4421
|
-
messages: {
|
|
4422
|
-
// 消息确认范围
|
|
4423
|
-
ackReactionScope: "group-mentions"
|
|
4424
|
-
},
|
|
4425
|
-
// commands: 命令配置
|
|
4426
|
-
commands: {
|
|
4427
|
-
// 本机命令:'auto' | 'on' | 'off'
|
|
4428
|
-
native: "auto",
|
|
4429
|
-
// 本机技能:'auto' | 'on' | 'off'
|
|
4430
|
-
nativeSkills: "auto",
|
|
4431
|
-
// 是否允许重启命令
|
|
4432
|
-
restart: true,
|
|
4433
|
-
// 所有者显示格式:'raw' | 'name' | 'hidden'
|
|
4434
|
-
ownerDisplay: "raw"
|
|
4435
|
-
},
|
|
4436
|
-
// session: 会话配置
|
|
4437
|
-
session: {
|
|
4438
|
-
// DM 作用域
|
|
4439
|
-
dmScope: "per-account-channel-peer"
|
|
4440
|
-
},
|
|
4441
|
-
// hooks: 钩子配置
|
|
4442
|
-
hooks: {
|
|
4443
|
-
internal: {
|
|
4444
|
-
// 启用内部钩子
|
|
4445
|
-
enabled: true,
|
|
4446
|
-
entries: {
|
|
4447
|
-
// 启动 Markdown 钩子
|
|
4448
|
-
"boot-md": { enabled: true },
|
|
4449
|
-
// 引导额外文件钩子
|
|
4450
|
-
"bootstrap-extra-files": { enabled: true },
|
|
4451
|
-
// 命令日志钩子
|
|
4452
|
-
"command-logger": { enabled: true },
|
|
4453
|
-
// 会话记忆钩子
|
|
4454
|
-
"session-memory": { enabled: true }
|
|
4455
|
-
}
|
|
4456
|
-
}
|
|
4457
|
-
},
|
|
4458
|
-
// channels: 通道配置
|
|
4459
|
-
channels: {
|
|
4460
|
-
"openclaw-workclaw": {
|
|
4461
|
-
// 启用通道
|
|
4462
|
-
enabled: true,
|
|
4463
|
-
// 连接模式:'websocket' | 'http'
|
|
4464
|
-
connectionMode: "websocket",
|
|
4465
|
-
// WebSocket 连接策略
|
|
4466
|
-
wsConnectionStrategy: "per-appKey",
|
|
4467
|
-
// 应用密钥(从服务器获取)
|
|
4468
|
-
appKey: boundConfig.appKey,
|
|
4469
|
-
// 应用密钥(从服务器获取)
|
|
4470
|
-
appSecret: boundConfig.appSecret,
|
|
4471
|
-
// API 基础 URL
|
|
4472
|
-
baseUrl: this.config.baseUrl || config.DEFAULT_BASE_URL,
|
|
4473
|
-
// WebSocket URL
|
|
4474
|
-
websocketUrl: this.config.wsUrl || config.DEFAULT_WS_URL,
|
|
4475
|
-
// 允许不安全的 TLS 连接
|
|
4476
|
-
allowInsecureTls: true,
|
|
4477
|
-
// 允许原始 JSON 载荷
|
|
4478
|
-
allowRawJsonPayload: true,
|
|
4479
|
-
accounts: {
|
|
4480
|
-
// 账户配置(agentId 从服务器获取)
|
|
4481
|
-
default: { enabled: true, agentId: boundConfig.agentId }
|
|
4482
|
-
}
|
|
4483
|
-
}
|
|
4484
|
-
},
|
|
4485
|
-
// gateway: 网关配置
|
|
4486
|
-
gateway: {
|
|
4487
|
-
// 网关模式:'local' | 'hosted'
|
|
4488
|
-
mode: "local",
|
|
4489
|
-
// 网关端口
|
|
4490
|
-
port: 18789,
|
|
4491
|
-
// 绑定地址:'loopback' | 'lan' | 'all'
|
|
4492
|
-
bind: "lan",
|
|
4493
|
-
// 认证模式(token字段未设置,是因为需要使用原始配置的token)
|
|
4494
|
-
auth: {
|
|
4495
|
-
mode: "token"
|
|
4496
|
-
},
|
|
4497
|
-
// Tailscale 配置
|
|
4498
|
-
tailscale: { mode: "off", resetOnExit: false },
|
|
4499
|
-
nodes: {
|
|
4500
|
-
// 节点上禁止的命令
|
|
4501
|
-
denyCommands: [
|
|
4502
|
-
"camera.snap",
|
|
4503
|
-
"camera.clip",
|
|
4504
|
-
"screen.record",
|
|
4505
|
-
"contacts.add",
|
|
4506
|
-
"calendar.add",
|
|
4507
|
-
"reminders.add"
|
|
4508
|
-
]
|
|
4509
|
-
},
|
|
4510
|
-
controlUi: {
|
|
4511
|
-
// 允许不安全认证
|
|
4512
|
-
allowInsecureAuth: true,
|
|
4513
|
-
// 禁用设备认证(仅用于开发)
|
|
4514
|
-
dangerouslyDisableDeviceAuth: true,
|
|
4515
|
-
// 允许 Host 头源回退
|
|
4516
|
-
dangerouslyAllowHostHeaderOriginFallback: true,
|
|
4517
|
-
// 允许的源
|
|
4518
|
-
allowedOrigins: ["http://localhost:18789", "http://127.0.0.1:18789"]
|
|
4321
|
+
};
|
|
4322
|
+
extendClass(KJUR.asn1.DERTaggedObject, KJUR.asn1.ASN1Object);
|
|
4323
|
+
var __extends = /* @__PURE__ */ function() {
|
|
4324
|
+
var extendStatics = function(d, b) {
|
|
4325
|
+
extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) {
|
|
4326
|
+
d2.__proto__ = b2;
|
|
4327
|
+
} || function(d2, b2) {
|
|
4328
|
+
for (var p in b2) if (Object.prototype.hasOwnProperty.call(b2, p)) d2[p] = b2[p];
|
|
4329
|
+
};
|
|
4330
|
+
return extendStatics(d, b);
|
|
4331
|
+
};
|
|
4332
|
+
return function(d, b) {
|
|
4333
|
+
if (typeof b !== "function" && b !== null)
|
|
4334
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
4335
|
+
extendStatics(d, b);
|
|
4336
|
+
function __() {
|
|
4337
|
+
this.constructor = d;
|
|
4338
|
+
}
|
|
4339
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
4340
|
+
};
|
|
4341
|
+
}();
|
|
4342
|
+
var JSEncryptRSAKey = (
|
|
4343
|
+
/** @class */
|
|
4344
|
+
function(_super) {
|
|
4345
|
+
__extends(JSEncryptRSAKey2, _super);
|
|
4346
|
+
function JSEncryptRSAKey2(key) {
|
|
4347
|
+
var _this = _super.call(this) || this;
|
|
4348
|
+
if (key) {
|
|
4349
|
+
if (typeof key === "string") {
|
|
4350
|
+
_this.parseKey(key);
|
|
4351
|
+
} else if (JSEncryptRSAKey2.hasPrivateKeyProperty(key) || JSEncryptRSAKey2.hasPublicKeyProperty(key)) {
|
|
4352
|
+
_this.parsePropertiesFrom(key);
|
|
4519
4353
|
}
|
|
4520
|
-
}
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4354
|
+
}
|
|
4355
|
+
return _this;
|
|
4356
|
+
}
|
|
4357
|
+
JSEncryptRSAKey2.prototype.parseKey = function(pem) {
|
|
4358
|
+
try {
|
|
4359
|
+
var modulus = 0;
|
|
4360
|
+
var public_exponent = 0;
|
|
4361
|
+
var reHex = /^\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\s*)+$/;
|
|
4362
|
+
var der = reHex.test(pem) ? Hex.decode(pem) : Base64.unarmor(pem);
|
|
4363
|
+
var asn1 = ASN1.decode(der);
|
|
4364
|
+
if (asn1.sub.length === 3) {
|
|
4365
|
+
asn1 = asn1.sub[2].sub[0];
|
|
4366
|
+
}
|
|
4367
|
+
if (asn1.sub.length === 9) {
|
|
4368
|
+
modulus = asn1.sub[1].getHexStringValue();
|
|
4369
|
+
this.n = parseBigInt(modulus, 16);
|
|
4370
|
+
public_exponent = asn1.sub[2].getHexStringValue();
|
|
4371
|
+
this.e = parseInt(public_exponent, 16);
|
|
4372
|
+
var private_exponent = asn1.sub[3].getHexStringValue();
|
|
4373
|
+
this.d = parseBigInt(private_exponent, 16);
|
|
4374
|
+
var prime1 = asn1.sub[4].getHexStringValue();
|
|
4375
|
+
this.p = parseBigInt(prime1, 16);
|
|
4376
|
+
var prime2 = asn1.sub[5].getHexStringValue();
|
|
4377
|
+
this.q = parseBigInt(prime2, 16);
|
|
4378
|
+
var exponent1 = asn1.sub[6].getHexStringValue();
|
|
4379
|
+
this.dmp1 = parseBigInt(exponent1, 16);
|
|
4380
|
+
var exponent2 = asn1.sub[7].getHexStringValue();
|
|
4381
|
+
this.dmq1 = parseBigInt(exponent2, 16);
|
|
4382
|
+
var coefficient = asn1.sub[8].getHexStringValue();
|
|
4383
|
+
this.coeff = parseBigInt(coefficient, 16);
|
|
4384
|
+
} else if (asn1.sub.length === 2) {
|
|
4385
|
+
if (asn1.sub[0].sub) {
|
|
4386
|
+
var bit_string = asn1.sub[1];
|
|
4387
|
+
var sequence = bit_string.sub[0];
|
|
4388
|
+
modulus = sequence.sub[0].getHexStringValue();
|
|
4389
|
+
this.n = parseBigInt(modulus, 16);
|
|
4390
|
+
public_exponent = sequence.sub[1].getHexStringValue();
|
|
4391
|
+
this.e = parseInt(public_exponent, 16);
|
|
4392
|
+
} else {
|
|
4393
|
+
modulus = asn1.sub[0].getHexStringValue();
|
|
4394
|
+
this.n = parseBigInt(modulus, 16);
|
|
4395
|
+
public_exponent = asn1.sub[1].getHexStringValue();
|
|
4396
|
+
this.e = parseInt(public_exponent, 16);
|
|
4554
4397
|
}
|
|
4555
|
-
}
|
|
4556
|
-
|
|
4557
|
-
paths: [paths.target]
|
|
4558
|
-
},
|
|
4559
|
-
// 插件条目启用状态
|
|
4560
|
-
entries: {
|
|
4561
|
-
[config.PLUGIN_NAME]: { enabled: true }
|
|
4398
|
+
} else {
|
|
4399
|
+
return false;
|
|
4562
4400
|
}
|
|
4401
|
+
return true;
|
|
4402
|
+
} catch (ex) {
|
|
4403
|
+
return false;
|
|
4563
4404
|
}
|
|
4564
4405
|
};
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
}
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
setDebug(!!options.debug);
|
|
4592
|
-
debugLog("[初始化] 开始处理...");
|
|
4593
|
-
debugLog(`[初始化] 参数: scenario=${options.scenario}, env=${options.env}, phone=${options.phone}, debug=${options.debug}`);
|
|
4594
|
-
checkEnv$1();
|
|
4595
|
-
debugLog("[初始化] 环境检查通过");
|
|
4596
|
-
try {
|
|
4597
|
-
let scenario = options.scenario;
|
|
4598
|
-
let env = options.env;
|
|
4599
|
-
let phone = options.phone;
|
|
4600
|
-
let userPass = options.userPass;
|
|
4601
|
-
const questions = [];
|
|
4602
|
-
if (!scenario) {
|
|
4603
|
-
debugLog("[初始化] 需要选择安装场景");
|
|
4604
|
-
questions.push({
|
|
4605
|
-
type: "list",
|
|
4606
|
-
name: "scenario",
|
|
4607
|
-
message: `${nodeEmoji.get("desktop_computer")} 请选择安装场景:`,
|
|
4608
|
-
default: "windows-local",
|
|
4609
|
-
choices: [
|
|
4610
|
-
{ name: `${chalk.green("Windows")} ${chalk.gray("本地安装")}`, value: "windows-local" },
|
|
4611
|
-
{ name: `${chalk.green("macOS")} ${chalk.gray("本地安装")}`, value: "mac-local" },
|
|
4612
|
-
{ name: `${chalk.green("Linux")} ${chalk.gray("本地安装")}`, value: "linux-local" }
|
|
4406
|
+
JSEncryptRSAKey2.prototype.getPrivateBaseKey = function() {
|
|
4407
|
+
var options = {
|
|
4408
|
+
array: [
|
|
4409
|
+
new KJUR.asn1.DERInteger({ int: 0 }),
|
|
4410
|
+
new KJUR.asn1.DERInteger({ bigint: this.n }),
|
|
4411
|
+
new KJUR.asn1.DERInteger({ int: this.e }),
|
|
4412
|
+
new KJUR.asn1.DERInteger({ bigint: this.d }),
|
|
4413
|
+
new KJUR.asn1.DERInteger({ bigint: this.p }),
|
|
4414
|
+
new KJUR.asn1.DERInteger({ bigint: this.q }),
|
|
4415
|
+
new KJUR.asn1.DERInteger({ bigint: this.dmp1 }),
|
|
4416
|
+
new KJUR.asn1.DERInteger({ bigint: this.dmq1 }),
|
|
4417
|
+
new KJUR.asn1.DERInteger({ bigint: this.coeff })
|
|
4418
|
+
]
|
|
4419
|
+
};
|
|
4420
|
+
var seq = new KJUR.asn1.DERSequence(options);
|
|
4421
|
+
return seq.getEncodedHex();
|
|
4422
|
+
};
|
|
4423
|
+
JSEncryptRSAKey2.prototype.getPrivateBaseKeyB64 = function() {
|
|
4424
|
+
return hex2b64(this.getPrivateBaseKey());
|
|
4425
|
+
};
|
|
4426
|
+
JSEncryptRSAKey2.prototype.getPublicBaseKey = function() {
|
|
4427
|
+
var first_sequence = new KJUR.asn1.DERSequence({
|
|
4428
|
+
array: [
|
|
4429
|
+
new KJUR.asn1.DERObjectIdentifier({ oid: "1.2.840.113549.1.1.1" }),
|
|
4430
|
+
// RSA Encryption pkcs #1 oid
|
|
4431
|
+
new KJUR.asn1.DERNull()
|
|
4613
4432
|
]
|
|
4614
4433
|
});
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
debugLog("[初始化] 需要选择环境");
|
|
4620
|
-
questions.push({
|
|
4621
|
-
type: "list",
|
|
4622
|
-
name: "env",
|
|
4623
|
-
message: `${nodeEmoji.get("globe_with_meridians")} 请选择环境:`,
|
|
4624
|
-
default: "test",
|
|
4625
|
-
choices: [
|
|
4626
|
-
{ name: `${chalk.green("测试环境")} ${chalk.gray("(test)")}`, value: "test" },
|
|
4627
|
-
{ name: `${chalk.red("正式环境")} ${chalk.gray("(prod)")}`, value: "prod" }
|
|
4434
|
+
var second_sequence = new KJUR.asn1.DERSequence({
|
|
4435
|
+
array: [
|
|
4436
|
+
new KJUR.asn1.DERInteger({ bigint: this.n }),
|
|
4437
|
+
new KJUR.asn1.DERInteger({ int: this.e })
|
|
4628
4438
|
]
|
|
4629
4439
|
});
|
|
4630
|
-
|
|
4631
|
-
|
|
4440
|
+
var bit_string = new KJUR.asn1.DERBitString({
|
|
4441
|
+
hex: "00" + second_sequence.getEncodedHex()
|
|
4442
|
+
});
|
|
4443
|
+
var seq = new KJUR.asn1.DERSequence({
|
|
4444
|
+
array: [first_sequence, bit_string]
|
|
4445
|
+
});
|
|
4446
|
+
return seq.getEncodedHex();
|
|
4447
|
+
};
|
|
4448
|
+
JSEncryptRSAKey2.prototype.getPublicBaseKeyB64 = function() {
|
|
4449
|
+
return hex2b64(this.getPublicBaseKey());
|
|
4450
|
+
};
|
|
4451
|
+
JSEncryptRSAKey2.wordwrap = function(str, width) {
|
|
4452
|
+
width = width || 64;
|
|
4453
|
+
if (!str) {
|
|
4454
|
+
return str;
|
|
4455
|
+
}
|
|
4456
|
+
var regex = "(.{1," + width + "})( +|$\n?)|(.{1," + width + "})";
|
|
4457
|
+
return str.match(RegExp(regex, "g")).join("\n");
|
|
4458
|
+
};
|
|
4459
|
+
JSEncryptRSAKey2.prototype.getPrivateKey = function() {
|
|
4460
|
+
var key = "-----BEGIN RSA PRIVATE KEY-----\n";
|
|
4461
|
+
key += JSEncryptRSAKey2.wordwrap(this.getPrivateBaseKeyB64()) + "\n";
|
|
4462
|
+
key += "-----END RSA PRIVATE KEY-----";
|
|
4463
|
+
return key;
|
|
4464
|
+
};
|
|
4465
|
+
JSEncryptRSAKey2.prototype.getPublicKey = function() {
|
|
4466
|
+
var key = "-----BEGIN PUBLIC KEY-----\n";
|
|
4467
|
+
key += JSEncryptRSAKey2.wordwrap(this.getPublicBaseKeyB64()) + "\n";
|
|
4468
|
+
key += "-----END PUBLIC KEY-----";
|
|
4469
|
+
return key;
|
|
4470
|
+
};
|
|
4471
|
+
JSEncryptRSAKey2.hasPublicKeyProperty = function(obj) {
|
|
4472
|
+
obj = obj || {};
|
|
4473
|
+
return obj.hasOwnProperty("n") && obj.hasOwnProperty("e");
|
|
4474
|
+
};
|
|
4475
|
+
JSEncryptRSAKey2.hasPrivateKeyProperty = function(obj) {
|
|
4476
|
+
obj = obj || {};
|
|
4477
|
+
return obj.hasOwnProperty("n") && obj.hasOwnProperty("e") && obj.hasOwnProperty("d") && obj.hasOwnProperty("p") && obj.hasOwnProperty("q") && obj.hasOwnProperty("dmp1") && obj.hasOwnProperty("dmq1") && obj.hasOwnProperty("coeff");
|
|
4478
|
+
};
|
|
4479
|
+
JSEncryptRSAKey2.prototype.parsePropertiesFrom = function(obj) {
|
|
4480
|
+
this.n = obj.n;
|
|
4481
|
+
this.e = obj.e;
|
|
4482
|
+
if (obj.hasOwnProperty("d")) {
|
|
4483
|
+
this.d = obj.d;
|
|
4484
|
+
this.p = obj.p;
|
|
4485
|
+
this.q = obj.q;
|
|
4486
|
+
this.dmp1 = obj.dmp1;
|
|
4487
|
+
this.dmq1 = obj.dmq1;
|
|
4488
|
+
this.coeff = obj.coeff;
|
|
4489
|
+
}
|
|
4490
|
+
};
|
|
4491
|
+
return JSEncryptRSAKey2;
|
|
4492
|
+
}(RSAKey)
|
|
4493
|
+
);
|
|
4494
|
+
var _a;
|
|
4495
|
+
var version = typeof process !== "undefined" ? (_a = process.env) === null || _a === void 0 ? void 0 : _a.npm_package_version : void 0;
|
|
4496
|
+
var JSEncrypt = (
|
|
4497
|
+
/** @class */
|
|
4498
|
+
function() {
|
|
4499
|
+
function JSEncrypt2(options) {
|
|
4500
|
+
if (options === void 0) {
|
|
4501
|
+
options = {};
|
|
4502
|
+
}
|
|
4503
|
+
this.default_key_size = options.default_key_size ? parseInt(options.default_key_size, 10) : 1024;
|
|
4504
|
+
this.default_public_exponent = options.default_public_exponent || "010001";
|
|
4505
|
+
this.log = options.log || false;
|
|
4506
|
+
this.key = options.key || null;
|
|
4632
4507
|
}
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
name: "phone",
|
|
4638
|
-
message: `${nodeEmoji.get("phone")} 请输入手机号码:`,
|
|
4639
|
-
validate: (value) => {
|
|
4640
|
-
if (!value || value.trim() === "") {
|
|
4641
|
-
return `${nodeEmoji.get("x")} 手机号码不能为空`;
|
|
4642
|
-
}
|
|
4643
|
-
if (!/^1[3-9]\d{9}$/.test(value)) {
|
|
4644
|
-
return `${nodeEmoji.get("warning")} 请输入正确的手机号码`;
|
|
4645
|
-
}
|
|
4646
|
-
return true;
|
|
4508
|
+
JSEncrypt2.prototype.setKey = function(key) {
|
|
4509
|
+
if (key) {
|
|
4510
|
+
if (this.log && this.key) {
|
|
4511
|
+
console.warn("A key was already set, overriding existing.");
|
|
4647
4512
|
}
|
|
4513
|
+
this.key = new JSEncryptRSAKey(key);
|
|
4514
|
+
} else if (!this.key && this.log) {
|
|
4515
|
+
console.error("A key was not set.");
|
|
4516
|
+
}
|
|
4517
|
+
};
|
|
4518
|
+
JSEncrypt2.prototype.setPrivateKey = function(privkey) {
|
|
4519
|
+
this.setKey(privkey);
|
|
4520
|
+
};
|
|
4521
|
+
JSEncrypt2.prototype.setPublicKey = function(pubkey) {
|
|
4522
|
+
this.setKey(pubkey);
|
|
4523
|
+
};
|
|
4524
|
+
JSEncrypt2.prototype.decrypt = function(str) {
|
|
4525
|
+
try {
|
|
4526
|
+
return this.getKey().decrypt(b64tohex(str));
|
|
4527
|
+
} catch (ex) {
|
|
4528
|
+
return false;
|
|
4529
|
+
}
|
|
4530
|
+
};
|
|
4531
|
+
JSEncrypt2.prototype.encrypt = function(str) {
|
|
4532
|
+
try {
|
|
4533
|
+
return hex2b64(this.getKey().encrypt(str));
|
|
4534
|
+
} catch (ex) {
|
|
4535
|
+
return false;
|
|
4536
|
+
}
|
|
4537
|
+
};
|
|
4538
|
+
JSEncrypt2.prototype.encryptOAEP = function(str) {
|
|
4539
|
+
try {
|
|
4540
|
+
return hex2b64(this.getKey().encrypt(str, oaep_pad));
|
|
4541
|
+
} catch (ex) {
|
|
4542
|
+
return false;
|
|
4543
|
+
}
|
|
4544
|
+
};
|
|
4545
|
+
JSEncrypt2.prototype.sign = function(str, digestMethod, digestName) {
|
|
4546
|
+
if (digestMethod === void 0) {
|
|
4547
|
+
digestMethod = function(raw) {
|
|
4548
|
+
return raw;
|
|
4549
|
+
};
|
|
4550
|
+
}
|
|
4551
|
+
if (digestName === void 0) {
|
|
4552
|
+
digestName = "";
|
|
4553
|
+
}
|
|
4554
|
+
try {
|
|
4555
|
+
return hex2b64(this.getKey().sign(str, digestMethod, digestName));
|
|
4556
|
+
} catch (ex) {
|
|
4557
|
+
return false;
|
|
4558
|
+
}
|
|
4559
|
+
};
|
|
4560
|
+
JSEncrypt2.prototype.signSha256 = function(str) {
|
|
4561
|
+
return this.sign(str, function(text) {
|
|
4562
|
+
return rstr2hex(rstr_sha256(text));
|
|
4563
|
+
}, "sha256");
|
|
4564
|
+
};
|
|
4565
|
+
JSEncrypt2.prototype.verify = function(str, signature, digestMethod) {
|
|
4566
|
+
if (digestMethod === void 0) {
|
|
4567
|
+
digestMethod = function(raw) {
|
|
4568
|
+
return raw;
|
|
4569
|
+
};
|
|
4570
|
+
}
|
|
4571
|
+
try {
|
|
4572
|
+
return this.getKey().verify(str, b64tohex(signature), digestMethod);
|
|
4573
|
+
} catch (ex) {
|
|
4574
|
+
return false;
|
|
4575
|
+
}
|
|
4576
|
+
};
|
|
4577
|
+
JSEncrypt2.prototype.verifySha256 = function(str, signature) {
|
|
4578
|
+
return this.verify(str, signature, function(text) {
|
|
4579
|
+
return rstr2hex(rstr_sha256(text));
|
|
4648
4580
|
});
|
|
4649
|
-
}
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
name: "userPass",
|
|
4657
|
-
message: `${nodeEmoji.get("key")} 请输入用户密码:`,
|
|
4658
|
-
validate: (value) => {
|
|
4659
|
-
if (!value || value.trim() === "") {
|
|
4660
|
-
return `${nodeEmoji.get("x")} 用户密码不能为空`;
|
|
4661
|
-
}
|
|
4662
|
-
return true;
|
|
4581
|
+
};
|
|
4582
|
+
JSEncrypt2.prototype.getKey = function(cb) {
|
|
4583
|
+
if (!this.key) {
|
|
4584
|
+
this.key = new JSEncryptRSAKey();
|
|
4585
|
+
if (cb && {}.toString.call(cb) === "[object Function]") {
|
|
4586
|
+
this.key.generateAsync(this.default_key_size, this.default_public_exponent, cb);
|
|
4587
|
+
return;
|
|
4663
4588
|
}
|
|
4664
|
-
|
|
4665
|
-
} else {
|
|
4666
|
-
debugLog("[初始化] 使用命令行参数: userPass");
|
|
4667
|
-
}
|
|
4668
|
-
if (questions.length > 0) {
|
|
4669
|
-
debugLog(`[初始化] 开始交互式问答,共 ${questions.length} 个问题`);
|
|
4670
|
-
const answers = await inquirer.prompt(questions);
|
|
4671
|
-
debugLog("[初始化] 交互式问答完成");
|
|
4672
|
-
scenario = scenario || answers.scenario;
|
|
4673
|
-
env = env || answers.env || "test";
|
|
4674
|
-
phone = phone || answers.phone;
|
|
4675
|
-
userPass = userPass || answers.userPass;
|
|
4676
|
-
}
|
|
4677
|
-
debugLog(`[初始化] 最终参数: scenario=${scenario}, env=${env}, phone=${phone}, pluginVersion=${options.pluginVersion}`);
|
|
4678
|
-
debugLog("[初始化] 创建 LocalInstaller 实例...");
|
|
4679
|
-
const installer = new LocalInstaller({
|
|
4680
|
-
phone,
|
|
4681
|
-
userPass,
|
|
4682
|
-
scenario,
|
|
4683
|
-
env,
|
|
4684
|
-
pluginVersion: options.pluginVersion
|
|
4685
|
-
});
|
|
4686
|
-
debugLog("[初始化] 开始安装...");
|
|
4687
|
-
await installer.install();
|
|
4688
|
-
debugLog("[初始化] 安装完成");
|
|
4689
|
-
console.log(installer.getPrefixText() + boxen(
|
|
4690
|
-
`${nodeEmoji.get("tada")} 插件初始化成功!`,
|
|
4691
|
-
{
|
|
4692
|
-
title: `${chalk.bold.green("初始化成功")}`,
|
|
4693
|
-
titleAlignment: "center",
|
|
4694
|
-
padding: { top: 1, bottom: 1, left: 5, right: 5 },
|
|
4695
|
-
margin: 1,
|
|
4696
|
-
borderStyle: "round",
|
|
4697
|
-
borderColor: "green",
|
|
4698
|
-
textAlignment: "center"
|
|
4699
|
-
}
|
|
4700
|
-
));
|
|
4701
|
-
} catch (error) {
|
|
4702
|
-
debugLog(`[初始化] 发生错误: ${error.message}`);
|
|
4703
|
-
console.error(boxen(
|
|
4704
|
-
`${chalk.yellow(error.message)}`,
|
|
4705
|
-
{
|
|
4706
|
-
title: `${chalk.bold.red("初始化失败")}`,
|
|
4707
|
-
titleAlignment: "center",
|
|
4708
|
-
padding: { top: 1, bottom: 1, left: 5, right: 5 },
|
|
4709
|
-
margin: 1,
|
|
4710
|
-
borderStyle: "round",
|
|
4711
|
-
borderColor: "red",
|
|
4712
|
-
textAlignment: "center"
|
|
4589
|
+
this.key.generate(this.default_key_size, this.default_public_exponent);
|
|
4713
4590
|
}
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
}
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4591
|
+
return this.key;
|
|
4592
|
+
};
|
|
4593
|
+
JSEncrypt2.prototype.getPrivateKey = function() {
|
|
4594
|
+
return this.getKey().getPrivateKey();
|
|
4595
|
+
};
|
|
4596
|
+
JSEncrypt2.prototype.getPrivateKeyB64 = function() {
|
|
4597
|
+
return this.getKey().getPrivateBaseKeyB64();
|
|
4598
|
+
};
|
|
4599
|
+
JSEncrypt2.prototype.getPublicKey = function() {
|
|
4600
|
+
return this.getKey().getPublicKey();
|
|
4601
|
+
};
|
|
4602
|
+
JSEncrypt2.prototype.getPublicKeyB64 = function() {
|
|
4603
|
+
return this.getKey().getPublicBaseKeyB64();
|
|
4604
|
+
};
|
|
4605
|
+
JSEncrypt2.version = version;
|
|
4606
|
+
return JSEncrypt2;
|
|
4607
|
+
}()
|
|
4608
|
+
);
|
|
4609
|
+
const PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBSYtNb6neLrrwsuPBsIFjpZBrffdkA8bpp2S35o2TCdhfdxS0nc4pkv9cJLkUvFa+gdQ5nLifnK9B1XoVbIQwY212QAftTDbl77bcHu7GAbv2TZr9pelSeUm1SrtMK5HDr/LzxTutGr4DovVHiDgEn45GQ1X5U+zC0Jp4Awn6ZwIDAQAB";
|
|
4610
|
+
function rsaEncrypt(txt) {
|
|
4611
|
+
const encrypt = new JSEncrypt();
|
|
4612
|
+
encrypt.setPublicKey(PUBLIC_KEY);
|
|
4613
|
+
const result = encrypt.encrypt(txt);
|
|
4614
|
+
return result || null;
|
|
4737
4615
|
}
|
|
4738
4616
|
function getHomeDir() {
|
|
4739
4617
|
return process$1.env.HOME || process$1.env.USERPROFILE || "";
|
|
4740
4618
|
}
|
|
4741
4619
|
const PLUGIN_PACKAGE_NAME = "@workclaw/openclaw-workclaw";
|
|
4620
|
+
function execAsync(command, options) {
|
|
4621
|
+
return new Promise((resolve2, reject) => {
|
|
4622
|
+
exec(command, { cwd: options.cwd, timeout: options.timeout }, (error, stdout, stderr) => {
|
|
4623
|
+
if (error) {
|
|
4624
|
+
reject(new Error(stderr || error.message));
|
|
4625
|
+
} else {
|
|
4626
|
+
resolve2(stdout);
|
|
4627
|
+
}
|
|
4628
|
+
});
|
|
4629
|
+
});
|
|
4630
|
+
}
|
|
4742
4631
|
function deepMerge(target, source) {
|
|
4743
4632
|
const result = { ...target };
|
|
4744
4633
|
for (const key in source) {
|
|
@@ -4752,194 +4641,132 @@ function deepMerge(target, source) {
|
|
|
4752
4641
|
}
|
|
4753
4642
|
return result;
|
|
4754
4643
|
}
|
|
4755
|
-
class
|
|
4644
|
+
class LocalInstaller {
|
|
4756
4645
|
constructor(config) {
|
|
4757
4646
|
this.config = config;
|
|
4758
4647
|
this.spinner = ora({ color: "cyan" }).start();
|
|
4759
4648
|
}
|
|
4760
4649
|
spinner;
|
|
4761
4650
|
prefixText = "";
|
|
4762
|
-
getPackageName() {
|
|
4763
|
-
if (this.config.pluginVersion) {
|
|
4764
|
-
return `${PLUGIN_PACKAGE_NAME}@${this.config.pluginVersion}`;
|
|
4765
|
-
}
|
|
4766
|
-
return PLUGIN_PACKAGE_NAME;
|
|
4767
|
-
}
|
|
4768
4651
|
validateConfig() {
|
|
4769
|
-
debugLog("[验证配置]
|
|
4770
|
-
if (!this.config.
|
|
4771
|
-
throw new AppError2(ERROR_CODES.
|
|
4652
|
+
debugLog("[验证配置] 检查手机号码和密码...");
|
|
4653
|
+
if (!this.config.phone) {
|
|
4654
|
+
throw new AppError2(ERROR_CODES.PHONE_REQUIRED, "手机号码不能为空,请使用 --phone 参数");
|
|
4772
4655
|
}
|
|
4773
|
-
if (!this.config.
|
|
4774
|
-
throw new AppError2(ERROR_CODES.
|
|
4656
|
+
if (!this.config.userPass) {
|
|
4657
|
+
throw new AppError2(ERROR_CODES.USER_PASS_REQUIRED, "用户密码不能为空,请使用 --user-pass 参数");
|
|
4775
4658
|
}
|
|
4776
|
-
debugLog("[验证配置]
|
|
4777
|
-
}
|
|
4778
|
-
getPaths() {
|
|
4779
|
-
const home = getHomeDir();
|
|
4780
|
-
const openclawDir = path.join(home, ".openclaw");
|
|
4781
|
-
const extensionsDir = path.join(openclawDir, "extensions");
|
|
4782
|
-
const targetDir = path.join(extensionsDir, "openclaw-workclaw");
|
|
4783
|
-
const configFile = path.join(openclawDir, "openclaw.json");
|
|
4784
|
-
const workspaceDir = path.join(openclawDir, "workspace");
|
|
4785
|
-
const tempDir = path.join(openclawDir, ".temp");
|
|
4786
|
-
return {
|
|
4787
|
-
home,
|
|
4788
|
-
extensions: extensionsDir,
|
|
4789
|
-
target: targetDir,
|
|
4790
|
-
config: configFile,
|
|
4791
|
-
workspace: workspaceDir,
|
|
4792
|
-
temp: tempDir
|
|
4793
|
-
};
|
|
4794
|
-
}
|
|
4795
|
-
updateSpinner(text) {
|
|
4796
|
-
this.spinner.prefixText = this.prefixText;
|
|
4797
|
-
this.spinner.text = `${chalk.cyan("安装进度")} ${chalk.dim("→")} ${chalk.yellow(text)}`;
|
|
4798
|
-
debugLog(`[Spinner] ${text}`);
|
|
4799
|
-
}
|
|
4800
|
-
getPrefixText() {
|
|
4801
|
-
return this.prefixText;
|
|
4659
|
+
debugLog("[验证配置] 配置验证通过");
|
|
4802
4660
|
}
|
|
4803
4661
|
async install() {
|
|
4804
4662
|
try {
|
|
4805
|
-
debugLog("[
|
|
4663
|
+
debugLog("[安装开始]");
|
|
4806
4664
|
this.validateConfig();
|
|
4807
|
-
this.
|
|
4808
|
-
const
|
|
4809
|
-
|
|
4810
|
-
|
|
4665
|
+
const env = this.config.env || "test";
|
|
4666
|
+
const config = getConfig(env);
|
|
4667
|
+
const homeDir = getHomeDir();
|
|
4668
|
+
const paths = {
|
|
4669
|
+
home: path.join(homeDir, config.DIRS.OPENCLAW),
|
|
4670
|
+
extensions: path.join(homeDir, config.DIRS.OPENCLAW, config.DIRS.EXTENSIONS),
|
|
4671
|
+
target: path.join(homeDir, config.DIRS.OPENCLAW, config.DIRS.EXTENSIONS, config.PLUGIN_NAME),
|
|
4672
|
+
config: path.join(homeDir, config.DIRS.OPENCLAW, config.DIRS.CONFIG_FILE),
|
|
4673
|
+
workspace: path.join(homeDir, config.DIRS.OPENCLAW, config.DIRS.WORKSPACE),
|
|
4674
|
+
temp: path.join(homeDir, config.DIRS.OPENCLAW, config.DIRS.TEMP)
|
|
4675
|
+
};
|
|
4676
|
+
debugLog(`[路径配置] home=${paths.home}`);
|
|
4677
|
+
debugLog(`[路径配置] extensions=${paths.extensions}`);
|
|
4678
|
+
debugLog(`[路径配置] target=${paths.target}`);
|
|
4679
|
+
debugLog(`[路径配置] config=${paths.config}`);
|
|
4680
|
+
debugLog(`[路径配置] workspace=${paths.workspace}`);
|
|
4681
|
+
const token = await this.doLogin(env);
|
|
4682
|
+
const boundConfig = await this.doFetchBoundConfig(env, token);
|
|
4683
|
+
await this.doCleanOldFiles(paths.target);
|
|
4811
4684
|
await this.doDownloadFromNpm(paths);
|
|
4812
|
-
this.
|
|
4813
|
-
await this.doUpdateConfig(paths);
|
|
4814
|
-
this.updateSpinner("更新配置完成");
|
|
4685
|
+
await this.doUpdateConfig(paths, boundConfig, env);
|
|
4815
4686
|
this.spinner.stop();
|
|
4816
|
-
debugLog("[盒子安装] 安装完成");
|
|
4817
4687
|
} catch (error) {
|
|
4818
4688
|
this.spinner.stop();
|
|
4819
|
-
debugLog(`[盒子安装] 安装失败: ${error.message}`);
|
|
4820
4689
|
throw error;
|
|
4821
4690
|
}
|
|
4822
4691
|
}
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4692
|
+
getPrefixText() {
|
|
4693
|
+
return this.prefixText;
|
|
4694
|
+
}
|
|
4695
|
+
async doLogin(env) {
|
|
4696
|
+
this.spinner.prefixText = this.prefixText;
|
|
4697
|
+
this.spinner.text = chalk.cyan("正在验证账号...");
|
|
4698
|
+
debugLog(`[用户登录] 手机号: ${this.config.phone}`);
|
|
4699
|
+
debugLog("[用户登录] RSA 加密密码...");
|
|
4700
|
+
const encryptedPassword = rsaEncrypt(this.config.userPass);
|
|
4701
|
+
if (!encryptedPassword) {
|
|
4702
|
+
throw new AppError2(ERROR_CODES.LOGIN_FAILED, "密码加密失败");
|
|
4703
|
+
}
|
|
4704
|
+
debugLog("[用户登录] 密码加密成功");
|
|
4705
|
+
debugLog("[用户登录] 调用登录接口...");
|
|
4706
|
+
const token = await login(this.config.phone, encryptedPassword, env);
|
|
4707
|
+
this.prefixText += chalk.green(` ✓ 账号验证成功
|
|
4708
|
+
`);
|
|
4709
|
+
debugLog("[用户登录] 登录成功");
|
|
4710
|
+
return token;
|
|
4711
|
+
}
|
|
4712
|
+
async doFetchBoundConfig(env, token) {
|
|
4713
|
+
this.spinner.prefixText = this.prefixText;
|
|
4714
|
+
this.spinner.text = chalk.cyan("正在获取绑定信息...");
|
|
4715
|
+
debugLog("[获取配置] 调用绑定配置接口...");
|
|
4716
|
+
const boundConfig = await fetchBoundConfig(token, this.config.phone, env);
|
|
4717
|
+
debugLog(`[获取配置] agentId=${boundConfig.agentId}, appKey=${boundConfig.appKey?.slice(0, 8)}...`);
|
|
4718
|
+
this.prefixText += chalk.green(` ✓ 绑定信息获取成功
|
|
4826
4719
|
`);
|
|
4720
|
+
debugLog("[获取配置] 获取成功");
|
|
4721
|
+
return boundConfig;
|
|
4722
|
+
}
|
|
4723
|
+
async doCleanOldFiles(targetPath) {
|
|
4724
|
+
this.spinner.prefixText = this.prefixText;
|
|
4725
|
+
this.spinner.text = chalk.cyan("正在检查已安装版本...");
|
|
4726
|
+
debugLog(`[清理旧版本] 检查目录: ${targetPath}`);
|
|
4827
4727
|
try {
|
|
4828
|
-
await fs.access(
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4728
|
+
await fs.access(targetPath);
|
|
4729
|
+
this.spinner.text = chalk.cyan("正在清理旧文件...");
|
|
4730
|
+
debugLog("[清理旧版本] 发现旧版本,开始清理...");
|
|
4731
|
+
await fs.rm(targetPath, { recursive: true, force: true });
|
|
4732
|
+
this.prefixText += chalk.green(` ✓ 旧版本清理完成
|
|
4832
4733
|
`);
|
|
4833
|
-
debugLog("[清理旧版本]
|
|
4734
|
+
debugLog("[清理旧版本] 清理完成");
|
|
4834
4735
|
} catch {
|
|
4835
|
-
|
|
4836
|
-
this.prefixText += chalk.green(`✓ 无旧版本需要清理
|
|
4736
|
+
this.prefixText += chalk.green(` ✓ 无旧版本需要清理
|
|
4837
4737
|
`);
|
|
4838
|
-
|
|
4839
|
-
try {
|
|
4840
|
-
await fs.access(paths.temp);
|
|
4841
|
-
await fs.rm(paths.temp, { recursive: true, force: true });
|
|
4842
|
-
} catch {
|
|
4843
|
-
debugLog("[清理旧版本] 无临时目录需要清理");
|
|
4738
|
+
debugLog("[清理旧版本] 未发现旧版本");
|
|
4844
4739
|
}
|
|
4845
4740
|
}
|
|
4846
4741
|
async doDownloadFromNpm(paths) {
|
|
4847
|
-
|
|
4848
|
-
this.
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
for (let i = 1; i <= maxRetries; i++) {
|
|
4854
|
-
debugLog(`[下载插件] 第 ${i} 次尝试下载 tarball...`);
|
|
4855
|
-
try {
|
|
4856
|
-
const packageName = this.getPackageName();
|
|
4857
|
-
debugLog(`[下载插件] 下载包名: ${packageName}`);
|
|
4858
|
-
const { execSync: execSync2 } = await import("node:child_process");
|
|
4859
|
-
const output = execSync2(
|
|
4860
|
-
`npm pack ${packageName} --registry=https://mirrors.tencent.com/npm/ --ignore-scripts`,
|
|
4861
|
-
{ cwd: paths.temp, encoding: "utf-8", timeout: 6e4 }
|
|
4862
|
-
);
|
|
4863
|
-
const filename = output.trim().split("\n").pop() || "";
|
|
4864
|
-
tarballPath = path.join(paths.temp, filename);
|
|
4865
|
-
debugLog(`[下载插件] tarball 下载成功: ${tarballPath}`);
|
|
4866
|
-
break;
|
|
4867
|
-
} catch (error) {
|
|
4868
|
-
lastError = error.stderr?.toString() || error.message || "未知错误";
|
|
4869
|
-
debugLog(`[下载插件] 第 ${i} 次尝试失败: ${lastError}`);
|
|
4870
|
-
if (i < maxRetries) {
|
|
4871
|
-
debugLog("[下载插件] 等待 3 秒后重试...");
|
|
4872
|
-
await new Promise((resolve2) => setTimeout(resolve2, 3e3));
|
|
4873
|
-
}
|
|
4874
|
-
}
|
|
4875
|
-
}
|
|
4876
|
-
if (!tarballPath) {
|
|
4877
|
-
this.prefixText += chalk.red(`✗ 下载失败
|
|
4878
|
-
`);
|
|
4879
|
-
throw new AppError2(ERROR_CODES.NPM_INSTALL_FAILED, `插件下载失败: ${lastError}`);
|
|
4880
|
-
}
|
|
4881
|
-
this.prefixText += chalk.green(`✓ 插件下载成功
|
|
4882
|
-
`);
|
|
4883
|
-
await this.extractTarball(tarballPath, paths);
|
|
4884
|
-
}
|
|
4885
|
-
async extractTarball(tarballPath, paths) {
|
|
4886
|
-
debugLog("[解压插件] 开始解压 tarball...");
|
|
4742
|
+
this.spinner.prefixText = this.prefixText;
|
|
4743
|
+
this.spinner.text = chalk.cyan("正在安装插件...");
|
|
4744
|
+
debugLog("[安装插件] 创建扩展目录...");
|
|
4745
|
+
await fs.mkdir(paths.extensions, { recursive: true });
|
|
4746
|
+
debugLog(`[安装插件] 扩展目录: ${paths.extensions}`);
|
|
4747
|
+
debugLog("[安装插件] 执行 openclaw plugins install 命令");
|
|
4887
4748
|
try {
|
|
4888
|
-
await
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
const stat = await fs.stat(packageDir);
|
|
4895
|
-
if (stat.isDirectory()) {
|
|
4896
|
-
await fs.mkdir(paths.extensions, { recursive: true });
|
|
4897
|
-
await fs.cp(packageDir, paths.target, { recursive: true });
|
|
4898
|
-
debugLog(`[解压插件] 插件解压成功: ${paths.target}`);
|
|
4899
|
-
this.prefixText += chalk.green(`✓ 插件解压成功
|
|
4900
|
-
`);
|
|
4901
|
-
this.spinner.prefixText = this.prefixText;
|
|
4902
|
-
this.spinner.text = `${chalk.cyan("安装依赖")} ${chalk.dim("→")} ${chalk.yellow("正在安装...")}`;
|
|
4903
|
-
debugLog("[安装依赖] 执行 npm install 安装生产环境依赖");
|
|
4904
|
-
try {
|
|
4905
|
-
execSync("npm install --omit=dev --ignore-scripts", {
|
|
4906
|
-
cwd: paths.target,
|
|
4907
|
-
stdio: "pipe",
|
|
4908
|
-
timeout: 12e4
|
|
4909
|
-
});
|
|
4910
|
-
debugLog("[安装依赖] npm install 执行成功");
|
|
4911
|
-
this.prefixText += chalk.green(`✓ 依赖安装成功
|
|
4912
|
-
`);
|
|
4913
|
-
} catch (error) {
|
|
4914
|
-
const stderr = error.stderr?.toString() || "";
|
|
4915
|
-
const stdout = error.stdout?.toString() || "";
|
|
4916
|
-
const combinedOutput = stderr + stdout;
|
|
4917
|
-
if (combinedOutput.includes("npm warn") || combinedOutput.includes("deprecated")) {
|
|
4918
|
-
debugLog("[安装依赖] npm install 有警告但可能成功,继续流程");
|
|
4919
|
-
this.prefixText += chalk.green(`✓ 依赖安装完成
|
|
4920
|
-
`);
|
|
4921
|
-
} else {
|
|
4922
|
-
debugLog(`[安装依赖] npm install 失败: ${combinedOutput}`);
|
|
4923
|
-
}
|
|
4924
|
-
}
|
|
4925
|
-
await fs.rm(paths.temp, { recursive: true, force: true });
|
|
4926
|
-
debugLog(`[解压插件] 清理临时文件成功`);
|
|
4927
|
-
this.prefixText += chalk.green(`✓ 清理临时文件成功
|
|
4749
|
+
await execAsync(
|
|
4750
|
+
`openclaw plugins install ${PLUGIN_PACKAGE_NAME} --dangerously-force-unsafe-install`,
|
|
4751
|
+
{ timeout: 12e4 }
|
|
4752
|
+
);
|
|
4753
|
+
debugLog("[安装插件] openclaw plugins install 执行成功");
|
|
4754
|
+
this.prefixText += chalk.green(` ✓ 插件安装完成
|
|
4928
4755
|
`);
|
|
4929
|
-
} else {
|
|
4930
|
-
throw new AppError2(ERROR_CODES.PLUGIN_EXTRACT_FAILED, "解压失败:package 目录不存在");
|
|
4931
|
-
}
|
|
4932
4756
|
} catch (error) {
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
`);
|
|
4936
|
-
throw new AppError2(ERROR_CODES.NPM_INSTALL_FAILED, `插件解压失败: ${error.message}`);
|
|
4757
|
+
const errorMsg = error.message || "未知错误";
|
|
4758
|
+
debugLog(`[安装插件] 安装失败: ${errorMsg}`);
|
|
4759
|
+
throw new AppError2(ERROR_CODES.NPM_INSTALL_FAILED, `插件安装失败: ${errorMsg}`);
|
|
4937
4760
|
}
|
|
4938
4761
|
}
|
|
4939
|
-
async doUpdateConfig(paths) {
|
|
4940
|
-
|
|
4941
|
-
this.
|
|
4942
|
-
|
|
4762
|
+
async doUpdateConfig(paths, boundConfig, env) {
|
|
4763
|
+
this.spinner.prefixText = this.prefixText;
|
|
4764
|
+
this.spinner.text = chalk.cyan("正在生成配置...");
|
|
4765
|
+
debugLog("[更新配置] 创建目录...");
|
|
4766
|
+
await fs.mkdir(paths.home, { recursive: true });
|
|
4767
|
+
await fs.mkdir(paths.workspace, { recursive: true });
|
|
4768
|
+
debugLog("[更新配置] 目录创建完成");
|
|
4769
|
+
debugLog("[更新配置] 读取原有配置...");
|
|
4943
4770
|
let originalConfig = {};
|
|
4944
4771
|
try {
|
|
4945
4772
|
const content = await fs.readFile(paths.config, "utf-8");
|
|
@@ -4948,48 +4775,33 @@ class BoxInstaller {
|
|
|
4948
4775
|
} catch {
|
|
4949
4776
|
debugLog("[更新配置] 无原有配置");
|
|
4950
4777
|
}
|
|
4951
|
-
const config = getConfig(
|
|
4778
|
+
const config = getConfig(env);
|
|
4952
4779
|
const newConfig = {
|
|
4953
4780
|
// diagnostics: 诊断配置
|
|
4954
4781
|
diagnostics: {
|
|
4955
|
-
// 启用诊断功能
|
|
4956
4782
|
enabled: true,
|
|
4957
|
-
// 启用所有诊断标志 ['*'] 表示全部,[] 表示禁用所有
|
|
4958
4783
|
flags: ["*"]
|
|
4959
4784
|
},
|
|
4960
4785
|
// browser: 浏览器配置
|
|
4961
4786
|
browser: {
|
|
4962
|
-
// 禁用浏览器工具
|
|
4963
4787
|
enabled: false
|
|
4964
4788
|
},
|
|
4965
4789
|
// models: 模型配置
|
|
4966
4790
|
models: {
|
|
4967
|
-
// 配置合并模式:'merge' 合并 | 'replace' 替换
|
|
4968
4791
|
mode: "merge",
|
|
4969
4792
|
providers: {
|
|
4970
4793
|
"siliconflow-minimax": {
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
// API 密钥(留空,由外部提供)
|
|
4974
|
-
apiKey: "",
|
|
4975
|
-
// API 类型:'openai-completions' | 'openai-chat' 等
|
|
4794
|
+
baseUrl: boundConfig.modelApiBaseUrl || config.MODEL_BASE_URL,
|
|
4795
|
+
apiKey: boundConfig.modelApiKey,
|
|
4976
4796
|
api: "openai-completions",
|
|
4977
|
-
// 是否使用 Authorization header 认证
|
|
4978
4797
|
authHeader: true,
|
|
4979
4798
|
models: [{
|
|
4980
|
-
// 模型 ID(provider/model 格式)
|
|
4981
4799
|
id: "Pro/MiniMaxAI/MiniMax-M2.5",
|
|
4982
|
-
// 模型显示名称
|
|
4983
4800
|
name: "MiniMax-M2.5",
|
|
4984
|
-
// 是否启用推理能力
|
|
4985
4801
|
reasoning: false,
|
|
4986
|
-
// 支持的输入类型:['text'] | ['text', 'image']
|
|
4987
4802
|
input: ["text"],
|
|
4988
|
-
// 价格(0 表示免费或未设置)
|
|
4989
4803
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
4990
|
-
// 上下文窗口大小(token)
|
|
4991
4804
|
contextWindow: 2e5,
|
|
4992
|
-
// 最大输出 token 数
|
|
4993
4805
|
maxTokens: 65536
|
|
4994
4806
|
}]
|
|
4995
4807
|
}
|
|
@@ -4998,82 +4810,56 @@ class BoxInstaller {
|
|
|
4998
4810
|
// agents: 代理配置
|
|
4999
4811
|
agents: {
|
|
5000
4812
|
defaults: {
|
|
5001
|
-
// 默认使用的模型
|
|
5002
4813
|
model: { primary: "siliconflow-minimax/Pro/MiniMaxAI/MiniMax-M2.5" },
|
|
5003
4814
|
models: {
|
|
5004
4815
|
"siliconflow-minimax/Pro/MiniMaxAI/MiniMax-M2.5": {
|
|
5005
|
-
// 模型别名,用于显示
|
|
5006
4816
|
alias: "Pro/MiniMaxAI/MiniMax-M2.5"
|
|
5007
4817
|
}
|
|
5008
4818
|
},
|
|
5009
|
-
// 工作区目录路径
|
|
5010
4819
|
workspace: paths.workspace,
|
|
5011
|
-
// 会话压缩模式:'safeguard' 保守模式
|
|
5012
4820
|
compaction: { mode: "safeguard" },
|
|
5013
|
-
// 详细程度:'full' | 'short' | 'off'
|
|
5014
4821
|
verboseDefault: "full",
|
|
5015
|
-
// 最大并发任务数
|
|
5016
4822
|
maxConcurrent: 4,
|
|
5017
|
-
// 子代理最大并发数
|
|
5018
4823
|
subagents: { maxConcurrent: 8 }
|
|
5019
4824
|
},
|
|
5020
|
-
// 代理列表
|
|
5021
4825
|
list: [{ id: "main", workspace: paths.workspace }]
|
|
5022
4826
|
},
|
|
5023
4827
|
// tools: 工具配置
|
|
5024
4828
|
tools: {
|
|
5025
|
-
// 禁用的工具列表(优先于 allow)
|
|
5026
4829
|
deny: ["image", "web_search", "web_fetch"],
|
|
5027
|
-
// 图像分析工具
|
|
5028
4830
|
media: { image: { enabled: false } },
|
|
5029
|
-
// 网络搜索和抓取工具
|
|
5030
4831
|
web: { search: { enabled: false }, fetch: { enabled: false } },
|
|
5031
|
-
// 提升权限工具(host=gateway)
|
|
5032
4832
|
elevated: { enabled: true, allowFrom: { webchat: ["*"] } },
|
|
5033
|
-
// exec 工具安全级别:'deny' | 'allowlist' | 'full'
|
|
5034
4833
|
exec: { security: "full" }
|
|
5035
4834
|
},
|
|
5036
4835
|
// bindings: 绑定配置
|
|
5037
4836
|
bindings: [{
|
|
5038
|
-
// 绑定的代理 ID
|
|
5039
4837
|
agentId: "main",
|
|
5040
|
-
// 匹配的通道和账户
|
|
5041
4838
|
match: { channel: "openclaw-workclaw", accountId: "default" }
|
|
5042
4839
|
}],
|
|
5043
4840
|
// messages: 消息配置
|
|
5044
4841
|
messages: {
|
|
5045
|
-
// 消息确认范围
|
|
5046
4842
|
ackReactionScope: "group-mentions"
|
|
5047
4843
|
},
|
|
5048
4844
|
// commands: 命令配置
|
|
5049
4845
|
commands: {
|
|
5050
|
-
// 本机命令:'auto' | 'on' | 'off'
|
|
5051
4846
|
native: "auto",
|
|
5052
|
-
// 本机技能:'auto' | 'on' | 'off'
|
|
5053
4847
|
nativeSkills: "auto",
|
|
5054
|
-
// 是否允许重启命令
|
|
5055
4848
|
restart: true,
|
|
5056
|
-
// 所有者显示格式:'raw' | 'name' | 'hidden'
|
|
5057
4849
|
ownerDisplay: "raw"
|
|
5058
4850
|
},
|
|
5059
4851
|
// session: 会话配置
|
|
5060
4852
|
session: {
|
|
5061
|
-
// DM 作用域
|
|
5062
4853
|
dmScope: "per-account-channel-peer"
|
|
5063
4854
|
},
|
|
5064
4855
|
// hooks: 钩子配置
|
|
5065
4856
|
hooks: {
|
|
5066
4857
|
internal: {
|
|
5067
|
-
// 启用内部钩子
|
|
5068
4858
|
enabled: true,
|
|
5069
4859
|
entries: {
|
|
5070
|
-
// 启动 Markdown 钩子
|
|
5071
4860
|
"boot-md": { enabled: true },
|
|
5072
|
-
// 引导额外文件钩子
|
|
5073
4861
|
"bootstrap-extra-files": { enabled: true },
|
|
5074
|
-
// 命令日志钩子
|
|
5075
4862
|
"command-logger": { enabled: true },
|
|
5076
|
-
// 会话记忆钩子
|
|
5077
4863
|
"session-memory": { enabled: true }
|
|
5078
4864
|
}
|
|
5079
4865
|
}
|
|
@@ -5081,119 +4867,82 @@ class BoxInstaller {
|
|
|
5081
4867
|
// channels: 通道配置
|
|
5082
4868
|
channels: {
|
|
5083
4869
|
"openclaw-workclaw": {
|
|
5084
|
-
// 启用通道
|
|
5085
4870
|
enabled: true,
|
|
5086
|
-
// 连接模式:'websocket' | 'http'
|
|
5087
4871
|
connectionMode: "websocket",
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
// 应用密钥
|
|
5091
|
-
appKey: this.config.appKey,
|
|
5092
|
-
// 应用密钥
|
|
5093
|
-
appSecret: this.config.appSecret,
|
|
5094
|
-
// API 基础 URL
|
|
4872
|
+
appKey: boundConfig.appKey,
|
|
4873
|
+
appSecret: boundConfig.appSecret,
|
|
5095
4874
|
baseUrl: this.config.baseUrl || config.DEFAULT_BASE_URL,
|
|
5096
|
-
// WebSocket URL
|
|
5097
4875
|
websocketUrl: this.config.wsUrl || config.DEFAULT_WS_URL,
|
|
5098
|
-
// 允许不安全的 TLS 连接
|
|
5099
4876
|
allowInsecureTls: true,
|
|
5100
|
-
// 允许原始 JSON 载荷
|
|
5101
4877
|
allowRawJsonPayload: true,
|
|
5102
|
-
|
|
5103
|
-
|
|
4878
|
+
userId: boundConfig.userId,
|
|
4879
|
+
dmPolicy: "open",
|
|
4880
|
+
allowFrom: ["*"],
|
|
5104
4881
|
accounts: {
|
|
5105
|
-
|
|
5106
|
-
default: { enabled: true, agentId: "" }
|
|
4882
|
+
default: { enabled: true, agentId: boundConfig.agentId }
|
|
5107
4883
|
}
|
|
5108
4884
|
}
|
|
5109
4885
|
},
|
|
5110
4886
|
// gateway: 网关配置
|
|
5111
4887
|
gateway: {
|
|
5112
|
-
// 网关模式:'local' | 'hosted'
|
|
5113
4888
|
mode: "local",
|
|
5114
|
-
// 网关端口
|
|
5115
4889
|
port: 18789,
|
|
5116
|
-
|
|
5117
|
-
bind: "loopback",
|
|
5118
|
-
// 认证模式(token字段未设置,是因为需要使用原始配置的token)
|
|
4890
|
+
bind: "lan",
|
|
5119
4891
|
auth: {
|
|
5120
4892
|
mode: "token"
|
|
5121
4893
|
},
|
|
5122
|
-
// Tailscale 配置
|
|
5123
4894
|
tailscale: { mode: "off", resetOnExit: false },
|
|
5124
4895
|
nodes: {
|
|
5125
|
-
// 节点上禁止的命令
|
|
5126
4896
|
denyCommands: [
|
|
5127
4897
|
"camera.snap",
|
|
5128
4898
|
"camera.clip",
|
|
5129
4899
|
"screen.record",
|
|
5130
4900
|
"contacts.add",
|
|
5131
4901
|
"calendar.add",
|
|
5132
|
-
"reminders.add"
|
|
5133
|
-
"sms.send",
|
|
5134
|
-
"sms.search"
|
|
4902
|
+
"reminders.add"
|
|
5135
4903
|
]
|
|
5136
4904
|
},
|
|
5137
4905
|
controlUi: {
|
|
5138
|
-
// 允许不安全认证
|
|
5139
4906
|
allowInsecureAuth: true,
|
|
5140
|
-
// 禁用设备认证(仅用于开发)
|
|
5141
4907
|
dangerouslyDisableDeviceAuth: true,
|
|
5142
|
-
// 允许 Host 头源回退
|
|
5143
4908
|
dangerouslyAllowHostHeaderOriginFallback: true,
|
|
5144
|
-
// 允许的源
|
|
5145
4909
|
allowedOrigins: ["http://localhost:18789", "http://127.0.0.1:18789"]
|
|
5146
4910
|
}
|
|
5147
4911
|
},
|
|
5148
4912
|
// skills: 技能配置
|
|
5149
4913
|
skills: {
|
|
5150
|
-
// 技能加载监视模式
|
|
5151
4914
|
load: { watch: true }
|
|
5152
4915
|
},
|
|
5153
4916
|
// logging: 日志配置
|
|
5154
4917
|
logging: {
|
|
5155
|
-
// 日志级别:'debug' | 'info' | 'warn' | 'error'
|
|
5156
4918
|
level: "info",
|
|
5157
|
-
// 控制台日志级别
|
|
5158
4919
|
consoleLevel: "info",
|
|
5159
|
-
// 控制台样式:'pretty' | 'basic' | 'raw'
|
|
5160
4920
|
consoleStyle: "pretty",
|
|
5161
|
-
// 敏感信息脱敏:'off' | 'keys' | 'all'
|
|
5162
4921
|
redactSensitive: "off",
|
|
5163
|
-
// 日志文件路径(空表示不写入文件)
|
|
5164
4922
|
file: "",
|
|
5165
|
-
// 脱敏模式(正则表达式)
|
|
5166
4923
|
redactPatterns: ["sk-.*"]
|
|
5167
4924
|
},
|
|
5168
4925
|
// plugins: 插件配置
|
|
5169
4926
|
plugins: {
|
|
5170
|
-
// 允许的插件列表
|
|
5171
4927
|
allow: [config.PLUGIN_NAME],
|
|
5172
|
-
// 插件安装跟踪(支持 openclaw plugins update 命令)
|
|
5173
4928
|
installs: {
|
|
5174
4929
|
[config.PLUGIN_NAME]: {
|
|
5175
|
-
// 安装来源
|
|
5176
4930
|
source: "npm",
|
|
5177
|
-
// npm 包名
|
|
5178
4931
|
spec: PLUGIN_PACKAGE_NAME,
|
|
5179
|
-
// 安装路径
|
|
5180
4932
|
installPath: paths.target
|
|
5181
4933
|
}
|
|
5182
4934
|
},
|
|
5183
|
-
// 插件加载路径
|
|
5184
|
-
load: {
|
|
5185
|
-
paths: [paths.target]
|
|
5186
|
-
},
|
|
5187
|
-
// 插件条目启用状态
|
|
5188
4935
|
entries: {
|
|
5189
4936
|
[config.PLUGIN_NAME]: { enabled: true }
|
|
5190
4937
|
}
|
|
5191
4938
|
}
|
|
5192
4939
|
};
|
|
5193
4940
|
const finalConfig = deepMerge(originalConfig, newConfig);
|
|
4941
|
+
this.spinner.prefixText = this.prefixText;
|
|
4942
|
+
this.spinner.text = chalk.cyan("正在写入配置...");
|
|
5194
4943
|
debugLog("[更新配置] 写入配置文件...");
|
|
5195
4944
|
await fs.writeFile(paths.config, JSON.stringify(finalConfig, null, 2), "utf-8");
|
|
5196
|
-
this.prefixText += chalk.green(
|
|
4945
|
+
this.prefixText += chalk.green(` ✓ 配置更新完成
|
|
5197
4946
|
`);
|
|
5198
4947
|
debugLog(`[更新配置] 配置文件写入成功: ${paths.config}`);
|
|
5199
4948
|
}
|
|
@@ -5215,84 +4964,107 @@ function checkEnv() {
|
|
|
5215
4964
|
throw new AppError2(ERROR_CODES.NPM_NOT_FOUND, "未检测到 npm,请先安装 Node.js 和 npm");
|
|
5216
4965
|
}
|
|
5217
4966
|
}
|
|
5218
|
-
async function
|
|
4967
|
+
async function createLocalCommand(options) {
|
|
5219
4968
|
setDebug(!!options.debug);
|
|
5220
|
-
debugLog("[
|
|
5221
|
-
debugLog(`[
|
|
4969
|
+
debugLog("[初始化] 开始处理...");
|
|
4970
|
+
debugLog(`[初始化] 参数: scenario=${options.scenario}, env=${options.env}, phone=${options.phone}, debug=${options.debug}`);
|
|
5222
4971
|
checkEnv();
|
|
5223
|
-
debugLog("[
|
|
4972
|
+
debugLog("[初始化] 环境检查通过");
|
|
5224
4973
|
try {
|
|
4974
|
+
let scenario = options.scenario;
|
|
5225
4975
|
let env = options.env;
|
|
5226
|
-
let
|
|
5227
|
-
let
|
|
4976
|
+
let phone = options.phone;
|
|
4977
|
+
let userPass = options.userPass;
|
|
5228
4978
|
const questions = [];
|
|
4979
|
+
if (!scenario) {
|
|
4980
|
+
debugLog("[初始化] 需要选择安装场景");
|
|
4981
|
+
questions.push({
|
|
4982
|
+
type: "list",
|
|
4983
|
+
name: "scenario",
|
|
4984
|
+
message: chalk.cyan("请选择安装场景:"),
|
|
4985
|
+
default: "windows-local",
|
|
4986
|
+
choices: [
|
|
4987
|
+
{ name: `${chalk.green("Windows")} ${chalk.dim("本地安装")}`, value: "windows-local" },
|
|
4988
|
+
{ name: `${chalk.green("macOS")} ${chalk.dim("本地安装")}`, value: "mac-local" },
|
|
4989
|
+
{ name: `${chalk.green("Linux")} ${chalk.dim("本地安装")}`, value: "linux-local" }
|
|
4990
|
+
]
|
|
4991
|
+
});
|
|
4992
|
+
} else {
|
|
4993
|
+
debugLog(`[初始化] 使用命令行参数: scenario=${scenario}`);
|
|
4994
|
+
}
|
|
5229
4995
|
if (!env) {
|
|
5230
|
-
debugLog("[
|
|
4996
|
+
debugLog("[初始化] 需要选择环境");
|
|
5231
4997
|
questions.push({
|
|
5232
4998
|
type: "list",
|
|
5233
4999
|
name: "env",
|
|
5234
|
-
message:
|
|
5000
|
+
message: chalk.cyan("请选择环境:"),
|
|
5235
5001
|
default: "test",
|
|
5236
5002
|
choices: [
|
|
5237
|
-
{ name: `${chalk.green("测试环境")} ${chalk.
|
|
5238
|
-
{ name: `${chalk.red("正式环境")} ${chalk.
|
|
5003
|
+
{ name: `${chalk.green("测试环境")} ${chalk.dim("(test)")}`, value: "test" },
|
|
5004
|
+
{ name: `${chalk.red("正式环境")} ${chalk.dim("(prod)")}`, value: "prod" }
|
|
5239
5005
|
]
|
|
5240
5006
|
});
|
|
5241
5007
|
} else {
|
|
5242
|
-
debugLog(`[
|
|
5008
|
+
debugLog(`[初始化] 使用命令行参数: env=${env}`);
|
|
5243
5009
|
}
|
|
5244
|
-
if (!
|
|
5245
|
-
debugLog("[
|
|
5010
|
+
if (!phone) {
|
|
5011
|
+
debugLog("[初始化] 需要输入手机号码");
|
|
5246
5012
|
questions.push({
|
|
5247
5013
|
type: "input",
|
|
5248
|
-
name: "
|
|
5249
|
-
message:
|
|
5014
|
+
name: "phone",
|
|
5015
|
+
message: chalk.cyan("请输入手机号码:"),
|
|
5250
5016
|
validate: (value) => {
|
|
5251
5017
|
if (!value || value.trim() === "") {
|
|
5252
|
-
return
|
|
5018
|
+
return chalk.red("手机号码不能为空");
|
|
5019
|
+
}
|
|
5020
|
+
if (!/^1[3-9]\d{9}$/.test(value)) {
|
|
5021
|
+
return chalk.yellow("请输入正确的手机号码");
|
|
5253
5022
|
}
|
|
5254
5023
|
return true;
|
|
5255
5024
|
}
|
|
5256
5025
|
});
|
|
5257
5026
|
} else {
|
|
5258
|
-
debugLog("[
|
|
5027
|
+
debugLog("[初始化] 使用命令行参数: phone");
|
|
5259
5028
|
}
|
|
5260
|
-
if (!
|
|
5261
|
-
debugLog("[
|
|
5029
|
+
if (!userPass) {
|
|
5030
|
+
debugLog("[初始化] 需要输入用户密码");
|
|
5262
5031
|
questions.push({
|
|
5263
5032
|
type: "input",
|
|
5264
|
-
name: "
|
|
5265
|
-
message:
|
|
5033
|
+
name: "userPass",
|
|
5034
|
+
message: chalk.cyan("请输入用户密码:"),
|
|
5266
5035
|
validate: (value) => {
|
|
5267
5036
|
if (!value || value.trim() === "") {
|
|
5268
|
-
return
|
|
5037
|
+
return chalk.red("用户密码不能为空");
|
|
5269
5038
|
}
|
|
5270
5039
|
return true;
|
|
5271
5040
|
}
|
|
5272
5041
|
});
|
|
5273
5042
|
} else {
|
|
5274
|
-
debugLog("[
|
|
5043
|
+
debugLog("[初始化] 使用命令行参数: userPass");
|
|
5275
5044
|
}
|
|
5276
5045
|
if (questions.length > 0) {
|
|
5277
|
-
debugLog(`[
|
|
5046
|
+
debugLog(`[初始化] 开始交互式问答,共 ${questions.length} 个问题`);
|
|
5278
5047
|
const answers = await inquirer.prompt(questions);
|
|
5279
|
-
debugLog("[
|
|
5048
|
+
debugLog("[初始化] 交互式问答完成");
|
|
5049
|
+
scenario = scenario || answers.scenario;
|
|
5280
5050
|
env = env || answers.env || "test";
|
|
5281
|
-
|
|
5282
|
-
|
|
5051
|
+
phone = phone || answers.phone;
|
|
5052
|
+
userPass = userPass || answers.userPass;
|
|
5283
5053
|
}
|
|
5284
|
-
debugLog(`[
|
|
5285
|
-
debugLog("[
|
|
5286
|
-
const installer = new
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5054
|
+
debugLog(`[初始化] 最终参数: scenario=${scenario}, env=${env}, phone=${phone}, pluginVersion=${options.pluginVersion}`);
|
|
5055
|
+
debugLog("[初始化] 创建 LocalInstaller 实例...");
|
|
5056
|
+
const installer = new LocalInstaller({
|
|
5057
|
+
phone,
|
|
5058
|
+
userPass,
|
|
5059
|
+
scenario,
|
|
5060
|
+
env,
|
|
5061
|
+
pluginVersion: options.pluginVersion
|
|
5290
5062
|
});
|
|
5291
|
-
debugLog("[
|
|
5063
|
+
debugLog("[初始化] 开始安装...");
|
|
5292
5064
|
await installer.install();
|
|
5293
|
-
debugLog("[
|
|
5065
|
+
debugLog("[初始化] 安装完成");
|
|
5294
5066
|
console.log(installer.getPrefixText() + boxen(
|
|
5295
|
-
`${
|
|
5067
|
+
`${chalk.green("✦")} 插件初始化成功!`,
|
|
5296
5068
|
{
|
|
5297
5069
|
title: `${chalk.bold.green("初始化成功")}`,
|
|
5298
5070
|
titleAlignment: "center",
|
|
@@ -5304,7 +5076,7 @@ async function createBoxCommand(options) {
|
|
|
5304
5076
|
}
|
|
5305
5077
|
));
|
|
5306
5078
|
} catch (error) {
|
|
5307
|
-
debugLog(`[
|
|
5079
|
+
debugLog(`[初始化] 发生错误: ${error.message}`);
|
|
5308
5080
|
console.error(boxen(
|
|
5309
5081
|
`${chalk.yellow(error.message)}`,
|
|
5310
5082
|
{
|
|
@@ -5321,7 +5093,7 @@ async function createBoxCommand(options) {
|
|
|
5321
5093
|
}
|
|
5322
5094
|
}
|
|
5323
5095
|
function registerCommands(program2) {
|
|
5324
|
-
program2.command("
|
|
5096
|
+
program2.command("local").description("本地账户安装(需要登录)").option("-s, --scenario <scenario>", "安装场景").option("-e, --env <env>", "环境 (test/prod)").option("--phone <phone>", "手机号码").option("--user-pass <userPass>", "用户密码").option("--plugin-version <plugin-version>", "插件版本号(默认最新版)").option("--debug", "开启调试日志").action(createLocalCommand);
|
|
5325
5097
|
}
|
|
5326
5098
|
const __filename$1 = fileURLToPath(import.meta.url);
|
|
5327
5099
|
const __dirname$1 = dirname(__filename$1);
|
|
@@ -5329,8 +5101,8 @@ const pkg = JSON.parse(readFileSync(resolve(__dirname$1, "../package.json"), "ut
|
|
|
5329
5101
|
const program = new Command();
|
|
5330
5102
|
function index() {
|
|
5331
5103
|
program.name(Object.keys(pkg.bin)[0]).version(pkg.version).description(pkg.description);
|
|
5332
|
-
registerCommands$1(program);
|
|
5333
5104
|
registerCommands(program);
|
|
5105
|
+
registerCommands$1(program);
|
|
5334
5106
|
program.parse(process$1.argv);
|
|
5335
5107
|
}
|
|
5336
5108
|
export {
|