openclawsetup 2.4.3 → 2.4.5
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/bin/cli.mjs +126 -19
- package/package.json +1 -1
package/bin/cli.mjs
CHANGED
|
@@ -200,9 +200,9 @@ function getConfigInfo() {
|
|
|
200
200
|
try {
|
|
201
201
|
const raw = readFileSync(configPath, 'utf8');
|
|
202
202
|
const json = JSON.parse(raw);
|
|
203
|
-
const token = json.token || json.gatewayToken || '';
|
|
204
|
-
const port = Number(json.port || json.gatewayPort || 18789);
|
|
205
|
-
const bind = json.bind || json.gatewayBind || '';
|
|
203
|
+
const token = json.gateway?.auth?.token || json.token || json.gatewayToken || '';
|
|
204
|
+
const port = Number(json.gateway?.port || json.port || json.gatewayPort || 18789);
|
|
205
|
+
const bind = json.gateway?.bind || json.bind || json.gatewayBind || '';
|
|
206
206
|
return { configDir: cfg.dir, configPath, token, port, bind, raw };
|
|
207
207
|
} catch {
|
|
208
208
|
try {
|
|
@@ -227,7 +227,17 @@ function getConfigInfo() {
|
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
function detectVps() {
|
|
230
|
-
|
|
230
|
+
if (platform() !== 'linux') return false;
|
|
231
|
+
// Cloud provider markers
|
|
232
|
+
if (existsSync('/etc/cloud') || existsSync('/var/lib/cloud') || existsSync('/sys/hypervisor')) return true;
|
|
233
|
+
// SSH session = remote server
|
|
234
|
+
if (process.env.SSH_CLIENT || process.env.SSH_TTY || process.env.SSH_CONNECTION) return true;
|
|
235
|
+
// systemd-detect-virt
|
|
236
|
+
const virt = safeExec('systemd-detect-virt 2>/dev/null');
|
|
237
|
+
if (virt.ok && virt.output.trim() && virt.output.trim() !== 'none') return true;
|
|
238
|
+
// Headless Linux (no display) likely a server
|
|
239
|
+
if (!process.env.DISPLAY && !process.env.WAYLAND_DISPLAY) return true;
|
|
240
|
+
return false;
|
|
231
241
|
}
|
|
232
242
|
|
|
233
243
|
function getServerIp() {
|
|
@@ -1168,6 +1178,98 @@ async function runHealthCheck(cliName, autoFix = false) {
|
|
|
1168
1178
|
|
|
1169
1179
|
// ============ 交互式菜单 ============
|
|
1170
1180
|
|
|
1181
|
+
async function showStatusInfo(cliName) {
|
|
1182
|
+
const config = getConfigInfo();
|
|
1183
|
+
const port = config.port || 18789;
|
|
1184
|
+
const token = config.token || '<未配置>';
|
|
1185
|
+
const dashboardUrl = `http://127.0.0.1:${port}/?token=${token}`;
|
|
1186
|
+
|
|
1187
|
+
console.log(colors.bold(colors.cyan('\n📊 OpenClaw 状态信息\n')));
|
|
1188
|
+
|
|
1189
|
+
// 服务状态
|
|
1190
|
+
const statusResult = safeExec(`${cliName} status`);
|
|
1191
|
+
const output = statusResult.ok ? statusResult.output : '';
|
|
1192
|
+
const isRunning = output.toLowerCase().includes('running') || output.toLowerCase().includes('active');
|
|
1193
|
+
|
|
1194
|
+
if (isRunning) {
|
|
1195
|
+
console.log(colors.green(' ✓ Gateway 服务正在运行'));
|
|
1196
|
+
} else {
|
|
1197
|
+
console.log(colors.red(' ✗ Gateway 服务未运行'));
|
|
1198
|
+
console.log(colors.yellow(' → 请先选择「检查修复」自动修复此问题\n'));
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
// 端口检查
|
|
1203
|
+
const portCmd = platform() === 'win32'
|
|
1204
|
+
? `netstat -an | findstr :${port}`
|
|
1205
|
+
: `lsof -i :${port} 2>/dev/null || netstat -tlnp 2>/dev/null | grep :${port}`;
|
|
1206
|
+
const portResult = safeExec(portCmd);
|
|
1207
|
+
if (portResult.ok && portResult.output) {
|
|
1208
|
+
console.log(colors.green(` ✓ 端口 ${port} 正在监听`));
|
|
1209
|
+
} else {
|
|
1210
|
+
console.log(colors.red(` ✗ 端口 ${port} 未监听`));
|
|
1211
|
+
console.log(colors.yellow(' → 请先选择「检查修复」自动修复此问题\n'));
|
|
1212
|
+
return;
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
// 模型配置
|
|
1216
|
+
if (config.raw) {
|
|
1217
|
+
const hasProviders = config.raw.includes('"providers"');
|
|
1218
|
+
if (hasProviders) {
|
|
1219
|
+
console.log(colors.green(' ✓ 已配置 AI 模型'));
|
|
1220
|
+
} else {
|
|
1221
|
+
console.log(colors.yellow(' ⚠ 未配置模型,请先选择「配置模型」'));
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
// Dashboard 访问指南
|
|
1226
|
+
console.log(colors.bold(colors.cyan('\n' + '─'.repeat(46))));
|
|
1227
|
+
console.log(colors.bold(colors.cyan(' 🌐 Web Dashboard 访问方法')));
|
|
1228
|
+
console.log(colors.bold(colors.cyan('─'.repeat(46))));
|
|
1229
|
+
|
|
1230
|
+
if (detectVps()) {
|
|
1231
|
+
const serverIp = getServerIp() || '<服务器IP>';
|
|
1232
|
+
const user = process.env.USER || 'root';
|
|
1233
|
+
|
|
1234
|
+
console.log(colors.gray('\n Gateway 绑定在 127.0.0.1(安全设计),需要通过'));
|
|
1235
|
+
console.log(colors.gray(' SSH 隧道从本地电脑访问。\n'));
|
|
1236
|
+
|
|
1237
|
+
console.log(colors.bold(' 第 1 步:在本地电脑打开终端,执行:\n'));
|
|
1238
|
+
|
|
1239
|
+
console.log(colors.yellow(' macOS / Linux:'));
|
|
1240
|
+
console.log(colors.green(` ssh -N -L ${port}:127.0.0.1:${port} ${user}@${serverIp}`));
|
|
1241
|
+
console.log('');
|
|
1242
|
+
console.log(colors.yellow(' Windows PowerShell:'));
|
|
1243
|
+
console.log(colors.green(` ssh -N -L ${port}:127.0.0.1:${port} ${user}@${serverIp}`));
|
|
1244
|
+
console.log('');
|
|
1245
|
+
console.log(colors.gray(' 保持这个终端窗口不要关闭。'));
|
|
1246
|
+
|
|
1247
|
+
console.log(colors.bold('\n 第 2 步:在本地浏览器打开:\n'));
|
|
1248
|
+
console.log(colors.green(` ${dashboardUrl}`));
|
|
1249
|
+
|
|
1250
|
+
console.log(colors.bold('\n 注意事项:'));
|
|
1251
|
+
console.log(colors.gray(' • SSH 窗口关闭后 Dashboard 无法访问,需重新执行第 1 步'));
|
|
1252
|
+
console.log(colors.gray(' • 如果连接断开,重新执行 SSH 命令即可'));
|
|
1253
|
+
console.log(colors.gray(' • 不建议将端口直接暴露到公网'));
|
|
1254
|
+
} else if (platform() === 'win32') {
|
|
1255
|
+
console.log(colors.gray('\n OpenClaw 运行在本机,直接用浏览器访问即可。\n'));
|
|
1256
|
+
console.log(colors.bold(' 在浏览器打开:\n'));
|
|
1257
|
+
console.log(colors.green(` ${dashboardUrl}`));
|
|
1258
|
+
console.log(colors.bold('\n 注意事项:'));
|
|
1259
|
+
console.log(colors.gray(' • 确保 Gateway 服务正在运行'));
|
|
1260
|
+
console.log(colors.gray(' • 如果无法访问,选择「检查修复」排查问题'));
|
|
1261
|
+
} else {
|
|
1262
|
+
console.log(colors.gray('\n OpenClaw 运行在本机,直接用浏览器访问即可。\n'));
|
|
1263
|
+
console.log(colors.bold(' 在浏览器打开:\n'));
|
|
1264
|
+
console.log(colors.green(` ${dashboardUrl}`));
|
|
1265
|
+
console.log(colors.bold('\n 注意事项:'));
|
|
1266
|
+
console.log(colors.gray(' • 确保 Gateway 服务正在运行'));
|
|
1267
|
+
console.log(colors.gray(' • 如果无法访问,选择「检查修复」排查问题'));
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
console.log('');
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1171
1273
|
async function showInteractiveMenu(existing) {
|
|
1172
1274
|
const cliName = existing.name || 'openclaw';
|
|
1173
1275
|
|
|
@@ -1179,27 +1281,32 @@ async function showInteractiveMenu(existing) {
|
|
|
1179
1281
|
showDashboardAccessInfo();
|
|
1180
1282
|
|
|
1181
1283
|
console.log(colors.cyan('\n请选择操作:'));
|
|
1182
|
-
console.log(` ${colors.yellow('1')}.
|
|
1183
|
-
console.log(` ${colors.yellow('2')}.
|
|
1184
|
-
console.log(` ${colors.yellow('3')}.
|
|
1185
|
-
console.log(` ${colors.yellow('4')}.
|
|
1186
|
-
console.log(` ${colors.yellow('5')}.
|
|
1187
|
-
console.log(` ${colors.yellow('6')}.
|
|
1188
|
-
console.log(` ${colors.yellow('7')}.
|
|
1284
|
+
console.log(` ${colors.yellow('1')}. 状态信息`);
|
|
1285
|
+
console.log(` ${colors.yellow('2')}. 检查修复`);
|
|
1286
|
+
console.log(` ${colors.yellow('3')}. 检查更新`);
|
|
1287
|
+
console.log(` ${colors.yellow('4')}. 配置模型`);
|
|
1288
|
+
console.log(` ${colors.yellow('5')}. 配置 Chat`);
|
|
1289
|
+
console.log(` ${colors.yellow('6')}. 配置技能`);
|
|
1290
|
+
console.log(` ${colors.yellow('7')}. 重新安装`);
|
|
1291
|
+
console.log(` ${colors.yellow('8')}. 完全卸载`);
|
|
1189
1292
|
console.log(` ${colors.yellow('0')}. 退出`);
|
|
1190
1293
|
|
|
1191
|
-
const choice = await askQuestion('\n请输入选项 (0-
|
|
1294
|
+
const choice = await askQuestion('\n请输入选项 (0-8): ');
|
|
1192
1295
|
|
|
1193
1296
|
switch (choice.trim()) {
|
|
1194
1297
|
case '1':
|
|
1195
|
-
await
|
|
1298
|
+
await showStatusInfo(cliName);
|
|
1196
1299
|
await waitForEnter('\n按回车返回菜单...');
|
|
1197
1300
|
break;
|
|
1198
1301
|
case '2':
|
|
1199
|
-
await
|
|
1302
|
+
await runHealthCheck(cliName, true);
|
|
1200
1303
|
await waitForEnter('\n按回车返回菜单...');
|
|
1201
1304
|
break;
|
|
1202
1305
|
case '3':
|
|
1306
|
+
await updateOpenClaw(cliName);
|
|
1307
|
+
await waitForEnter('\n按回车返回菜单...');
|
|
1308
|
+
break;
|
|
1309
|
+
case '4':
|
|
1203
1310
|
console.log(colors.cyan('\n启动模型配置...'));
|
|
1204
1311
|
spawnSync('npx', ['openclawapi@latest'], {
|
|
1205
1312
|
stdio: 'inherit',
|
|
@@ -1207,7 +1314,7 @@ async function showInteractiveMenu(existing) {
|
|
|
1207
1314
|
});
|
|
1208
1315
|
await waitForEnter('\n按回车返回菜单...');
|
|
1209
1316
|
break;
|
|
1210
|
-
case '
|
|
1317
|
+
case '5':
|
|
1211
1318
|
console.log(colors.cyan('\n选择聊天渠道:'));
|
|
1212
1319
|
console.log(` ${colors.yellow('a')}. Discord`);
|
|
1213
1320
|
console.log(` ${colors.yellow('b')}. 飞书`);
|
|
@@ -1227,13 +1334,13 @@ async function showInteractiveMenu(existing) {
|
|
|
1227
1334
|
}
|
|
1228
1335
|
await waitForEnter('\n按回车返回菜单...');
|
|
1229
1336
|
break;
|
|
1230
|
-
case '
|
|
1337
|
+
case '6':
|
|
1231
1338
|
console.log(colors.cyan('\n配置技能(即将支持)...'));
|
|
1232
1339
|
// TODO: 等待技能地址提供后实现
|
|
1233
1340
|
log.warn('技能配置功能即将上线,请稍后再试');
|
|
1234
1341
|
await waitForEnter('\n按回车返回菜单...');
|
|
1235
1342
|
break;
|
|
1236
|
-
case '
|
|
1343
|
+
case '7':
|
|
1237
1344
|
console.log(colors.yellow('\n即将重新安装 OpenClaw...'));
|
|
1238
1345
|
const confirmReinstall = await askQuestion('确认重新安装?(y/N): ');
|
|
1239
1346
|
if (confirmReinstall.toLowerCase() === 'y') {
|
|
@@ -1243,7 +1350,7 @@ async function showInteractiveMenu(existing) {
|
|
|
1243
1350
|
showCompletionInfo(newCliName);
|
|
1244
1351
|
}
|
|
1245
1352
|
break;
|
|
1246
|
-
case '
|
|
1353
|
+
case '8':
|
|
1247
1354
|
console.log(colors.red('\n⚠ 警告:卸载将删除所有配置!'));
|
|
1248
1355
|
const confirmUninstall = await askQuestion('确认卸载?(y/N): ');
|
|
1249
1356
|
if (confirmUninstall.toLowerCase() === 'y') {
|
|
@@ -1257,7 +1364,7 @@ async function showInteractiveMenu(existing) {
|
|
|
1257
1364
|
console.log(colors.gray('\n再见!'));
|
|
1258
1365
|
process.exit(0);
|
|
1259
1366
|
default:
|
|
1260
|
-
log.warn('无效选项,请输入 0-
|
|
1367
|
+
log.warn('无效选项,请输入 0-8');
|
|
1261
1368
|
}
|
|
1262
1369
|
}
|
|
1263
1370
|
}
|