@lark-apaas/openclaw-scripts-diagnose-cli 0.1.1-alpha.6 → 0.1.1-alpha.8
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 +144 -129
- package/package.json +4 -2
- package/template/openclaw.json +522 -0
- package/template/scripts/restart.sh +37 -0
- package/template/scripts/start.sh +6 -0
- package/template/scripts/stop.sh +2 -0
package/dist/index.cjs
CHANGED
|
@@ -1078,7 +1078,6 @@ function startAsyncReset(ctxBase64) {
|
|
|
1078
1078
|
//#region src/reset.ts
|
|
1079
1079
|
const STEPS = [
|
|
1080
1080
|
"备份当前配置",
|
|
1081
|
-
"下载技术栈模板",
|
|
1082
1081
|
"生成默认配置",
|
|
1083
1082
|
"杀掉 openclaw 进程",
|
|
1084
1083
|
"重装 openclaw",
|
|
@@ -1089,10 +1088,14 @@ const STEPS = [
|
|
|
1089
1088
|
];
|
|
1090
1089
|
const TOTAL_STEPS = STEPS.length;
|
|
1091
1090
|
const CORE_BACKUP_PATH = "/home/gem/workspace/.force/openclaw/core-backup.json";
|
|
1092
|
-
const TMP_RESET_DIR = "/tmp/openclaw-reset";
|
|
1093
1091
|
/**
|
|
1094
|
-
*
|
|
1092
|
+
* Directory holding the bundled openclaw template (openclaw.json + scripts/).
|
|
1093
|
+
* Synced from git@code.byted.org:apaas/miaoda-openclaw-template.git via
|
|
1094
|
+
* scripts/sync-template.sh and published alongside dist/.
|
|
1095
|
+
*
|
|
1096
|
+
* At runtime, __dirname points to dist/, so the template lives one level up.
|
|
1095
1097
|
*/
|
|
1098
|
+
const TEMPLATE_DIR = node_path.default.resolve(__dirname, "..", "template");
|
|
1096
1099
|
function writeResultFile(resultFile, result) {
|
|
1097
1100
|
const dir = node_path.default.dirname(resultFile);
|
|
1098
1101
|
if (!node_fs.default.existsSync(dir)) node_fs.default.mkdirSync(dir, { recursive: true });
|
|
@@ -1100,21 +1103,15 @@ function writeResultFile(resultFile, result) {
|
|
|
1100
1103
|
node_fs.default.writeFileSync(tmpPath, JSON.stringify(result), "utf-8");
|
|
1101
1104
|
node_fs.default.renameSync(tmpPath, resultFile);
|
|
1102
1105
|
}
|
|
1103
|
-
|
|
1104
|
-
* Update progress in the result file.
|
|
1105
|
-
*/
|
|
1106
|
-
function updateProgress(resultFile, step, progress, startedAt) {
|
|
1106
|
+
function updateProgress(resultFile, step, startedAt) {
|
|
1107
1107
|
writeResultFile(resultFile, {
|
|
1108
1108
|
status: "running",
|
|
1109
1109
|
step,
|
|
1110
1110
|
totalSteps: TOTAL_STEPS,
|
|
1111
|
-
progress,
|
|
1111
|
+
progress: STEPS[step - 1],
|
|
1112
1112
|
startedAt
|
|
1113
1113
|
});
|
|
1114
1114
|
}
|
|
1115
|
-
/**
|
|
1116
|
-
* Mark the task as done.
|
|
1117
|
-
*/
|
|
1118
1115
|
function markDone(resultFile, startedAt) {
|
|
1119
1116
|
writeResultFile(resultFile, {
|
|
1120
1117
|
status: "done",
|
|
@@ -1125,151 +1122,169 @@ function markDone(resultFile, startedAt) {
|
|
|
1125
1122
|
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1126
1123
|
});
|
|
1127
1124
|
}
|
|
1128
|
-
|
|
1129
|
-
* Mark the task as failed.
|
|
1130
|
-
*/
|
|
1131
|
-
function markFailed(resultFile, step, progress, error, startedAt) {
|
|
1125
|
+
function markFailed(resultFile, step, error, startedAt) {
|
|
1132
1126
|
writeResultFile(resultFile, {
|
|
1133
1127
|
status: "failed",
|
|
1134
1128
|
step,
|
|
1135
1129
|
totalSteps: TOTAL_STEPS,
|
|
1136
|
-
progress,
|
|
1130
|
+
progress: step > 0 ? STEPS[step - 1] : "初始化",
|
|
1137
1131
|
error,
|
|
1138
1132
|
startedAt,
|
|
1139
1133
|
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1140
1134
|
});
|
|
1141
1135
|
}
|
|
1136
|
+
/** Step 1: Backup current config as openclaw.json.bak.N */
|
|
1137
|
+
function backupCurrentConfig(configPath) {
|
|
1138
|
+
if (!fileExists(configPath)) return;
|
|
1139
|
+
const dir = node_path.default.dirname(configPath);
|
|
1140
|
+
let maxN = 0;
|
|
1141
|
+
try {
|
|
1142
|
+
for (const f of node_fs.default.readdirSync(dir)) {
|
|
1143
|
+
const match = f.match(/^openclaw\.json\.bak\.(\d+)$/);
|
|
1144
|
+
if (match) {
|
|
1145
|
+
const n = parseInt(match[1], 10);
|
|
1146
|
+
if (n > maxN) maxN = n;
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
} catch {}
|
|
1150
|
+
node_fs.default.copyFileSync(configPath, configPath + ".bak." + (maxN + 1));
|
|
1151
|
+
}
|
|
1152
|
+
/** Step 2: Replace $$__XXX__ placeholders and write default config. */
|
|
1153
|
+
function generateDefaultConfig(srcDir, configPath, templateVars) {
|
|
1154
|
+
const srcConfigPath = node_path.default.join(srcDir, "openclaw.json");
|
|
1155
|
+
if (!fileExists(srcConfigPath)) throw new Error("template openclaw.json not found at " + srcConfigPath);
|
|
1156
|
+
let content = node_fs.default.readFileSync(srcConfigPath, "utf-8");
|
|
1157
|
+
for (const [placeholder, value] of Object.entries(templateVars)) content = content.split(placeholder).join(value);
|
|
1158
|
+
node_fs.default.writeFileSync(configPath, content, "utf-8");
|
|
1159
|
+
}
|
|
1160
|
+
/** Step 3: Kill all openclaw processes. */
|
|
1161
|
+
function killOpenclawProcesses() {
|
|
1162
|
+
try {
|
|
1163
|
+
shell("pkill -f openclaw-gateway || true", 5e3);
|
|
1164
|
+
} catch {}
|
|
1165
|
+
shell("sleep 2", 5e3);
|
|
1166
|
+
}
|
|
1167
|
+
/** Step 4: Reinstall openclaw to the version specified in template. */
|
|
1168
|
+
function reinstallOpenclaw(srcDir) {
|
|
1169
|
+
const version = loadJSON5().parse(node_fs.default.readFileSync(node_path.default.join(srcDir, "openclaw.json"), "utf-8")).meta?.lastTouchedVersion;
|
|
1170
|
+
try {
|
|
1171
|
+
shell("npm uninstall -g openclaw 2>/dev/null || true", 3e4);
|
|
1172
|
+
} catch {}
|
|
1173
|
+
shell(`npm i -g openclaw@${version || "latest"}`, 6e5);
|
|
1174
|
+
shell("openclaw doctor --fix", 12e4);
|
|
1175
|
+
}
|
|
1176
|
+
/** Step 5: Merge core-backup.json into config + ensure allowedOrigins. */
|
|
1177
|
+
function mergeCoreBackupAndOrigins(configPath, vars) {
|
|
1178
|
+
const JSON5 = loadJSON5();
|
|
1179
|
+
if (fileExists(CORE_BACKUP_PATH)) {
|
|
1180
|
+
const backup = JSON.parse(node_fs.default.readFileSync(CORE_BACKUP_PATH, "utf-8"));
|
|
1181
|
+
const config = JSON5.parse(node_fs.default.readFileSync(configPath, "utf-8"));
|
|
1182
|
+
if (backup.agents) config.agents = backup.agents;
|
|
1183
|
+
if (backup.bindings) config.bindings = backup.bindings;
|
|
1184
|
+
const backupAccounts = backup.channels?.feishu;
|
|
1185
|
+
if (backupAccounts?.accounts) {
|
|
1186
|
+
if (!config.channels) config.channels = {};
|
|
1187
|
+
const ch = config.channels;
|
|
1188
|
+
if (!ch.feishu) ch.feishu = {};
|
|
1189
|
+
ch.feishu.accounts = backupAccounts.accounts;
|
|
1190
|
+
}
|
|
1191
|
+
node_fs.default.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
1192
|
+
}
|
|
1193
|
+
const expectedOrigins = Array.isArray(vars.expectedOrigins) ? vars.expectedOrigins : [];
|
|
1194
|
+
if (expectedOrigins.length > 0) {
|
|
1195
|
+
const config = JSON5.parse(node_fs.default.readFileSync(configPath, "utf-8"));
|
|
1196
|
+
if (!config.gateway) config.gateway = {};
|
|
1197
|
+
const gw = config.gateway;
|
|
1198
|
+
if (!gw.controlUi) gw.controlUi = {};
|
|
1199
|
+
const cui = gw.controlUi;
|
|
1200
|
+
const current = Array.isArray(cui.allowedOrigins) ? cui.allowedOrigins.filter((o) => typeof o === "string") : [];
|
|
1201
|
+
const seen = new Set(current);
|
|
1202
|
+
const merged = [...current];
|
|
1203
|
+
for (const o of expectedOrigins) if (!seen.has(o)) {
|
|
1204
|
+
merged.push(o);
|
|
1205
|
+
seen.add(o);
|
|
1206
|
+
}
|
|
1207
|
+
cui.allowedOrigins = merged;
|
|
1208
|
+
node_fs.default.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
/** Step 6: Copy startup scripts from template to agent dir. */
|
|
1212
|
+
function copyStartupScripts(srcDir, configDir) {
|
|
1213
|
+
const srcScriptsDir = node_path.default.join(srcDir, "scripts");
|
|
1214
|
+
const targetScriptsDir = node_path.default.join(configDir, "scripts");
|
|
1215
|
+
if (!node_fs.default.existsSync(srcScriptsDir)) return;
|
|
1216
|
+
if (!node_fs.default.existsSync(targetScriptsDir)) node_fs.default.mkdirSync(targetScriptsDir, { recursive: true });
|
|
1217
|
+
shell(`cp -r '${srcScriptsDir}'/* '${targetScriptsDir}/'`, 1e4);
|
|
1218
|
+
}
|
|
1219
|
+
/** Step 7: Reinstall all plugins via openclaw CLI. */
|
|
1220
|
+
function reinstallPlugins() {
|
|
1221
|
+
try {
|
|
1222
|
+
shell("openclaw plugins update --all", 3e5);
|
|
1223
|
+
} catch {}
|
|
1224
|
+
}
|
|
1225
|
+
/** Step 8: Write secrets/provider key files and restart openclaw. */
|
|
1226
|
+
function writeSecretsAndRestart(vars, resetData, configDir) {
|
|
1227
|
+
if (resetData.secretsContent && vars.secretsFilePath) writeFile(vars.secretsFilePath, resetData.secretsContent);
|
|
1228
|
+
if (resetData.providerKeyContent && vars.providerFilePath) writeFile(vars.providerFilePath, resetData.providerKeyContent);
|
|
1229
|
+
const restartScript = node_path.default.join(configDir, "scripts", "restart.sh");
|
|
1230
|
+
if (fileExists(restartScript)) shell(`bash '${restartScript}'`, 3e4);
|
|
1231
|
+
}
|
|
1142
1232
|
/**
|
|
1143
|
-
* Run the
|
|
1233
|
+
* Run the 8-step reset process. Called from the worker entry point.
|
|
1234
|
+
*
|
|
1235
|
+
* Each step is an independent function. The orchestrator handles progress
|
|
1236
|
+
* reporting, error handling, and process-level exception guards.
|
|
1237
|
+
*
|
|
1238
|
+
* The openclaw.json / scripts/*.sh template files are bundled with this CLI
|
|
1239
|
+
* (see TEMPLATE_DIR) and synced from the miaoda-openclaw-template repo via
|
|
1240
|
+
* scripts/sync-template.sh, so no runtime download is required.
|
|
1144
1241
|
*/
|
|
1145
1242
|
function runReset(input, taskId, resultFile) {
|
|
1146
1243
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1147
|
-
const { configPath, resetData } = input;
|
|
1244
|
+
const { configPath, vars, resetData } = input;
|
|
1148
1245
|
const configDir = node_path.default.dirname(configPath);
|
|
1246
|
+
const srcDir = TEMPLATE_DIR;
|
|
1149
1247
|
let currentStep = 0;
|
|
1248
|
+
if (!node_fs.default.existsSync(node_path.default.join(srcDir, "openclaw.json"))) {
|
|
1249
|
+
markFailed(resultFile, 0, `bundled template not found at ${srcDir}`, startedAt);
|
|
1250
|
+
process.exit(1);
|
|
1251
|
+
}
|
|
1150
1252
|
process.on("uncaughtException", (err) => {
|
|
1151
|
-
|
|
1152
|
-
markFailed(resultFile, currentStep, stepName, `uncaught exception: ${err.message}`, startedAt);
|
|
1253
|
+
markFailed(resultFile, currentStep, `uncaught exception: ${err.message}`, startedAt);
|
|
1153
1254
|
process.exit(1);
|
|
1154
1255
|
});
|
|
1155
1256
|
process.on("unhandledRejection", (reason) => {
|
|
1156
|
-
|
|
1157
|
-
markFailed(resultFile, currentStep, stepName, `unhandled rejection: ${reason}`, startedAt);
|
|
1257
|
+
markFailed(resultFile, currentStep, `unhandled rejection: ${reason}`, startedAt);
|
|
1158
1258
|
process.exit(1);
|
|
1159
1259
|
});
|
|
1260
|
+
/** Advance to the next step, updating the progress file. */
|
|
1261
|
+
const step = (n) => {
|
|
1262
|
+
currentStep = n;
|
|
1263
|
+
updateProgress(resultFile, n, startedAt);
|
|
1264
|
+
};
|
|
1160
1265
|
try {
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
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
|
-
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 {}
|
|
1266
|
+
step(1);
|
|
1267
|
+
backupCurrentConfig(configPath);
|
|
1268
|
+
step(2);
|
|
1269
|
+
generateDefaultConfig(srcDir, configPath, resetData.templateVars);
|
|
1270
|
+
step(3);
|
|
1271
|
+
killOpenclawProcesses();
|
|
1272
|
+
step(4);
|
|
1273
|
+
reinstallOpenclaw(srcDir);
|
|
1274
|
+
step(5);
|
|
1275
|
+
mergeCoreBackupAndOrigins(configPath, vars);
|
|
1276
|
+
step(6);
|
|
1277
|
+
copyStartupScripts(srcDir, configDir);
|
|
1278
|
+
step(7);
|
|
1279
|
+
reinstallPlugins();
|
|
1280
|
+
step(8);
|
|
1281
|
+
writeSecretsAndRestart(vars, resetData, configDir);
|
|
1253
1282
|
markDone(resultFile, startedAt);
|
|
1254
1283
|
} catch (e) {
|
|
1255
|
-
|
|
1256
|
-
markFailed(resultFile, currentStep, stepName, e.message, startedAt);
|
|
1284
|
+
markFailed(resultFile, currentStep, e.message, startedAt);
|
|
1257
1285
|
process.exit(1);
|
|
1258
1286
|
}
|
|
1259
1287
|
}
|
|
1260
|
-
/**
|
|
1261
|
-
* Find the source directory within the extracted zip.
|
|
1262
|
-
* Looks for openclaw.json in TMP_RESET_DIR or one level deep.
|
|
1263
|
-
*/
|
|
1264
|
-
function findSrcDir(baseDir) {
|
|
1265
|
-
if (node_fs.default.existsSync(node_path.default.join(baseDir, "openclaw.json"))) return baseDir;
|
|
1266
|
-
const entries = node_fs.default.readdirSync(baseDir, { withFileTypes: true });
|
|
1267
|
-
for (const entry of entries) if (entry.isDirectory()) {
|
|
1268
|
-
const candidate = node_path.default.join(baseDir, entry.name);
|
|
1269
|
-
if (node_fs.default.existsSync(node_path.default.join(candidate, "openclaw.json"))) return candidate;
|
|
1270
|
-
}
|
|
1271
|
-
return baseDir;
|
|
1272
|
-
}
|
|
1273
1288
|
//#endregion
|
|
1274
1289
|
//#region src/get-reset-task.ts
|
|
1275
1290
|
/**
|
package/package.json
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lark-apaas/openclaw-scripts-diagnose-cli",
|
|
3
|
-
"version": "0.1.1-alpha.
|
|
3
|
+
"version": "0.1.1-alpha.8",
|
|
4
4
|
"description": "CLI for OpenClaw config diagnose and repair with JSON5 support",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"bin": {
|
|
7
7
|
"mclaw-diagnose": "./dist/index.cjs"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
|
-
"dist"
|
|
10
|
+
"dist",
|
|
11
|
+
"template"
|
|
11
12
|
],
|
|
12
13
|
"scripts": {
|
|
13
14
|
"build": "tsdown",
|
|
14
15
|
"test": "vitest run",
|
|
15
16
|
"test:watch": "vitest",
|
|
16
17
|
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
18
|
+
"sync:template": "bash scripts/sync-template.sh",
|
|
17
19
|
"prepublishOnly": "npm run build"
|
|
18
20
|
},
|
|
19
21
|
"keywords": [
|
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"lastTouchedVersion": "2026.4.9",
|
|
4
|
+
"lastTouchedAt": "2026-04-11T09:30:21.703Z"
|
|
5
|
+
},
|
|
6
|
+
"wizard": {
|
|
7
|
+
"lastRunAt": "2026-03-30T14:54:56.160Z",
|
|
8
|
+
"lastRunVersion": "2026.3.24",
|
|
9
|
+
"lastRunCommand": "doctor",
|
|
10
|
+
"lastRunMode": "local"
|
|
11
|
+
},
|
|
12
|
+
"update": {
|
|
13
|
+
"checkOnStart": false
|
|
14
|
+
},
|
|
15
|
+
"browser": {
|
|
16
|
+
"enabled": true,
|
|
17
|
+
"color": "#00AA00",
|
|
18
|
+
"executablePath": "/usr/bin/chromium-browser",
|
|
19
|
+
"headless": true,
|
|
20
|
+
"noSandbox": true,
|
|
21
|
+
"defaultProfile": "openclaw",
|
|
22
|
+
"extraArgs": [
|
|
23
|
+
"--window-size=1920,1080",
|
|
24
|
+
"--test-type",
|
|
25
|
+
"--disable-gpu",
|
|
26
|
+
"--no-sandbox"
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
"secrets": {
|
|
30
|
+
"providers": {
|
|
31
|
+
"miaoda-provider": {
|
|
32
|
+
"source": "file",
|
|
33
|
+
"path": "$$__MIAODA_PROVIDER_FILEPATH__",
|
|
34
|
+
"mode": "singleValue"
|
|
35
|
+
},
|
|
36
|
+
"miaoda-secret-provider": {
|
|
37
|
+
"source": "file",
|
|
38
|
+
"path": "$$__MIAODA_OPENCLAW_SECRETS_FILEPATH__",
|
|
39
|
+
"mode": "json"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"models": {
|
|
44
|
+
"providers": {
|
|
45
|
+
"miaoda": {
|
|
46
|
+
"baseUrl": "$$__MIAODA_PROVIDER_BASE_URL__",
|
|
47
|
+
"apiKey": {
|
|
48
|
+
"source": "file",
|
|
49
|
+
"provider": "miaoda-provider",
|
|
50
|
+
"id": "value"
|
|
51
|
+
},
|
|
52
|
+
"api": "openai-completions",
|
|
53
|
+
"headers": {
|
|
54
|
+
"x-api-key": {
|
|
55
|
+
"source": "file",
|
|
56
|
+
"provider": "miaoda-secret-provider",
|
|
57
|
+
"id": "/models_providers_miaoda_headers_x_api_key"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"models": [
|
|
61
|
+
{
|
|
62
|
+
"id": "miaoda-model-auto",
|
|
63
|
+
"name": "妙搭",
|
|
64
|
+
"reasoning": false,
|
|
65
|
+
"input": [
|
|
66
|
+
"text"
|
|
67
|
+
],
|
|
68
|
+
"cost": {
|
|
69
|
+
"input": 0,
|
|
70
|
+
"output": 0,
|
|
71
|
+
"cacheRead": 0,
|
|
72
|
+
"cacheWrite": 0
|
|
73
|
+
},
|
|
74
|
+
"contextWindow": 200000,
|
|
75
|
+
"maxTokens": 8192
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"id": "miaoda-auto-multimodal",
|
|
79
|
+
"name": "妙搭多模态",
|
|
80
|
+
"reasoning": false,
|
|
81
|
+
"input": [
|
|
82
|
+
"text",
|
|
83
|
+
"image"
|
|
84
|
+
],
|
|
85
|
+
"cost": {
|
|
86
|
+
"input": 0,
|
|
87
|
+
"output": 0,
|
|
88
|
+
"cacheRead": 0,
|
|
89
|
+
"cacheWrite": 0
|
|
90
|
+
},
|
|
91
|
+
"contextWindow": 200000,
|
|
92
|
+
"maxTokens": 8192
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"id": "miaoda-model-flash",
|
|
96
|
+
"name": "妙搭 Flash",
|
|
97
|
+
"reasoning": false,
|
|
98
|
+
"input": [
|
|
99
|
+
"text"
|
|
100
|
+
],
|
|
101
|
+
"cost": {
|
|
102
|
+
"input": 0,
|
|
103
|
+
"output": 0,
|
|
104
|
+
"cacheRead": 0,
|
|
105
|
+
"cacheWrite": 0
|
|
106
|
+
},
|
|
107
|
+
"contextWindow": 200000,
|
|
108
|
+
"maxTokens": 8192
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
"agents": {
|
|
115
|
+
"defaults": {
|
|
116
|
+
"model": {
|
|
117
|
+
"primary": "miaoda/miaoda-model-auto"
|
|
118
|
+
},
|
|
119
|
+
"imageModel": "miaoda/miaoda-auto-multimodal",
|
|
120
|
+
"imageGenerationModel": {
|
|
121
|
+
"primary": "miaoda/miaoda-image-gen"
|
|
122
|
+
},
|
|
123
|
+
"models": {
|
|
124
|
+
"miaoda/miaoda-model-auto": {
|
|
125
|
+
"alias": "Miaoda Auto"
|
|
126
|
+
},
|
|
127
|
+
"miaoda/miaoda-auto-multimodal": {
|
|
128
|
+
"alias": "Miaoda Multimodal"
|
|
129
|
+
},
|
|
130
|
+
"miaoda/miaoda-model-flash": {
|
|
131
|
+
"alias": "Miaoda Flash"
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
"workspace": "$$__MIAODA_WORKSPACE_DIR__/workspace",
|
|
135
|
+
"compaction": {
|
|
136
|
+
"mode": "safeguard",
|
|
137
|
+
"reserveTokensFloor": 50000
|
|
138
|
+
},
|
|
139
|
+
"verboseDefault": "off",
|
|
140
|
+
"blockStreamingCoalesce": {
|
|
141
|
+
"minChars": 20,
|
|
142
|
+
"maxChars": 800,
|
|
143
|
+
"idleMs": 300
|
|
144
|
+
},
|
|
145
|
+
"humanDelay": {
|
|
146
|
+
"mode": "off"
|
|
147
|
+
},
|
|
148
|
+
"heartbeat": {
|
|
149
|
+
"every": "4h",
|
|
150
|
+
"activeHours": {
|
|
151
|
+
"start": "08:00",
|
|
152
|
+
"end": "22:00"
|
|
153
|
+
},
|
|
154
|
+
"model": "miaoda/miaoda-model-flash"
|
|
155
|
+
},
|
|
156
|
+
"maxConcurrent": 4,
|
|
157
|
+
"subagents": {
|
|
158
|
+
"maxConcurrent": 8
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
"tools": {
|
|
163
|
+
"profile": "full",
|
|
164
|
+
"alsoAllow": [
|
|
165
|
+
"feishu_bitable_app",
|
|
166
|
+
"feishu_bitable_app_table",
|
|
167
|
+
"feishu_bitable_app_table_field",
|
|
168
|
+
"feishu_bitable_app_table_record",
|
|
169
|
+
"feishu_bitable_app_table_view",
|
|
170
|
+
"feishu_calendar_calendar",
|
|
171
|
+
"feishu_calendar_event",
|
|
172
|
+
"feishu_calendar_event_attendee",
|
|
173
|
+
"feishu_calendar_freebusy",
|
|
174
|
+
"feishu_chat",
|
|
175
|
+
"feishu_chat_members",
|
|
176
|
+
"feishu_create_doc",
|
|
177
|
+
"feishu_doc_comments",
|
|
178
|
+
"feishu_doc_media",
|
|
179
|
+
"feishu_drive_file",
|
|
180
|
+
"feishu_fetch_doc",
|
|
181
|
+
"feishu_get_user",
|
|
182
|
+
"feishu_im_bot_image",
|
|
183
|
+
"feishu_im_user_fetch_resource",
|
|
184
|
+
"feishu_im_user_get_messages",
|
|
185
|
+
"feishu_im_user_get_thread_messages",
|
|
186
|
+
"feishu_im_user_message",
|
|
187
|
+
"feishu_im_user_search_messages",
|
|
188
|
+
"feishu_oauth",
|
|
189
|
+
"feishu_oauth_batch_auth",
|
|
190
|
+
"feishu_search_doc_wiki",
|
|
191
|
+
"feishu_search_user",
|
|
192
|
+
"feishu_sheet",
|
|
193
|
+
"feishu_task_comment",
|
|
194
|
+
"feishu_task_subtask",
|
|
195
|
+
"feishu_task_task",
|
|
196
|
+
"feishu_task_tasklist",
|
|
197
|
+
"feishu_update_doc",
|
|
198
|
+
"feishu_wiki_space",
|
|
199
|
+
"feishu_wiki_space_node"
|
|
200
|
+
],
|
|
201
|
+
"deny": [
|
|
202
|
+
"web_fetch",
|
|
203
|
+
"tts",
|
|
204
|
+
"agents_list",
|
|
205
|
+
"feishu_task_task",
|
|
206
|
+
"feishu_task_tasklist",
|
|
207
|
+
"feishu_task_comment",
|
|
208
|
+
"feishu_task_subtask",
|
|
209
|
+
"feishu_bitable_app_table_view",
|
|
210
|
+
"feishu_doc_comments",
|
|
211
|
+
"feishu_doc_media",
|
|
212
|
+
"feishu_drive_file",
|
|
213
|
+
"feishu_wiki_space",
|
|
214
|
+
"feishu_wiki_space_node",
|
|
215
|
+
"feishu_sheet"
|
|
216
|
+
],
|
|
217
|
+
"web": {
|
|
218
|
+
"search": {
|
|
219
|
+
"provider": "miaoda"
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
"media": {
|
|
223
|
+
"image": {
|
|
224
|
+
"models": [
|
|
225
|
+
{
|
|
226
|
+
"provider": "miaoda"
|
|
227
|
+
}
|
|
228
|
+
]
|
|
229
|
+
},
|
|
230
|
+
"audio": {
|
|
231
|
+
"models": [
|
|
232
|
+
{
|
|
233
|
+
"provider": "miaoda"
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
"sessions": {
|
|
239
|
+
"visibility": "all"
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
"messages": {
|
|
243
|
+
"ackReactionScope": "group-mentions"
|
|
244
|
+
},
|
|
245
|
+
"commands": {
|
|
246
|
+
"native": "auto",
|
|
247
|
+
"nativeSkills": "auto",
|
|
248
|
+
"restart": true,
|
|
249
|
+
"ownerDisplay": "raw"
|
|
250
|
+
},
|
|
251
|
+
"session": {
|
|
252
|
+
"dmScope": "per-channel-peer"
|
|
253
|
+
},
|
|
254
|
+
"channels": {
|
|
255
|
+
"feishu": {
|
|
256
|
+
"enabled": true,
|
|
257
|
+
"appId": "$$__FEISHU_APP_ID__",
|
|
258
|
+
"appSecret": {
|
|
259
|
+
"source": "file",
|
|
260
|
+
"provider": "miaoda-secret-provider",
|
|
261
|
+
"id": "/channels_feishu_app_secret"
|
|
262
|
+
},
|
|
263
|
+
"domain": "feishu",
|
|
264
|
+
"requireMention": true,
|
|
265
|
+
"dmPolicy": "allowlist",
|
|
266
|
+
"allowFrom": [
|
|
267
|
+
"$$__FEISHU_OPEN_ID__"
|
|
268
|
+
],
|
|
269
|
+
"groupPolicy": "allowlist",
|
|
270
|
+
"groupAllowFrom": [
|
|
271
|
+
"$$__FEISHU_OPEN_ID__"
|
|
272
|
+
],
|
|
273
|
+
"groups": {
|
|
274
|
+
"*": {
|
|
275
|
+
"enabled": true
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
"streaming": true,
|
|
279
|
+
"threadSession": true,
|
|
280
|
+
"footer": {
|
|
281
|
+
"elapsed": false,
|
|
282
|
+
"status": false
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
},
|
|
286
|
+
"discovery": {
|
|
287
|
+
"mdns": {
|
|
288
|
+
"mode": "off"
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
"gateway": {
|
|
292
|
+
"port": 18789,
|
|
293
|
+
"mode": "local",
|
|
294
|
+
"bind": "loopback",
|
|
295
|
+
"controlUi": {
|
|
296
|
+
"allowedOrigins": [
|
|
297
|
+
"$$__MIAODA_DOMAIN__",
|
|
298
|
+
"$$__MIAODA_ORIGIN__"
|
|
299
|
+
],
|
|
300
|
+
"dangerouslyDisableDeviceAuth": true
|
|
301
|
+
},
|
|
302
|
+
"auth": {
|
|
303
|
+
"mode": "token",
|
|
304
|
+
"token": "$$__CLAW_TOKEN__"
|
|
305
|
+
},
|
|
306
|
+
"trustedProxies": [
|
|
307
|
+
"::1",
|
|
308
|
+
"127.0.0.1"
|
|
309
|
+
],
|
|
310
|
+
"tailscale": {
|
|
311
|
+
"mode": "off",
|
|
312
|
+
"resetOnExit": false
|
|
313
|
+
}
|
|
314
|
+
},
|
|
315
|
+
"skills": {
|
|
316
|
+
"install": {
|
|
317
|
+
"nodeManager": "npm"
|
|
318
|
+
},
|
|
319
|
+
"entries": {
|
|
320
|
+
"1password": {
|
|
321
|
+
"enabled": false
|
|
322
|
+
},
|
|
323
|
+
"apple-notes": {
|
|
324
|
+
"enabled": false
|
|
325
|
+
},
|
|
326
|
+
"apple-reminders": {
|
|
327
|
+
"enabled": false
|
|
328
|
+
},
|
|
329
|
+
"bear-notes": {
|
|
330
|
+
"enabled": false
|
|
331
|
+
},
|
|
332
|
+
"bluebubbles": {
|
|
333
|
+
"enabled": false
|
|
334
|
+
},
|
|
335
|
+
"blucli": {
|
|
336
|
+
"enabled": false
|
|
337
|
+
},
|
|
338
|
+
"camsnap": {
|
|
339
|
+
"enabled": false
|
|
340
|
+
},
|
|
341
|
+
"coding-agent": {
|
|
342
|
+
"enabled": false
|
|
343
|
+
},
|
|
344
|
+
"discord": {
|
|
345
|
+
"enabled": false
|
|
346
|
+
},
|
|
347
|
+
"eightctl": {
|
|
348
|
+
"enabled": false
|
|
349
|
+
},
|
|
350
|
+
"gemini": {
|
|
351
|
+
"enabled": false
|
|
352
|
+
},
|
|
353
|
+
"gifgrep": {
|
|
354
|
+
"enabled": false
|
|
355
|
+
},
|
|
356
|
+
"gog": {
|
|
357
|
+
"enabled": false
|
|
358
|
+
},
|
|
359
|
+
"goplaces": {
|
|
360
|
+
"enabled": false
|
|
361
|
+
},
|
|
362
|
+
"imsg": {
|
|
363
|
+
"enabled": false
|
|
364
|
+
},
|
|
365
|
+
"model-usage": {
|
|
366
|
+
"enabled": false
|
|
367
|
+
},
|
|
368
|
+
"notion": {
|
|
369
|
+
"enabled": false
|
|
370
|
+
},
|
|
371
|
+
"openai-image-gen": {
|
|
372
|
+
"enabled": false
|
|
373
|
+
},
|
|
374
|
+
"openai-whisper": {
|
|
375
|
+
"enabled": false
|
|
376
|
+
},
|
|
377
|
+
"openai-whisper-api": {
|
|
378
|
+
"enabled": false
|
|
379
|
+
},
|
|
380
|
+
"openhue": {
|
|
381
|
+
"enabled": false
|
|
382
|
+
},
|
|
383
|
+
"oracle": {
|
|
384
|
+
"enabled": false
|
|
385
|
+
},
|
|
386
|
+
"ordercli": {
|
|
387
|
+
"enabled": false
|
|
388
|
+
},
|
|
389
|
+
"peekaboo": {
|
|
390
|
+
"enabled": false
|
|
391
|
+
},
|
|
392
|
+
"sag": {
|
|
393
|
+
"enabled": false
|
|
394
|
+
},
|
|
395
|
+
"slack": {
|
|
396
|
+
"enabled": false
|
|
397
|
+
},
|
|
398
|
+
"sonoscli": {
|
|
399
|
+
"enabled": false
|
|
400
|
+
},
|
|
401
|
+
"spotify-player": {
|
|
402
|
+
"enabled": false
|
|
403
|
+
},
|
|
404
|
+
"summarize": {
|
|
405
|
+
"enabled": false
|
|
406
|
+
},
|
|
407
|
+
"things-mac": {
|
|
408
|
+
"enabled": false
|
|
409
|
+
},
|
|
410
|
+
"trello": {
|
|
411
|
+
"enabled": false
|
|
412
|
+
},
|
|
413
|
+
"voice-call": {
|
|
414
|
+
"enabled": false
|
|
415
|
+
},
|
|
416
|
+
"wacli": {
|
|
417
|
+
"enabled": false
|
|
418
|
+
},
|
|
419
|
+
"xurl": {
|
|
420
|
+
"enabled": false
|
|
421
|
+
},
|
|
422
|
+
"feishu-task": {
|
|
423
|
+
"enabled": false
|
|
424
|
+
},
|
|
425
|
+
"gh-issues": {
|
|
426
|
+
"enabled": false
|
|
427
|
+
},
|
|
428
|
+
"github": {
|
|
429
|
+
"enabled": false
|
|
430
|
+
},
|
|
431
|
+
"tmux": {
|
|
432
|
+
"enabled": false
|
|
433
|
+
},
|
|
434
|
+
"blogwatcher": {
|
|
435
|
+
"enabled": false
|
|
436
|
+
},
|
|
437
|
+
"himalaya": {
|
|
438
|
+
"enabled": false
|
|
439
|
+
},
|
|
440
|
+
"video-frames": {
|
|
441
|
+
"enabled": false
|
|
442
|
+
},
|
|
443
|
+
"obsidian": {
|
|
444
|
+
"enabled": false
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
},
|
|
448
|
+
"plugins": {
|
|
449
|
+
"allow": [
|
|
450
|
+
"openclaw-lark",
|
|
451
|
+
"openclaw-extension-miaoda",
|
|
452
|
+
"openclaw-extension-miaoda-coding",
|
|
453
|
+
"browser"
|
|
454
|
+
],
|
|
455
|
+
"entries": {
|
|
456
|
+
"feishu": {
|
|
457
|
+
"enabled": false
|
|
458
|
+
},
|
|
459
|
+
"openclaw-extension-miaoda": {
|
|
460
|
+
"enabled": true,
|
|
461
|
+
"config": {
|
|
462
|
+
"greeting": {
|
|
463
|
+
"message": "👋 Hi,我是**$$__MIAODA_CLAW_NAME__**,一只生活在飞书里的 🦞 小龙虾,打个招呼,我们开始认识一下?",
|
|
464
|
+
"targets": [
|
|
465
|
+
"$$__FEISHU_OPEN_ID__"
|
|
466
|
+
]
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
},
|
|
470
|
+
"openclaw-lark": {
|
|
471
|
+
"enabled": true
|
|
472
|
+
},
|
|
473
|
+
"openclaw-extension-miaoda-coding": {
|
|
474
|
+
"enabled": true
|
|
475
|
+
},
|
|
476
|
+
"browser": {
|
|
477
|
+
"enabled": true
|
|
478
|
+
}
|
|
479
|
+
},
|
|
480
|
+
"installs": {
|
|
481
|
+
"openclaw-lark": {
|
|
482
|
+
"source": "npm",
|
|
483
|
+
"spec": "@lark-apaas/openclaw-lark",
|
|
484
|
+
"installPath": "./extensions/openclaw-lark",
|
|
485
|
+
"version": "2026.4.3",
|
|
486
|
+
"resolvedName": "@lark-apaas/openclaw-lark",
|
|
487
|
+
"resolvedVersion": "2026.4.3",
|
|
488
|
+
"resolvedSpec": "@lark-apaas/openclaw-lark@2026.4.3",
|
|
489
|
+
"integrity": "sha512-1eJ2WCvAYsnM9TPwPbEoD3nJtqNSOP2zOBV/3Vb9YQRg1kJJspEly5yCjiZt1wew4UhyN8Tcrp/XV78Qn747GA==",
|
|
490
|
+
"shasum": "e8d8cf05f8cb96cf5de4bca097c527eb9116e655",
|
|
491
|
+
"resolvedAt": "2026-04-03T06:27:44.706Z",
|
|
492
|
+
"installedAt": "2026-04-03T06:28:10.547Z"
|
|
493
|
+
},
|
|
494
|
+
"openclaw-extension-miaoda": {
|
|
495
|
+
"source": "npm",
|
|
496
|
+
"installPath": "./extensions/openclaw-extension-miaoda",
|
|
497
|
+
"version": "1.0.9",
|
|
498
|
+
"installedAt": "2026-04-11T09:27:06.639Z",
|
|
499
|
+
"spec": "@lark-apaas/openclaw-extension-miaoda@1.0.9",
|
|
500
|
+
"resolvedVersion": "1.0.9",
|
|
501
|
+
"resolvedName": "@lark-apaas/openclaw-extension-miaoda",
|
|
502
|
+
"resolvedSpec": "@lark-apaas/openclaw-extension-miaoda@1.0.9",
|
|
503
|
+
"resolvedAt": "2026-04-11T09:27:06.639Z",
|
|
504
|
+
"integrity": "sha512-McNeuPAUDLrMhT3yZuwk9A7pI262r2CK1N1KNQP6VuzymkDUjx2sTcJPCEBB3bFkdXd0yUU983/OhJiaJo+JWg==",
|
|
505
|
+
"shasum": "a3c75886e40b63f39a33a2660932f8afdae6a514"
|
|
506
|
+
},
|
|
507
|
+
"openclaw-extension-miaoda-coding": {
|
|
508
|
+
"source": "npm",
|
|
509
|
+
"spec": "@lark-apaas/openclaw-extension-miaoda-coding",
|
|
510
|
+
"installPath": "./extensions/openclaw-extension-miaoda-coding",
|
|
511
|
+
"version": "1.0.8",
|
|
512
|
+
"resolvedName": "@lark-apaas/openclaw-extension-miaoda-coding",
|
|
513
|
+
"resolvedVersion": "1.0.8",
|
|
514
|
+
"resolvedSpec": "@lark-apaas/openclaw-extension-miaoda-coding@1.0.8",
|
|
515
|
+
"integrity": "sha512-uxlLtgH2CTwz56UTaZD+n/x1p2a3Q01o3Og7oLUJCm6izWHXFEI1SQhNnCPggrfSam49KFir8xB64tY4T9dt2Q==",
|
|
516
|
+
"shasum": "058eadf5bc71ae87f79b5096b9d96f4afb89a9db",
|
|
517
|
+
"resolvedAt": "2026-04-09T11:33:36.208Z",
|
|
518
|
+
"installedAt": "2026-04-09T11:33:37.171Z"
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
log() { echo "[restart.sh] $(date '+%Y-%m-%d %H:%M:%S') $*"; }
|
|
4
|
+
|
|
5
|
+
gw_alive() {
|
|
6
|
+
pgrep -f "openclaw-gateway|openclaw gateway" | grep -vw "$$" >/dev/null 2>&1
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
if [ -d "/run/systemd/system/" ]; then
|
|
10
|
+
log "systemd detected, restarting via systemctl..."
|
|
11
|
+
sudo systemctl restart openclaw
|
|
12
|
+
log "systemctl restart exit code: $?"
|
|
13
|
+
else
|
|
14
|
+
log "killing openclaw-gateway processes..."
|
|
15
|
+
PIDS_GW=$(pgrep -f "openclaw-gateway|openclaw gateway" | grep -vw "$$" || true)
|
|
16
|
+
if [ -n "$PIDS_GW" ]; then
|
|
17
|
+
log "killing gateway pids: $(echo $PIDS_GW | tr '\n' ' ')"
|
|
18
|
+
kill -9 $PIDS_GW 2>&1
|
|
19
|
+
else
|
|
20
|
+
log "no openclaw-gateway processes found"
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
for i in $(seq 1 50); do
|
|
24
|
+
gw_alive || break
|
|
25
|
+
sleep 0.1
|
|
26
|
+
done
|
|
27
|
+
|
|
28
|
+
if gw_alive; then
|
|
29
|
+
log "ERROR: openclaw-gateway still alive after 5s, abort"
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
32
|
+
log "openclaw-gateway stopped"
|
|
33
|
+
|
|
34
|
+
log "starting openclaw gateway..."
|
|
35
|
+
nohup openclaw gateway run --port 18789 > /tmp/openclaw-gateway.log 2>&1 &
|
|
36
|
+
log "gateway started (pid=$!)"
|
|
37
|
+
fi
|