@lark-apaas/openclaw-scripts-diagnose-cli 0.1.1-alpha.6 → 0.1.1-alpha.7
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 +150 -119
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1090,9 +1090,6 @@ const STEPS = [
|
|
|
1090
1090
|
const TOTAL_STEPS = STEPS.length;
|
|
1091
1091
|
const CORE_BACKUP_PATH = "/home/gem/workspace/.force/openclaw/core-backup.json";
|
|
1092
1092
|
const TMP_RESET_DIR = "/tmp/openclaw-reset";
|
|
1093
|
-
/**
|
|
1094
|
-
* Atomically write the result file (write .tmp + rename).
|
|
1095
|
-
*/
|
|
1096
1093
|
function writeResultFile(resultFile, result) {
|
|
1097
1094
|
const dir = node_path.default.dirname(resultFile);
|
|
1098
1095
|
if (!node_fs.default.existsSync(dir)) node_fs.default.mkdirSync(dir, { recursive: true });
|
|
@@ -1100,21 +1097,15 @@ function writeResultFile(resultFile, result) {
|
|
|
1100
1097
|
node_fs.default.writeFileSync(tmpPath, JSON.stringify(result), "utf-8");
|
|
1101
1098
|
node_fs.default.renameSync(tmpPath, resultFile);
|
|
1102
1099
|
}
|
|
1103
|
-
|
|
1104
|
-
* Update progress in the result file.
|
|
1105
|
-
*/
|
|
1106
|
-
function updateProgress(resultFile, step, progress, startedAt) {
|
|
1100
|
+
function updateProgress(resultFile, step, startedAt) {
|
|
1107
1101
|
writeResultFile(resultFile, {
|
|
1108
1102
|
status: "running",
|
|
1109
1103
|
step,
|
|
1110
1104
|
totalSteps: TOTAL_STEPS,
|
|
1111
|
-
progress,
|
|
1105
|
+
progress: STEPS[step - 1],
|
|
1112
1106
|
startedAt
|
|
1113
1107
|
});
|
|
1114
1108
|
}
|
|
1115
|
-
/**
|
|
1116
|
-
* Mark the task as done.
|
|
1117
|
-
*/
|
|
1118
1109
|
function markDone(resultFile, startedAt) {
|
|
1119
1110
|
writeResultFile(resultFile, {
|
|
1120
1111
|
status: "done",
|
|
@@ -1125,142 +1116,182 @@ function markDone(resultFile, startedAt) {
|
|
|
1125
1116
|
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1126
1117
|
});
|
|
1127
1118
|
}
|
|
1128
|
-
|
|
1129
|
-
* Mark the task as failed.
|
|
1130
|
-
*/
|
|
1131
|
-
function markFailed(resultFile, step, progress, error, startedAt) {
|
|
1119
|
+
function markFailed(resultFile, step, error, startedAt) {
|
|
1132
1120
|
writeResultFile(resultFile, {
|
|
1133
1121
|
status: "failed",
|
|
1134
1122
|
step,
|
|
1135
1123
|
totalSteps: TOTAL_STEPS,
|
|
1136
|
-
progress,
|
|
1124
|
+
progress: step > 0 ? STEPS[step - 1] : "初始化",
|
|
1137
1125
|
error,
|
|
1138
1126
|
startedAt,
|
|
1139
1127
|
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1140
1128
|
});
|
|
1141
1129
|
}
|
|
1130
|
+
/** Step 1: Backup current config as openclaw.json.bak.N */
|
|
1131
|
+
function backupCurrentConfig(configPath) {
|
|
1132
|
+
if (!fileExists(configPath)) return;
|
|
1133
|
+
const dir = node_path.default.dirname(configPath);
|
|
1134
|
+
let maxN = 0;
|
|
1135
|
+
try {
|
|
1136
|
+
for (const f of node_fs.default.readdirSync(dir)) {
|
|
1137
|
+
const match = f.match(/^openclaw\.json\.bak\.(\d+)$/);
|
|
1138
|
+
if (match) {
|
|
1139
|
+
const n = parseInt(match[1], 10);
|
|
1140
|
+
if (n > maxN) maxN = n;
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
} catch {}
|
|
1144
|
+
node_fs.default.copyFileSync(configPath, configPath + ".bak." + (maxN + 1));
|
|
1145
|
+
}
|
|
1146
|
+
/** Step 2: Download/copy template zip and extract to TMP_RESET_DIR. Returns srcDir. */
|
|
1147
|
+
function downloadAndExtractTemplate(zipDownloadURL) {
|
|
1148
|
+
if (!node_fs.default.existsSync(TMP_RESET_DIR)) node_fs.default.mkdirSync(TMP_RESET_DIR, { recursive: true });
|
|
1149
|
+
const zipPath = node_path.default.join(TMP_RESET_DIR, "template.zip");
|
|
1150
|
+
if (zipDownloadURL.startsWith("http://") || zipDownloadURL.startsWith("https://")) shell(`curl -sSL -o '${zipPath}' '${zipDownloadURL}'`, 12e4);
|
|
1151
|
+
else shell(`cp "${zipDownloadURL}" '${zipPath}'`, 1e4);
|
|
1152
|
+
shell(`unzip -o '${zipPath}' -d '${TMP_RESET_DIR}'`, 6e4);
|
|
1153
|
+
return findSrcDir(TMP_RESET_DIR);
|
|
1154
|
+
}
|
|
1155
|
+
/** Step 3: Replace $$__XXX__ placeholders and write default config. */
|
|
1156
|
+
function generateDefaultConfig(srcDir, configPath, templateVars) {
|
|
1157
|
+
const srcConfigPath = node_path.default.join(srcDir, "openclaw.json");
|
|
1158
|
+
if (!fileExists(srcConfigPath)) throw new Error("template openclaw.json not found at " + srcConfigPath);
|
|
1159
|
+
let content = node_fs.default.readFileSync(srcConfigPath, "utf-8");
|
|
1160
|
+
for (const [placeholder, value] of Object.entries(templateVars)) content = content.split(placeholder).join(value);
|
|
1161
|
+
node_fs.default.writeFileSync(configPath, content, "utf-8");
|
|
1162
|
+
}
|
|
1163
|
+
/** Step 4: Kill all openclaw processes. */
|
|
1164
|
+
function killOpenclawProcesses() {
|
|
1165
|
+
try {
|
|
1166
|
+
shell("pkill -f openclaw-gateway || true", 5e3);
|
|
1167
|
+
} catch {}
|
|
1168
|
+
shell("sleep 2", 5e3);
|
|
1169
|
+
}
|
|
1170
|
+
/** Step 5: Reinstall openclaw to the version specified in template. */
|
|
1171
|
+
function reinstallOpenclaw(srcDir) {
|
|
1172
|
+
const version = loadJSON5().parse(node_fs.default.readFileSync(node_path.default.join(srcDir, "openclaw.json"), "utf-8")).meta?.lastTouchedVersion;
|
|
1173
|
+
try {
|
|
1174
|
+
shell("npm uninstall -g openclaw 2>/dev/null || true", 3e4);
|
|
1175
|
+
} catch {}
|
|
1176
|
+
shell(`npm i -g openclaw@${version || "latest"}`, 6e5);
|
|
1177
|
+
shell("openclaw doctor --fix", 12e4);
|
|
1178
|
+
}
|
|
1179
|
+
/** Step 6: Merge core-backup.json into config + ensure allowedOrigins. */
|
|
1180
|
+
function mergeCoreBackupAndOrigins(configPath, vars) {
|
|
1181
|
+
const JSON5 = loadJSON5();
|
|
1182
|
+
if (fileExists(CORE_BACKUP_PATH)) {
|
|
1183
|
+
const backup = JSON.parse(node_fs.default.readFileSync(CORE_BACKUP_PATH, "utf-8"));
|
|
1184
|
+
const config = JSON5.parse(node_fs.default.readFileSync(configPath, "utf-8"));
|
|
1185
|
+
if (backup.agents) config.agents = backup.agents;
|
|
1186
|
+
if (backup.bindings) config.bindings = backup.bindings;
|
|
1187
|
+
const backupAccounts = backup.channels?.feishu;
|
|
1188
|
+
if (backupAccounts?.accounts) {
|
|
1189
|
+
if (!config.channels) config.channels = {};
|
|
1190
|
+
const ch = config.channels;
|
|
1191
|
+
if (!ch.feishu) ch.feishu = {};
|
|
1192
|
+
ch.feishu.accounts = backupAccounts.accounts;
|
|
1193
|
+
}
|
|
1194
|
+
node_fs.default.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
1195
|
+
}
|
|
1196
|
+
const expectedOrigins = Array.isArray(vars.expectedOrigins) ? vars.expectedOrigins : [];
|
|
1197
|
+
if (expectedOrigins.length > 0) {
|
|
1198
|
+
const config = JSON5.parse(node_fs.default.readFileSync(configPath, "utf-8"));
|
|
1199
|
+
if (!config.gateway) config.gateway = {};
|
|
1200
|
+
const gw = config.gateway;
|
|
1201
|
+
if (!gw.controlUi) gw.controlUi = {};
|
|
1202
|
+
const cui = gw.controlUi;
|
|
1203
|
+
const current = Array.isArray(cui.allowedOrigins) ? cui.allowedOrigins.filter((o) => typeof o === "string") : [];
|
|
1204
|
+
const seen = new Set(current);
|
|
1205
|
+
const merged = [...current];
|
|
1206
|
+
for (const o of expectedOrigins) if (!seen.has(o)) {
|
|
1207
|
+
merged.push(o);
|
|
1208
|
+
seen.add(o);
|
|
1209
|
+
}
|
|
1210
|
+
cui.allowedOrigins = merged;
|
|
1211
|
+
node_fs.default.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
/** Step 7: Copy startup scripts from template to agent dir. */
|
|
1215
|
+
function copyStartupScripts(srcDir, configDir) {
|
|
1216
|
+
const srcScriptsDir = node_path.default.join(srcDir, "scripts");
|
|
1217
|
+
const targetScriptsDir = node_path.default.join(configDir, "scripts");
|
|
1218
|
+
if (!node_fs.default.existsSync(srcScriptsDir)) return;
|
|
1219
|
+
if (!node_fs.default.existsSync(targetScriptsDir)) node_fs.default.mkdirSync(targetScriptsDir, { recursive: true });
|
|
1220
|
+
shell(`cp -r '${srcScriptsDir}'/* '${targetScriptsDir}/'`, 1e4);
|
|
1221
|
+
}
|
|
1222
|
+
/** Step 8: Reinstall all plugins via openclaw CLI. */
|
|
1223
|
+
function reinstallPlugins() {
|
|
1224
|
+
try {
|
|
1225
|
+
shell("openclaw plugins update --all", 3e5);
|
|
1226
|
+
} catch {}
|
|
1227
|
+
}
|
|
1228
|
+
/** Step 9: Write secrets/provider key files and restart openclaw. */
|
|
1229
|
+
function writeSecretsAndRestart(vars, resetData, configDir) {
|
|
1230
|
+
if (resetData.secretsContent && vars.secretsFilePath) writeFile(vars.secretsFilePath, resetData.secretsContent);
|
|
1231
|
+
if (resetData.providerKeyContent && vars.providerFilePath) writeFile(vars.providerFilePath, resetData.providerKeyContent);
|
|
1232
|
+
const restartScript = node_path.default.join(configDir, "scripts", "restart.sh");
|
|
1233
|
+
if (fileExists(restartScript)) shell(`bash '${restartScript}'`, 3e4);
|
|
1234
|
+
}
|
|
1235
|
+
/** Clean up temporary reset directory. */
|
|
1236
|
+
function cleanup() {
|
|
1237
|
+
try {
|
|
1238
|
+
node_fs.default.rmSync(TMP_RESET_DIR, {
|
|
1239
|
+
recursive: true,
|
|
1240
|
+
force: true
|
|
1241
|
+
});
|
|
1242
|
+
} catch {}
|
|
1243
|
+
}
|
|
1142
1244
|
/**
|
|
1143
1245
|
* Run the 9-step reset process. Called from the worker entry point.
|
|
1246
|
+
*
|
|
1247
|
+
* Each step is an independent function. The orchestrator handles progress
|
|
1248
|
+
* reporting, error handling, and process-level exception guards.
|
|
1144
1249
|
*/
|
|
1145
1250
|
function runReset(input, taskId, resultFile) {
|
|
1146
1251
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1147
|
-
const { configPath, resetData } = input;
|
|
1252
|
+
const { configPath, vars, resetData } = input;
|
|
1148
1253
|
const configDir = node_path.default.dirname(configPath);
|
|
1149
1254
|
let currentStep = 0;
|
|
1150
1255
|
process.on("uncaughtException", (err) => {
|
|
1151
|
-
|
|
1152
|
-
markFailed(resultFile, currentStep, stepName, `uncaught exception: ${err.message}`, startedAt);
|
|
1256
|
+
markFailed(resultFile, currentStep, `uncaught exception: ${err.message}`, startedAt);
|
|
1153
1257
|
process.exit(1);
|
|
1154
1258
|
});
|
|
1155
1259
|
process.on("unhandledRejection", (reason) => {
|
|
1156
|
-
|
|
1157
|
-
markFailed(resultFile, currentStep, stepName, `unhandled rejection: ${reason}`, startedAt);
|
|
1260
|
+
markFailed(resultFile, currentStep, `unhandled rejection: ${reason}`, startedAt);
|
|
1158
1261
|
process.exit(1);
|
|
1159
1262
|
});
|
|
1263
|
+
/** Advance to the next step, updating the progress file. */
|
|
1264
|
+
const step = (n) => {
|
|
1265
|
+
currentStep = n;
|
|
1266
|
+
updateProgress(resultFile, n, startedAt);
|
|
1267
|
+
};
|
|
1160
1268
|
try {
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
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
|
-
try {
|
|
1206
|
-
shell("npm uninstall -g openclaw 2>/dev/null || true", 3e4);
|
|
1207
|
-
} catch {}
|
|
1208
|
-
if (version) shell(`npm i -g openclaw@${version}`, 6e5);
|
|
1209
|
-
else shell("npm i -g openclaw@latest", 6e5);
|
|
1210
|
-
shell("openclaw doctor --fix", 12e4);
|
|
1211
|
-
currentStep = 6;
|
|
1212
|
-
updateProgress(resultFile, currentStep, STEPS[5], startedAt);
|
|
1213
|
-
if (fileExists(CORE_BACKUP_PATH)) {
|
|
1214
|
-
const backup = JSON.parse(node_fs.default.readFileSync(CORE_BACKUP_PATH, "utf-8"));
|
|
1215
|
-
const mergeConfig = JSON5.parse(node_fs.default.readFileSync(configPath, "utf-8"));
|
|
1216
|
-
if (backup.agents) mergeConfig.agents = backup.agents;
|
|
1217
|
-
if (backup.bindings) mergeConfig.bindings = backup.bindings;
|
|
1218
|
-
const backupFeishu = backup.channels?.feishu;
|
|
1219
|
-
if (backupFeishu?.accounts) {
|
|
1220
|
-
if (!mergeConfig.channels) mergeConfig.channels = {};
|
|
1221
|
-
const ch = mergeConfig.channels;
|
|
1222
|
-
if (!ch.feishu) ch.feishu = {};
|
|
1223
|
-
const feishu = ch.feishu;
|
|
1224
|
-
feishu.accounts = backupFeishu.accounts;
|
|
1225
|
-
}
|
|
1226
|
-
node_fs.default.writeFileSync(configPath, JSON.stringify(mergeConfig, null, 2), "utf-8");
|
|
1227
|
-
}
|
|
1228
|
-
currentStep = 7;
|
|
1229
|
-
updateProgress(resultFile, currentStep, STEPS[6], startedAt);
|
|
1230
|
-
const srcScriptsDir = node_path.default.join(srcDir, "scripts");
|
|
1231
|
-
const targetScriptsDir = node_path.default.join(configDir, "scripts");
|
|
1232
|
-
if (node_fs.default.existsSync(srcScriptsDir)) {
|
|
1233
|
-
if (!node_fs.default.existsSync(targetScriptsDir)) node_fs.default.mkdirSync(targetScriptsDir, { recursive: true });
|
|
1234
|
-
shell(`cp -r '${srcScriptsDir}'/* '${targetScriptsDir}/'`, 1e4);
|
|
1235
|
-
}
|
|
1236
|
-
currentStep = 8;
|
|
1237
|
-
updateProgress(resultFile, currentStep, STEPS[7], startedAt);
|
|
1238
|
-
try {
|
|
1239
|
-
shell("openclaw plugins update --all", 3e5);
|
|
1240
|
-
} catch (e) {}
|
|
1241
|
-
currentStep = 9;
|
|
1242
|
-
updateProgress(resultFile, currentStep, STEPS[8], startedAt);
|
|
1243
|
-
if (resetData.secretsContent && input.vars.secretsFilePath) writeFile(input.vars.secretsFilePath, resetData.secretsContent);
|
|
1244
|
-
if (resetData.providerKeyContent && input.vars.providerFilePath) writeFile(input.vars.providerFilePath, resetData.providerKeyContent);
|
|
1245
|
-
const restartScript = node_path.default.join(configDir, "scripts", "restart.sh");
|
|
1246
|
-
if (fileExists(restartScript)) shell(`bash '${restartScript}'`, 3e4);
|
|
1247
|
-
try {
|
|
1248
|
-
node_fs.default.rmSync(TMP_RESET_DIR, {
|
|
1249
|
-
recursive: true,
|
|
1250
|
-
force: true
|
|
1251
|
-
});
|
|
1252
|
-
} catch {}
|
|
1269
|
+
step(1);
|
|
1270
|
+
backupCurrentConfig(configPath);
|
|
1271
|
+
step(2);
|
|
1272
|
+
const srcDir = downloadAndExtractTemplate(resetData.zipDownloadURL);
|
|
1273
|
+
step(3);
|
|
1274
|
+
generateDefaultConfig(srcDir, configPath, resetData.templateVars);
|
|
1275
|
+
step(4);
|
|
1276
|
+
killOpenclawProcesses();
|
|
1277
|
+
step(5);
|
|
1278
|
+
reinstallOpenclaw(srcDir);
|
|
1279
|
+
step(6);
|
|
1280
|
+
mergeCoreBackupAndOrigins(configPath, vars);
|
|
1281
|
+
step(7);
|
|
1282
|
+
copyStartupScripts(srcDir, configDir);
|
|
1283
|
+
step(8);
|
|
1284
|
+
reinstallPlugins();
|
|
1285
|
+
step(9);
|
|
1286
|
+
writeSecretsAndRestart(vars, resetData, configDir);
|
|
1287
|
+
cleanup();
|
|
1253
1288
|
markDone(resultFile, startedAt);
|
|
1254
1289
|
} catch (e) {
|
|
1255
|
-
|
|
1256
|
-
markFailed(resultFile, currentStep, stepName, e.message, startedAt);
|
|
1290
|
+
markFailed(resultFile, currentStep, e.message, startedAt);
|
|
1257
1291
|
process.exit(1);
|
|
1258
1292
|
}
|
|
1259
1293
|
}
|
|
1260
|
-
/**
|
|
1261
|
-
* Find the source directory within the extracted zip.
|
|
1262
|
-
* Looks for openclaw.json in TMP_RESET_DIR or one level deep.
|
|
1263
|
-
*/
|
|
1294
|
+
/** Find the source directory within the extracted zip (openclaw.json location). */
|
|
1264
1295
|
function findSrcDir(baseDir) {
|
|
1265
1296
|
if (node_fs.default.existsSync(node_path.default.join(baseDir, "openclaw.json"))) return baseDir;
|
|
1266
1297
|
const entries = node_fs.default.readdirSync(baseDir, { withFileTypes: true });
|