@lark-apaas/openclaw-scripts-diagnose-cli 0.1.1-alpha.1 → 0.1.1-alpha.3
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/dist/index.cjs +380 -19
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ node_fs = __toESM(node_fs);
|
|
|
30
30
|
let node_path = require("node:path");
|
|
31
31
|
node_path = __toESM(node_path);
|
|
32
32
|
let node_child_process = require("node:child_process");
|
|
33
|
+
let node_crypto = require("node:crypto");
|
|
33
34
|
//#region src/rule-engine/base.ts
|
|
34
35
|
/** Abstract base class for all diagnose rules */
|
|
35
36
|
var DiagnoseRule = class {
|
|
@@ -721,13 +722,7 @@ AllowedOriginsRule = __decorate([Rule({
|
|
|
721
722
|
repairMode: "standard"
|
|
722
723
|
})], AllowedOriginsRule);
|
|
723
724
|
function getExpectedOrigins(vars) {
|
|
724
|
-
|
|
725
|
-
if (vars.miaodaDomain) origins.push(vars.miaodaDomain);
|
|
726
|
-
if (vars.miaodaOrigin) origins.push(vars.miaodaOrigin);
|
|
727
|
-
if (Array.isArray(vars.miaodaOrigins)) {
|
|
728
|
-
for (const o of vars.miaodaOrigins) if (o) origins.push(o);
|
|
729
|
-
}
|
|
730
|
-
return [...new Set(origins)];
|
|
725
|
+
return Array.isArray(vars.expectedOrigins) ? vars.expectedOrigins : [];
|
|
731
726
|
}
|
|
732
727
|
function getCurrentOrigins(config) {
|
|
733
728
|
const controlUi = getNestedMap(config, "gateway", "controlUi");
|
|
@@ -990,19 +985,385 @@ function runRepair(input) {
|
|
|
990
985
|
}
|
|
991
986
|
}
|
|
992
987
|
//#endregion
|
|
988
|
+
//#region src/backup.ts
|
|
989
|
+
const BACKUP_PATH = "/home/gem/workspace/.force/openclaw/core-backup.json";
|
|
990
|
+
function runBackup(input) {
|
|
991
|
+
try {
|
|
992
|
+
const { configPath } = input;
|
|
993
|
+
try {
|
|
994
|
+
const validateOutput = shell("openclaw config validate --json");
|
|
995
|
+
if (!JSON.parse(validateOutput).valid) return {
|
|
996
|
+
success: false,
|
|
997
|
+
error: "config validation failed"
|
|
998
|
+
};
|
|
999
|
+
} catch (e) {
|
|
1000
|
+
return {
|
|
1001
|
+
success: false,
|
|
1002
|
+
error: "config validate command failed: " + e.message
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
if (!fileExists(configPath)) return {
|
|
1006
|
+
success: false,
|
|
1007
|
+
error: "config file not found: " + configPath
|
|
1008
|
+
};
|
|
1009
|
+
const config = loadJSON5().parse(readFile(configPath));
|
|
1010
|
+
const backup = { _backup_meta: { created_at: (/* @__PURE__ */ new Date()).toISOString() } };
|
|
1011
|
+
if (config.agents) backup.agents = config.agents;
|
|
1012
|
+
if (config.bindings) backup.bindings = config.bindings;
|
|
1013
|
+
const feishu = config.channels?.feishu;
|
|
1014
|
+
if (feishu?.accounts) backup.channels = { feishu: { accounts: feishu.accounts } };
|
|
1015
|
+
const backupDir = node_path.default.dirname(BACKUP_PATH);
|
|
1016
|
+
if (!node_fs.default.existsSync(backupDir)) node_fs.default.mkdirSync(backupDir, { recursive: true });
|
|
1017
|
+
const tmpPath = BACKUP_PATH + ".tmp";
|
|
1018
|
+
node_fs.default.writeFileSync(tmpPath, JSON.stringify(backup, null, 2), "utf-8");
|
|
1019
|
+
node_fs.default.renameSync(tmpPath, BACKUP_PATH);
|
|
1020
|
+
return { success: true };
|
|
1021
|
+
} catch (e) {
|
|
1022
|
+
return {
|
|
1023
|
+
success: false,
|
|
1024
|
+
error: "backup failed: " + e.message
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
//#endregion
|
|
1029
|
+
//#region src/reset-async.ts
|
|
1030
|
+
/**
|
|
1031
|
+
* Start an async reset task: spawn a detached child process and return the taskId.
|
|
1032
|
+
*
|
|
1033
|
+
* The child process runs: node cli.js reset --worker --task-id=xxx --ctx=base64
|
|
1034
|
+
*/
|
|
1035
|
+
function startAsyncReset(ctxBase64) {
|
|
1036
|
+
const taskId = (0, node_crypto.randomUUID)();
|
|
1037
|
+
const resultFile = `/tmp/openclaw-reset-${taskId}.json`;
|
|
1038
|
+
const initial = {
|
|
1039
|
+
status: "running",
|
|
1040
|
+
step: 0,
|
|
1041
|
+
totalSteps: 9,
|
|
1042
|
+
progress: "初始化...",
|
|
1043
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1044
|
+
};
|
|
1045
|
+
const tmpPath = resultFile + ".tmp";
|
|
1046
|
+
const dir = node_path.default.dirname(resultFile);
|
|
1047
|
+
if (!node_fs.default.existsSync(dir)) node_fs.default.mkdirSync(dir, { recursive: true });
|
|
1048
|
+
node_fs.default.writeFileSync(tmpPath, JSON.stringify(initial), "utf-8");
|
|
1049
|
+
node_fs.default.renameSync(tmpPath, resultFile);
|
|
1050
|
+
const child = (0, node_child_process.spawn)(process.execPath, [
|
|
1051
|
+
process.argv[1],
|
|
1052
|
+
"reset",
|
|
1053
|
+
"--worker",
|
|
1054
|
+
`--task-id=${taskId}`,
|
|
1055
|
+
`--ctx=${ctxBase64}`
|
|
1056
|
+
], {
|
|
1057
|
+
detached: true,
|
|
1058
|
+
stdio: "ignore"
|
|
1059
|
+
});
|
|
1060
|
+
child.on("error", (err) => {
|
|
1061
|
+
const failResult = {
|
|
1062
|
+
status: "failed",
|
|
1063
|
+
step: 0,
|
|
1064
|
+
totalSteps: 9,
|
|
1065
|
+
progress: "Worker process failed to start",
|
|
1066
|
+
error: err.message,
|
|
1067
|
+
startedAt: initial.startedAt,
|
|
1068
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1069
|
+
};
|
|
1070
|
+
const errTmpPath = resultFile + ".tmp";
|
|
1071
|
+
node_fs.default.writeFileSync(errTmpPath, JSON.stringify(failResult));
|
|
1072
|
+
node_fs.default.renameSync(errTmpPath, resultFile);
|
|
1073
|
+
});
|
|
1074
|
+
child.unref();
|
|
1075
|
+
return { taskId };
|
|
1076
|
+
}
|
|
1077
|
+
//#endregion
|
|
1078
|
+
//#region src/reset.ts
|
|
1079
|
+
const STEPS = [
|
|
1080
|
+
"备份当前配置",
|
|
1081
|
+
"下载技术栈模板",
|
|
1082
|
+
"生成默认配置",
|
|
1083
|
+
"杀掉 openclaw 进程",
|
|
1084
|
+
"重装 openclaw",
|
|
1085
|
+
"合并核心备份配置",
|
|
1086
|
+
"复制启动脚本",
|
|
1087
|
+
"重装内置插件",
|
|
1088
|
+
"启动并验证"
|
|
1089
|
+
];
|
|
1090
|
+
const TOTAL_STEPS = STEPS.length;
|
|
1091
|
+
const CORE_BACKUP_PATH = "/home/gem/workspace/.force/openclaw/core-backup.json";
|
|
1092
|
+
const TMP_RESET_DIR = "/tmp/openclaw-reset";
|
|
1093
|
+
/**
|
|
1094
|
+
* Atomically write the result file (write .tmp + rename).
|
|
1095
|
+
*/
|
|
1096
|
+
function writeResultFile(resultFile, result) {
|
|
1097
|
+
const dir = node_path.default.dirname(resultFile);
|
|
1098
|
+
if (!node_fs.default.existsSync(dir)) node_fs.default.mkdirSync(dir, { recursive: true });
|
|
1099
|
+
const tmpPath = resultFile + ".tmp";
|
|
1100
|
+
node_fs.default.writeFileSync(tmpPath, JSON.stringify(result), "utf-8");
|
|
1101
|
+
node_fs.default.renameSync(tmpPath, resultFile);
|
|
1102
|
+
}
|
|
1103
|
+
/**
|
|
1104
|
+
* Update progress in the result file.
|
|
1105
|
+
*/
|
|
1106
|
+
function updateProgress(resultFile, step, progress, startedAt) {
|
|
1107
|
+
writeResultFile(resultFile, {
|
|
1108
|
+
status: "running",
|
|
1109
|
+
step,
|
|
1110
|
+
totalSteps: TOTAL_STEPS,
|
|
1111
|
+
progress,
|
|
1112
|
+
startedAt
|
|
1113
|
+
});
|
|
1114
|
+
}
|
|
1115
|
+
/**
|
|
1116
|
+
* Mark the task as done.
|
|
1117
|
+
*/
|
|
1118
|
+
function markDone(resultFile, startedAt) {
|
|
1119
|
+
writeResultFile(resultFile, {
|
|
1120
|
+
status: "done",
|
|
1121
|
+
step: TOTAL_STEPS,
|
|
1122
|
+
totalSteps: TOTAL_STEPS,
|
|
1123
|
+
progress: "重置完成",
|
|
1124
|
+
startedAt,
|
|
1125
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1126
|
+
});
|
|
1127
|
+
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Mark the task as failed.
|
|
1130
|
+
*/
|
|
1131
|
+
function markFailed(resultFile, step, progress, error, startedAt) {
|
|
1132
|
+
writeResultFile(resultFile, {
|
|
1133
|
+
status: "failed",
|
|
1134
|
+
step,
|
|
1135
|
+
totalSteps: TOTAL_STEPS,
|
|
1136
|
+
progress,
|
|
1137
|
+
error,
|
|
1138
|
+
startedAt,
|
|
1139
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
/**
|
|
1143
|
+
* Run the 9-step reset process. Called from the worker entry point.
|
|
1144
|
+
*/
|
|
1145
|
+
function runReset(input, taskId, resultFile) {
|
|
1146
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1147
|
+
const { configPath, resetData } = input;
|
|
1148
|
+
const configDir = node_path.default.dirname(configPath);
|
|
1149
|
+
let currentStep = 0;
|
|
1150
|
+
process.on("uncaughtException", (err) => {
|
|
1151
|
+
const stepName = currentStep > 0 ? STEPS[currentStep - 1] : "初始化";
|
|
1152
|
+
markFailed(resultFile, currentStep, stepName, `uncaught exception: ${err.message}`, startedAt);
|
|
1153
|
+
process.exit(1);
|
|
1154
|
+
});
|
|
1155
|
+
process.on("unhandledRejection", (reason) => {
|
|
1156
|
+
const stepName = currentStep > 0 ? STEPS[currentStep - 1] : "初始化";
|
|
1157
|
+
markFailed(resultFile, currentStep, stepName, `unhandled rejection: ${reason}`, startedAt);
|
|
1158
|
+
process.exit(1);
|
|
1159
|
+
});
|
|
1160
|
+
try {
|
|
1161
|
+
currentStep = 1;
|
|
1162
|
+
updateProgress(resultFile, currentStep, STEPS[0], startedAt);
|
|
1163
|
+
if (fileExists(configPath)) {
|
|
1164
|
+
let maxN = 0;
|
|
1165
|
+
try {
|
|
1166
|
+
const files = node_fs.default.readdirSync(configDir);
|
|
1167
|
+
const bakPattern = /^openclaw\.json\.bak\.(\d+)$/;
|
|
1168
|
+
for (const f of files) {
|
|
1169
|
+
const match = f.match(bakPattern);
|
|
1170
|
+
if (match) {
|
|
1171
|
+
const n = parseInt(match[1], 10);
|
|
1172
|
+
if (n > maxN) maxN = n;
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
} catch {}
|
|
1176
|
+
const bakPath = configPath + ".bak." + (maxN + 1);
|
|
1177
|
+
node_fs.default.copyFileSync(configPath, bakPath);
|
|
1178
|
+
}
|
|
1179
|
+
currentStep = 2;
|
|
1180
|
+
updateProgress(resultFile, currentStep, STEPS[1], startedAt);
|
|
1181
|
+
if (!node_fs.default.existsSync(TMP_RESET_DIR)) node_fs.default.mkdirSync(TMP_RESET_DIR, { recursive: true });
|
|
1182
|
+
const zipPath = node_path.default.join(TMP_RESET_DIR, "template.zip");
|
|
1183
|
+
const zipSource = resetData.zipDownloadURL;
|
|
1184
|
+
if (zipSource.startsWith("http://") || zipSource.startsWith("https://")) shell(`curl -sSL -o '${zipPath}' '${zipSource}'`, 12e4);
|
|
1185
|
+
else shell(`cp '${zipSource}' '${zipPath}'`, 1e4);
|
|
1186
|
+
shell(`unzip -o '${zipPath}' -d '${TMP_RESET_DIR}'`, 6e4);
|
|
1187
|
+
const srcDir = findSrcDir(TMP_RESET_DIR);
|
|
1188
|
+
currentStep = 3;
|
|
1189
|
+
updateProgress(resultFile, currentStep, STEPS[2], startedAt);
|
|
1190
|
+
const srcConfigPath = node_path.default.join(srcDir, "openclaw.json");
|
|
1191
|
+
if (!fileExists(srcConfigPath)) throw new Error("template openclaw.json not found in downloaded zip at " + srcConfigPath);
|
|
1192
|
+
let configContent = node_fs.default.readFileSync(srcConfigPath, "utf-8");
|
|
1193
|
+
for (const [placeholder, value] of Object.entries(resetData.templateVars)) configContent = configContent.split(placeholder).join(value);
|
|
1194
|
+
node_fs.default.writeFileSync(configPath, configContent, "utf-8");
|
|
1195
|
+
currentStep = 4;
|
|
1196
|
+
updateProgress(resultFile, currentStep, STEPS[3], startedAt);
|
|
1197
|
+
try {
|
|
1198
|
+
shell("pkill -f openclaw-gateway || true", 5e3);
|
|
1199
|
+
} catch {}
|
|
1200
|
+
shell("sleep 2", 5e3);
|
|
1201
|
+
currentStep = 5;
|
|
1202
|
+
updateProgress(resultFile, currentStep, STEPS[4], startedAt);
|
|
1203
|
+
const JSON5 = loadJSON5();
|
|
1204
|
+
const version = JSON5.parse(node_fs.default.readFileSync(srcConfigPath, "utf-8")).meta?.lastTouchedVersion;
|
|
1205
|
+
if (version) shell(`npm install -g @anthropic-ai/openclaw@${version}`, 3e5);
|
|
1206
|
+
else shell("npm install -g @anthropic-ai/openclaw@latest", 3e5);
|
|
1207
|
+
currentStep = 6;
|
|
1208
|
+
updateProgress(resultFile, currentStep, STEPS[5], startedAt);
|
|
1209
|
+
if (fileExists(CORE_BACKUP_PATH)) {
|
|
1210
|
+
const backup = JSON.parse(node_fs.default.readFileSync(CORE_BACKUP_PATH, "utf-8"));
|
|
1211
|
+
const mergeConfig = JSON5.parse(node_fs.default.readFileSync(configPath, "utf-8"));
|
|
1212
|
+
if (backup.agents) mergeConfig.agents = backup.agents;
|
|
1213
|
+
if (backup.bindings) mergeConfig.bindings = backup.bindings;
|
|
1214
|
+
const backupFeishu = backup.channels?.feishu;
|
|
1215
|
+
if (backupFeishu?.accounts) {
|
|
1216
|
+
if (!mergeConfig.channels) mergeConfig.channels = {};
|
|
1217
|
+
const ch = mergeConfig.channels;
|
|
1218
|
+
if (!ch.feishu) ch.feishu = {};
|
|
1219
|
+
const feishu = ch.feishu;
|
|
1220
|
+
feishu.accounts = backupFeishu.accounts;
|
|
1221
|
+
}
|
|
1222
|
+
node_fs.default.writeFileSync(configPath, JSON.stringify(mergeConfig, null, 2), "utf-8");
|
|
1223
|
+
}
|
|
1224
|
+
currentStep = 7;
|
|
1225
|
+
updateProgress(resultFile, currentStep, STEPS[6], startedAt);
|
|
1226
|
+
const srcScriptsDir = node_path.default.join(srcDir, "scripts");
|
|
1227
|
+
const targetScriptsDir = node_path.default.join(configDir, "scripts");
|
|
1228
|
+
if (node_fs.default.existsSync(srcScriptsDir)) {
|
|
1229
|
+
if (!node_fs.default.existsSync(targetScriptsDir)) node_fs.default.mkdirSync(targetScriptsDir, { recursive: true });
|
|
1230
|
+
shell(`cp -r '${srcScriptsDir}'/* '${targetScriptsDir}/'`, 1e4);
|
|
1231
|
+
}
|
|
1232
|
+
currentStep = 8;
|
|
1233
|
+
updateProgress(resultFile, currentStep, STEPS[7], startedAt);
|
|
1234
|
+
try {
|
|
1235
|
+
shell("openclaw plugins install --all", 3e5);
|
|
1236
|
+
} catch (e) {}
|
|
1237
|
+
currentStep = 9;
|
|
1238
|
+
updateProgress(resultFile, currentStep, STEPS[8], startedAt);
|
|
1239
|
+
if (resetData.secretsContent && input.vars.secretsFilePath) writeFile(input.vars.secretsFilePath, resetData.secretsContent);
|
|
1240
|
+
if (resetData.providerKeyContent && input.vars.providerFilePath) writeFile(input.vars.providerFilePath, resetData.providerKeyContent);
|
|
1241
|
+
const restartScript = node_path.default.join(configDir, "scripts", "restart.sh");
|
|
1242
|
+
if (fileExists(restartScript)) shell(`bash '${restartScript}'`, 3e4);
|
|
1243
|
+
try {
|
|
1244
|
+
node_fs.default.rmSync(TMP_RESET_DIR, {
|
|
1245
|
+
recursive: true,
|
|
1246
|
+
force: true
|
|
1247
|
+
});
|
|
1248
|
+
} catch {}
|
|
1249
|
+
markDone(resultFile, startedAt);
|
|
1250
|
+
} catch (e) {
|
|
1251
|
+
const stepName = currentStep > 0 ? STEPS[currentStep - 1] : "初始化";
|
|
1252
|
+
markFailed(resultFile, currentStep, stepName, e.message, startedAt);
|
|
1253
|
+
process.exit(1);
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
/**
|
|
1257
|
+
* Find the source directory within the extracted zip.
|
|
1258
|
+
* Looks for openclaw.json in TMP_RESET_DIR or one level deep.
|
|
1259
|
+
*/
|
|
1260
|
+
function findSrcDir(baseDir) {
|
|
1261
|
+
if (node_fs.default.existsSync(node_path.default.join(baseDir, "openclaw.json"))) return baseDir;
|
|
1262
|
+
const entries = node_fs.default.readdirSync(baseDir, { withFileTypes: true });
|
|
1263
|
+
for (const entry of entries) if (entry.isDirectory()) {
|
|
1264
|
+
const candidate = node_path.default.join(baseDir, entry.name);
|
|
1265
|
+
if (node_fs.default.existsSync(node_path.default.join(candidate, "openclaw.json"))) return candidate;
|
|
1266
|
+
}
|
|
1267
|
+
return baseDir;
|
|
1268
|
+
}
|
|
1269
|
+
//#endregion
|
|
1270
|
+
//#region src/get-reset-task.ts
|
|
1271
|
+
/**
|
|
1272
|
+
* Long-poll for a reset task result.
|
|
1273
|
+
* Reads the result file every 1s for up to 30s.
|
|
1274
|
+
* Returns immediately on terminal states (done/failed).
|
|
1275
|
+
*/
|
|
1276
|
+
function getResetTask(taskId) {
|
|
1277
|
+
const resultFile = `/tmp/openclaw-reset-${taskId}.json`;
|
|
1278
|
+
const deadline = Date.now() + 3e4;
|
|
1279
|
+
while (Date.now() < deadline) {
|
|
1280
|
+
if (!node_fs.default.existsSync(resultFile)) {
|
|
1281
|
+
sleepSync(1e3);
|
|
1282
|
+
continue;
|
|
1283
|
+
}
|
|
1284
|
+
try {
|
|
1285
|
+
const content = node_fs.default.readFileSync(resultFile, "utf-8");
|
|
1286
|
+
const result = JSON.parse(content);
|
|
1287
|
+
if (result.status === "done" || result.status === "failed") return result;
|
|
1288
|
+
} catch {}
|
|
1289
|
+
sleepSync(1e3);
|
|
1290
|
+
}
|
|
1291
|
+
if (node_fs.default.existsSync(resultFile)) try {
|
|
1292
|
+
return JSON.parse(node_fs.default.readFileSync(resultFile, "utf-8"));
|
|
1293
|
+
} catch {}
|
|
1294
|
+
return {
|
|
1295
|
+
status: "running",
|
|
1296
|
+
progress: "等待中..."
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1299
|
+
/**
|
|
1300
|
+
* Synchronous sleep using Atomics.wait on a shared buffer.
|
|
1301
|
+
*/
|
|
1302
|
+
function sleepSync(ms) {
|
|
1303
|
+
const buf = new SharedArrayBuffer(4);
|
|
1304
|
+
const arr = new Int32Array(buf);
|
|
1305
|
+
Atomics.wait(arr, 0, 0, ms);
|
|
1306
|
+
}
|
|
1307
|
+
//#endregion
|
|
993
1308
|
//#region src/index.ts
|
|
994
1309
|
const args = node_process.default.argv.slice(2);
|
|
995
1310
|
const mode = args.find((a) => !a.startsWith("--"));
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1311
|
+
switch (mode) {
|
|
1312
|
+
case "check":
|
|
1313
|
+
case "repair": {
|
|
1314
|
+
const ctx = args.find((a) => a.startsWith("--ctx="))?.slice(6);
|
|
1315
|
+
if (!ctx) {
|
|
1316
|
+
console.error("Error: --ctx=<base64> is required");
|
|
1317
|
+
node_process.default.exit(1);
|
|
1318
|
+
}
|
|
1319
|
+
const input = JSON.parse(Buffer.from(ctx, "base64").toString("utf-8"));
|
|
1320
|
+
if (mode === "check") console.log(JSON.stringify(runCheck(input)));
|
|
1321
|
+
else console.log(JSON.stringify(runRepair(input)));
|
|
1322
|
+
break;
|
|
1323
|
+
}
|
|
1324
|
+
case "backup": {
|
|
1325
|
+
const ctx = args.find((a) => a.startsWith("--ctx="))?.slice(6);
|
|
1326
|
+
if (!ctx) {
|
|
1327
|
+
console.error("Error: --ctx=<base64> is required");
|
|
1328
|
+
node_process.default.exit(1);
|
|
1329
|
+
}
|
|
1330
|
+
const input = JSON.parse(Buffer.from(ctx, "base64").toString("utf-8"));
|
|
1331
|
+
console.log(JSON.stringify(runBackup(input)));
|
|
1332
|
+
break;
|
|
1333
|
+
}
|
|
1334
|
+
case "reset":
|
|
1335
|
+
if (args.includes("--async")) {
|
|
1336
|
+
const ctx = args.find((a) => a.startsWith("--ctx="))?.slice(6);
|
|
1337
|
+
if (!ctx) {
|
|
1338
|
+
console.error("Error: --ctx=<base64> is required");
|
|
1339
|
+
node_process.default.exit(1);
|
|
1340
|
+
}
|
|
1341
|
+
console.log(JSON.stringify(startAsyncReset(ctx)));
|
|
1342
|
+
} else if (args.includes("--worker")) {
|
|
1343
|
+
const ctx = args.find((a) => a.startsWith("--ctx="))?.slice(6);
|
|
1344
|
+
const taskId = args.find((a) => a.startsWith("--task-id="))?.slice(10);
|
|
1345
|
+
if (!ctx || !taskId) {
|
|
1346
|
+
console.error("Error: --ctx=<base64> and --task-id=<id> are required for worker");
|
|
1347
|
+
node_process.default.exit(1);
|
|
1348
|
+
}
|
|
1349
|
+
const resultFile = `/tmp/openclaw-reset-${taskId}.json`;
|
|
1350
|
+
runReset(JSON.parse(Buffer.from(ctx, "base64").toString("utf-8")), taskId, resultFile);
|
|
1351
|
+
} else {
|
|
1352
|
+
console.error("Usage: reset --async --ctx=<base64> | reset --worker --task-id=<id> --ctx=<base64>");
|
|
1353
|
+
node_process.default.exit(1);
|
|
1354
|
+
}
|
|
1355
|
+
break;
|
|
1356
|
+
case "get_reset_task": {
|
|
1357
|
+
const taskId = args.find((a) => a.startsWith("--task-id="))?.slice(10);
|
|
1358
|
+
if (!taskId) {
|
|
1359
|
+
console.error("Error: --task-id=<id> is required");
|
|
1360
|
+
node_process.default.exit(1);
|
|
1361
|
+
}
|
|
1362
|
+
console.log(JSON.stringify(getResetTask(taskId)));
|
|
1363
|
+
break;
|
|
1364
|
+
}
|
|
1365
|
+
default:
|
|
1366
|
+
console.error("Usage: mclaw-diagnose <check|repair|backup|reset|get_reset_task> [options]");
|
|
1367
|
+
node_process.default.exit(1);
|
|
1368
|
+
}
|
|
1008
1369
|
//#endregion
|