openclawsetup 2.8.11 → 2.8.13
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 +97 -16
- package/package.json +1 -1
package/bin/cli.mjs
CHANGED
|
@@ -208,6 +208,28 @@ function safeFileRead(path) {
|
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
+
function sanitizeAuthProfiles(raw) {
|
|
212
|
+
try {
|
|
213
|
+
const obj = JSON.parse(raw);
|
|
214
|
+
const redact = (o) => {
|
|
215
|
+
if (!o || typeof o !== 'object') return o;
|
|
216
|
+
const copy = Array.isArray(o) ? [...o] : { ...o };
|
|
217
|
+
for (const k of Object.keys(copy)) {
|
|
218
|
+
if (/^(key|token|access|refresh|apiKey)$/i.test(k) && typeof copy[k] === 'string') {
|
|
219
|
+
const v = copy[k];
|
|
220
|
+
copy[k] = v.length > 8 ? `${v.slice(0, 4)}...${v.slice(-4)}` : '<REDACTED>';
|
|
221
|
+
} else if (typeof copy[k] === 'object') {
|
|
222
|
+
copy[k] = redact(copy[k]);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return copy;
|
|
226
|
+
};
|
|
227
|
+
return JSON.stringify(redact(obj), null, 2);
|
|
228
|
+
} catch {
|
|
229
|
+
return sanitizeText(raw);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
211
233
|
function runCmdCapture(cmd, timeout = 20000) {
|
|
212
234
|
const result = safeExec(cmd, { timeout });
|
|
213
235
|
if (result.ok) {
|
|
@@ -499,12 +521,12 @@ async function collectEvidencePackage(options = {}) {
|
|
|
499
521
|
|
|
500
522
|
const snapshot = gatherEnvironmentSnapshot();
|
|
501
523
|
const tokenOptimizationPreview = createTokenOptimizationPlan();
|
|
502
|
-
const cliName = snapshot.openclaw.detectedInstall?.name || findWorkingCliName() || 'openclaw';
|
|
524
|
+
const cliName = snapshot.openclaw.detectedInstall?.name || findWorkingCliName(snapshot.openclaw.configDir?.includes('.clawdbot') ? 'clawdbot' : undefined) || 'openclaw';
|
|
503
525
|
|
|
504
526
|
const captures = {
|
|
505
527
|
doctor: runCmdCapture(`${cliName} doctor`, quick ? 20000 : 90000),
|
|
506
528
|
status: runCmdCapture(`${cliName} status`, 20000),
|
|
507
|
-
gatewayLogs: runCmdCapture(`${cliName}
|
|
529
|
+
gatewayLogs: runCmdCapture(`${cliName} logs --lines 80`, quick ? 20000 : 45000),
|
|
508
530
|
cliVersion: runCmdCapture(`${cliName} --version`, 15000),
|
|
509
531
|
npmListGlobalOpenclaw: runCmdCapture('npm ls -g openclaw --depth=0', 20000),
|
|
510
532
|
npmListGlobalClawdbot: runCmdCapture('npm ls -g clawdbot --depth=0', 20000),
|
|
@@ -528,16 +550,56 @@ async function collectEvidencePackage(options = {}) {
|
|
|
528
550
|
const configRaw = safeFileRead(snapshot.openclaw.configPath);
|
|
529
551
|
const safeConfigPreview = sanitizeText(truncateText(configRaw, 20000));
|
|
530
552
|
|
|
553
|
+
// Capture auth-profiles.json (critical for 401 debugging)
|
|
554
|
+
const configDir = snapshot.openclaw.configDir || '';
|
|
555
|
+
const authProfilesCandidates = configDir ? [
|
|
556
|
+
join(configDir, 'agents', 'main', 'agent', 'auth-profiles.json'),
|
|
557
|
+
join(configDir, 'agent', 'auth-profiles.json'),
|
|
558
|
+
] : [];
|
|
559
|
+
let authProfilesPath = '';
|
|
560
|
+
let authProfilesRaw = '';
|
|
561
|
+
for (const candidate of authProfilesCandidates) {
|
|
562
|
+
const content = safeFileRead(candidate);
|
|
563
|
+
if (content) {
|
|
564
|
+
authProfilesPath = candidate;
|
|
565
|
+
authProfilesRaw = content;
|
|
566
|
+
break;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
// Redact key values but preserve structure for debugging
|
|
570
|
+
const safeAuthProfiles = authProfilesRaw ? sanitizeAuthProfiles(authProfilesRaw) : '';
|
|
571
|
+
|
|
572
|
+
// Try to read Gateway log file directly
|
|
573
|
+
const logFileCandidates = configDir ? [
|
|
574
|
+
join(configDir, 'gateway.log'),
|
|
575
|
+
join(configDir, 'logs', 'gateway.log'),
|
|
576
|
+
join(configDir, 'agents', 'main', 'agent', 'gateway.log'),
|
|
577
|
+
] : [];
|
|
578
|
+
let gatewayLogContent = '';
|
|
579
|
+
for (const candidate of logFileCandidates) {
|
|
580
|
+
const content = safeFileRead(candidate);
|
|
581
|
+
if (content) {
|
|
582
|
+
// Take last 5000 chars
|
|
583
|
+
gatewayLogContent = sanitizeText(content.length > 5000 ? content.slice(-5000) : content);
|
|
584
|
+
break;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
531
588
|
const summary = {
|
|
532
589
|
meta: {
|
|
533
590
|
generatedAt: new Date().toISOString(),
|
|
534
591
|
durationMs: Date.now() - startedAt,
|
|
535
592
|
quick,
|
|
536
|
-
evidenceVersion: '1.
|
|
593
|
+
evidenceVersion: '1.1.0',
|
|
537
594
|
},
|
|
538
595
|
snapshot,
|
|
539
596
|
tokenOptimizationPreview,
|
|
540
597
|
captures,
|
|
598
|
+
authProfiles: {
|
|
599
|
+
path: authProfilesPath || '(not found)',
|
|
600
|
+
content: safeAuthProfiles || '(empty or missing)',
|
|
601
|
+
},
|
|
602
|
+
gatewayLogFile: gatewayLogContent || '(not found)',
|
|
541
603
|
strongCheck: strongCheckResult
|
|
542
604
|
? {
|
|
543
605
|
issuesCount: strongCheckResult.issues?.length || 0,
|
|
@@ -550,6 +612,9 @@ async function collectEvidencePackage(options = {}) {
|
|
|
550
612
|
|
|
551
613
|
writeFileSync(join(evidenceDir, 'summary.json'), `${JSON.stringify(summary, null, 2)}\n`, 'utf8');
|
|
552
614
|
writeFileSync(join(evidenceDir, 'config.preview.json.txt'), `${safeConfigPreview || '<empty>'}\n`, 'utf8');
|
|
615
|
+
if (safeAuthProfiles) {
|
|
616
|
+
writeFileSync(join(evidenceDir, 'auth-profiles.preview.json.txt'), `${safeAuthProfiles}\n`, 'utf8');
|
|
617
|
+
}
|
|
553
618
|
|
|
554
619
|
const readme = [
|
|
555
620
|
'# OpenClaw 排障证据包',
|
|
@@ -561,6 +626,7 @@ async function collectEvidencePackage(options = {}) {
|
|
|
561
626
|
'## 文件说明',
|
|
562
627
|
'- summary.json: 机器可解析的完整诊断结果(已脱敏)',
|
|
563
628
|
'- config.preview.json.txt: 配置文件预览(已脱敏)',
|
|
629
|
+
'- auth-profiles.preview.json.txt: 认证配置预览(已脱敏,如存在)',
|
|
564
630
|
'',
|
|
565
631
|
'## 发给技术支持',
|
|
566
632
|
'请把整个证据包文件夹(或 zip)发给技术支持即可。',
|
|
@@ -631,9 +697,9 @@ ${colors.cyan('安装后配置模型:')}
|
|
|
631
697
|
npx openclawapi@latest # 交互式配置
|
|
632
698
|
|
|
633
699
|
${colors.cyan('常见问题快速修复:')}
|
|
634
|
-
Gateway 未启动: openclaw gateway start
|
|
700
|
+
Gateway 未启动: openclaw gateway start (或 clawdbot gateway start)
|
|
635
701
|
端口被占用: openclaw config set gateway.port 18790
|
|
636
|
-
配置文件损坏:
|
|
702
|
+
配置文件损坏: 重新运行 npx openclawsetup@latest
|
|
637
703
|
`);
|
|
638
704
|
}
|
|
639
705
|
|
|
@@ -730,8 +796,17 @@ function isRealGatewayCli(name) {
|
|
|
730
796
|
return true;
|
|
731
797
|
}
|
|
732
798
|
|
|
733
|
-
function findWorkingCliName() {
|
|
734
|
-
|
|
799
|
+
function findWorkingCliName(preferredName) {
|
|
800
|
+
const candidates = ['openclaw', 'clawdbot', 'moltbot'];
|
|
801
|
+
// If a preferred name is given (e.g. matching the config dir), check it first
|
|
802
|
+
if (preferredName) {
|
|
803
|
+
const reordered = [preferredName, ...candidates.filter(n => n !== preferredName)];
|
|
804
|
+
for (const name of reordered) {
|
|
805
|
+
if (isRealGatewayCli(name)) return name;
|
|
806
|
+
}
|
|
807
|
+
return null;
|
|
808
|
+
}
|
|
809
|
+
for (const name of candidates) {
|
|
735
810
|
if (isRealGatewayCli(name)) return name;
|
|
736
811
|
}
|
|
737
812
|
return null;
|
|
@@ -743,13 +818,17 @@ function detectExistingInstall() {
|
|
|
743
818
|
const clawdbotDir = join(home, '.clawdbot');
|
|
744
819
|
|
|
745
820
|
if (existsSync(openclawDir) || existsSync(clawdbotDir)) {
|
|
821
|
+
// Prefer the CLI that matches the config directory to avoid cross-config issues
|
|
822
|
+
// e.g. if config is in ~/.clawdbot, prefer 'clawdbot' CLI (reads ~/.clawdbot/clawdbot.json)
|
|
823
|
+
// if config is in ~/.openclaw, prefer 'openclaw' CLI (reads ~/.openclaw/openclaw.json)
|
|
746
824
|
const configDir = existsSync(openclawDir) ? openclawDir : clawdbotDir;
|
|
747
|
-
const
|
|
825
|
+
const preferredCli = existsSync(openclawDir) ? 'openclaw' : 'clawdbot';
|
|
826
|
+
const cliName = findWorkingCliName(preferredCli);
|
|
748
827
|
if (cliName) {
|
|
749
828
|
return { installed: true, configDir, name: cliName };
|
|
750
829
|
}
|
|
751
830
|
// Config dir exists but no working CLI found
|
|
752
|
-
return { installed: true, configDir, name:
|
|
831
|
+
return { installed: true, configDir, name: preferredCli, cliMissing: true };
|
|
753
832
|
}
|
|
754
833
|
|
|
755
834
|
const cliName = findWorkingCliName();
|
|
@@ -1630,7 +1709,7 @@ function showInstallGuide() {
|
|
|
1630
1709
|
console.log(colors.bold(colors.cyan(' 📖 OpenClaw 安装指引')));
|
|
1631
1710
|
console.log(colors.bold(colors.cyan('='.repeat(60))));
|
|
1632
1711
|
|
|
1633
|
-
console.log(colors.yellow('\n接下来会运行官方
|
|
1712
|
+
console.log(colors.yellow('\n接下来会运行官方 onboard 命令'));
|
|
1634
1713
|
console.log(colors.yellow('自动模式会按以下推荐选择(可随时接管):\n'));
|
|
1635
1714
|
|
|
1636
1715
|
console.log(colors.cyan('┌─────────────────────────────────────────────────────────┐'));
|
|
@@ -1844,7 +1923,7 @@ async function runOnboard(cliName) {
|
|
|
1844
1923
|
console.log(colors.bold(colors.cyan('\n[2/2] 运行配置向导\n')));
|
|
1845
1924
|
|
|
1846
1925
|
console.log(colors.gray('-'.repeat(60)));
|
|
1847
|
-
console.log(colors.gray('以下是官方
|
|
1926
|
+
console.log(colors.gray('以下是官方 onboard 界面:'));
|
|
1848
1927
|
console.log(colors.gray('-'.repeat(60) + '\n'));
|
|
1849
1928
|
|
|
1850
1929
|
const manualResult = runOnboardManual(cliName);
|
|
@@ -2203,7 +2282,7 @@ function showCompletionInfo(cliName) {
|
|
|
2203
2282
|
console.log(colors.cyan('\n下一步 - 配置 AI 模型(必须):'));
|
|
2204
2283
|
console.log(` ${colors.yellow('npx openclawapi@latest preset-claude')}`);
|
|
2205
2284
|
|
|
2206
|
-
showDashboardAccessInfo();
|
|
2285
|
+
showDashboardAccessInfo(cliName);
|
|
2207
2286
|
|
|
2208
2287
|
console.log(colors.cyan('\n常用命令:'));
|
|
2209
2288
|
console.log(` 查看状态: ${colors.yellow(`${cliName} status`)}`);
|
|
@@ -2218,12 +2297,14 @@ function showCompletionInfo(cliName) {
|
|
|
2218
2297
|
console.log('');
|
|
2219
2298
|
}
|
|
2220
2299
|
|
|
2221
|
-
function showDashboardAccessInfo() {
|
|
2300
|
+
function showDashboardAccessInfo(cliName) {
|
|
2222
2301
|
const config = getConfigInfo();
|
|
2223
2302
|
const port = config.port || 18789;
|
|
2224
2303
|
const tokenRaw = getDashboardToken(config) || '<你的token>';
|
|
2225
2304
|
const tokenMasked = maskToken(tokenRaw);
|
|
2226
2305
|
const dashboardUrl = `http://127.0.0.1:${port}/?token=${tokenMasked}`;
|
|
2306
|
+
const activeCli = cliName || (config.configPath?.includes('.clawdbot') ? 'clawdbot' : 'openclaw');
|
|
2307
|
+
const configFileName = config.configPath || `~/.${activeCli}/${activeCli}.json`;
|
|
2227
2308
|
|
|
2228
2309
|
if (detectVps()) {
|
|
2229
2310
|
const serverIp = getServerIp() || '<服务器IP>';
|
|
@@ -2239,10 +2320,10 @@ function showDashboardAccessInfo() {
|
|
|
2239
2320
|
console.log(` ${colors.green(dashboardUrl)}`);
|
|
2240
2321
|
console.log('');
|
|
2241
2322
|
console.log(colors.yellow(' 方式二:直接暴露端口(不推荐,有安全风险)'));
|
|
2242
|
-
console.log(colors.gray(
|
|
2323
|
+
console.log(colors.gray(` 1. 修改配置文件 ${configFileName}`));
|
|
2243
2324
|
console.log(colors.gray(' 将 "bind": "loopback" 改为 "bind": "all"'));
|
|
2244
2325
|
console.log(colors.gray(` 2. 在云服务器控制台开放端口 ${port}`));
|
|
2245
|
-
console.log(colors.gray(
|
|
2326
|
+
console.log(colors.gray(` 3. 重启 Gateway:${activeCli} gateway restart`));
|
|
2246
2327
|
console.log(colors.gray(` 4. 访问:http://${serverIp}:${port}/?token=...`));
|
|
2247
2328
|
} else {
|
|
2248
2329
|
console.log(colors.cyan('\nDashboard 访问:'));
|
|
@@ -2894,7 +2975,7 @@ async function showInteractiveMenu(existing) {
|
|
|
2894
2975
|
console.log(colors.bold(colors.cyan(' 🦞 OpenClaw 管理菜单')));
|
|
2895
2976
|
console.log(colors.bold(colors.cyan('='.repeat(50))));
|
|
2896
2977
|
|
|
2897
|
-
showDashboardAccessInfo();
|
|
2978
|
+
showDashboardAccessInfo(cliName);
|
|
2898
2979
|
|
|
2899
2980
|
console.log(colors.cyan('\n请选择操作:'));
|
|
2900
2981
|
console.log(` ${colors.yellow('1')}. 状态信息`);
|