openclawsetup 2.1.2 → 2.1.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/README.md +10 -0
- package/bin/cli.mjs +144 -16
- package/package.json +1 -1
- package//344/275/277/347/224/250/350/257/264/346/230/216.md +6 -4
package/README.md
CHANGED
|
@@ -72,6 +72,7 @@ npx openclawsetup@latest --auto
|
|
|
72
72
|
| `--with-channel` | 检测到渠道配置时暂停自动选择 |
|
|
73
73
|
| `--update` | 检查并更新已安装的 OpenClaw |
|
|
74
74
|
| `--reinstall` | 卸载后重新安装(清除配置) |
|
|
75
|
+
| `--uninstall` | 卸载 OpenClaw |
|
|
75
76
|
| `--help, -h` | 显示帮助信息 |
|
|
76
77
|
|
|
77
78
|
## 使用示例
|
|
@@ -100,6 +101,9 @@ npx openclawsetup@latest --update
|
|
|
100
101
|
|
|
101
102
|
# 卸载后重新安装(会清除配置)
|
|
102
103
|
npx openclawsetup@latest --reinstall
|
|
104
|
+
|
|
105
|
+
# 直接卸载
|
|
106
|
+
npx openclawsetup@latest --uninstall
|
|
103
107
|
```
|
|
104
108
|
|
|
105
109
|
## 安装后
|
|
@@ -114,6 +118,12 @@ npx openclawapi@latest preset-claude
|
|
|
114
118
|
npx openclawapi@latest
|
|
115
119
|
```
|
|
116
120
|
|
|
121
|
+
## Dashboard 访问
|
|
122
|
+
|
|
123
|
+
安装完成后会自动显示:
|
|
124
|
+
- 本机访问地址(含 token)
|
|
125
|
+
- 云服务器场景下的 SSH 隧道命令与说明
|
|
126
|
+
|
|
117
127
|
## 配置聊天渠道
|
|
118
128
|
|
|
119
129
|
```bash
|
package/bin/cli.mjs
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { execSync, spawnSync } from 'child_process';
|
|
14
|
-
import { existsSync, accessSync, constants as fsConstants, rmSync } from 'fs';
|
|
14
|
+
import { existsSync, accessSync, constants as fsConstants, rmSync, readFileSync } from 'fs';
|
|
15
15
|
import { homedir, platform } from 'os';
|
|
16
16
|
import { join } from 'path';
|
|
17
17
|
import { createInterface } from 'readline';
|
|
@@ -51,6 +51,7 @@ function parseArgs() {
|
|
|
51
51
|
return {
|
|
52
52
|
update: args.includes('--update'),
|
|
53
53
|
reinstall: args.includes('--reinstall'),
|
|
54
|
+
uninstall: args.includes('--uninstall'),
|
|
54
55
|
manual: args.includes('--manual'),
|
|
55
56
|
auto: args.includes('--auto'),
|
|
56
57
|
withModel: args.includes('--with-model'),
|
|
@@ -67,6 +68,7 @@ ${colors.cyan('用法:')}
|
|
|
67
68
|
npx openclawsetup 带中文指引的安装
|
|
68
69
|
npx openclawsetup --update 更新已安装的 OpenClaw
|
|
69
70
|
npx openclawsetup --reinstall 卸载后重新安装
|
|
71
|
+
npx openclawsetup --uninstall 卸载 OpenClaw
|
|
70
72
|
npx openclawsetup --manual 完全手动模式
|
|
71
73
|
npx openclawsetup --auto 强制自动模式
|
|
72
74
|
|
|
@@ -139,6 +141,65 @@ function detectExistingInstall() {
|
|
|
139
141
|
return { installed: false };
|
|
140
142
|
}
|
|
141
143
|
|
|
144
|
+
function getConfigInfo() {
|
|
145
|
+
const home = homedir();
|
|
146
|
+
const configs = [
|
|
147
|
+
{ dir: join(home, '.openclaw'), file: 'openclaw.json' },
|
|
148
|
+
{ dir: join(home, '.clawdbot'), file: 'clawdbot.json' },
|
|
149
|
+
];
|
|
150
|
+
|
|
151
|
+
for (const cfg of configs) {
|
|
152
|
+
const configPath = join(cfg.dir, cfg.file);
|
|
153
|
+
if (!existsSync(configPath)) continue;
|
|
154
|
+
try {
|
|
155
|
+
const raw = readFileSync(configPath, 'utf8');
|
|
156
|
+
const json = JSON.parse(raw);
|
|
157
|
+
const token = json.token || json.gatewayToken || '';
|
|
158
|
+
const port = Number(json.port || json.gatewayPort || 18789);
|
|
159
|
+
const bind = json.bind || json.gatewayBind || '';
|
|
160
|
+
return { configDir: cfg.dir, configPath, token, port, bind, raw };
|
|
161
|
+
} catch {
|
|
162
|
+
try {
|
|
163
|
+
const raw = readFileSync(configPath, 'utf8');
|
|
164
|
+
const tokenMatch = raw.match(/"token"\\s*:\\s*"([^"]+)"/i);
|
|
165
|
+
const portMatch = raw.match(/"port"\\s*:\\s*(\\d+)/i);
|
|
166
|
+
const bindMatch = raw.match(/"bind"\\s*:\\s*"([^"]+)"/i);
|
|
167
|
+
return {
|
|
168
|
+
configDir: cfg.dir,
|
|
169
|
+
configPath,
|
|
170
|
+
token: tokenMatch ? tokenMatch[1] : '',
|
|
171
|
+
port: portMatch ? Number(portMatch[1]) : 18789,
|
|
172
|
+
bind: bindMatch ? bindMatch[1] : '',
|
|
173
|
+
raw,
|
|
174
|
+
};
|
|
175
|
+
} catch {
|
|
176
|
+
return { configDir: cfg.dir, configPath, token: '', port: 18789, bind: '', raw: '' };
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return { configDir: '', configPath: '', token: '', port: 18789, bind: '', raw: '' };
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function detectVps() {
|
|
184
|
+
return existsSync('/etc/cloud') || existsSync('/var/lib/cloud') || existsSync('/sys/hypervisor');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function getServerIp() {
|
|
188
|
+
const candidates = [
|
|
189
|
+
'curl -s --connect-timeout 2 ifconfig.me',
|
|
190
|
+
'curl -s --connect-timeout 2 icanhazip.com',
|
|
191
|
+
'curl -s --connect-timeout 2 ipinfo.io/ip',
|
|
192
|
+
"hostname -I 2>/dev/null | awk '{print $1}'",
|
|
193
|
+
];
|
|
194
|
+
for (const cmd of candidates) {
|
|
195
|
+
const result = safeExec(cmd);
|
|
196
|
+
if (result.ok && result.output) {
|
|
197
|
+
return result.output.trim();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return '';
|
|
201
|
+
}
|
|
202
|
+
|
|
142
203
|
// ============ 安装指引 ============
|
|
143
204
|
|
|
144
205
|
function showInstallGuide() {
|
|
@@ -676,6 +737,8 @@ function showCompletionInfo(cliName) {
|
|
|
676
737
|
console.log(colors.cyan('\n下一步 - 配置 AI 模型(必须):'));
|
|
677
738
|
console.log(` ${colors.yellow('npx openclawapi@latest preset-claude')}`);
|
|
678
739
|
|
|
740
|
+
showDashboardAccessInfo();
|
|
741
|
+
|
|
679
742
|
console.log(colors.cyan('\n常用命令:'));
|
|
680
743
|
console.log(` 查看状态: ${colors.yellow(`${cliName} status`)}`);
|
|
681
744
|
console.log(` 查看日志: ${colors.yellow(`${cliName} gateway logs`)}`);
|
|
@@ -689,6 +752,78 @@ function showCompletionInfo(cliName) {
|
|
|
689
752
|
console.log('');
|
|
690
753
|
}
|
|
691
754
|
|
|
755
|
+
function showDashboardAccessInfo() {
|
|
756
|
+
const config = getConfigInfo();
|
|
757
|
+
const port = config.port || 18789;
|
|
758
|
+
const token = config.token || '<你的token>';
|
|
759
|
+
const dashboardUrl = `http://127.0.0.1:${port}/?token=${token}`;
|
|
760
|
+
|
|
761
|
+
if (detectVps()) {
|
|
762
|
+
const serverIp = getServerIp() || '<服务器IP>';
|
|
763
|
+
const user = process.env.USER || 'root';
|
|
764
|
+
|
|
765
|
+
console.log(colors.cyan('\n📡 Dashboard 访问(云服务器):'));
|
|
766
|
+
console.log(colors.gray(' Gateway 默认绑定 127.0.0.1,外部无法直接访问(安全设计)'));
|
|
767
|
+
console.log('');
|
|
768
|
+
console.log(colors.yellow(' 方式一:SSH 隧道(推荐,安全)'));
|
|
769
|
+
console.log(colors.gray(' 在本地电脑执行以下命令,保持终端窗口打开:'));
|
|
770
|
+
console.log(` ${colors.green(`ssh -N -L ${port}:127.0.0.1:${port} ${user}@${serverIp}`)}`);
|
|
771
|
+
console.log(colors.gray(' 然后在本地浏览器访问:'));
|
|
772
|
+
console.log(` ${colors.green(dashboardUrl)}`);
|
|
773
|
+
console.log('');
|
|
774
|
+
console.log(colors.yellow(' 方式二:直接暴露端口(不推荐,有安全风险)'));
|
|
775
|
+
console.log(colors.gray(' 1. 修改配置文件 ~/.openclaw/openclaw.json'));
|
|
776
|
+
console.log(colors.gray(' 将 "bind": "loopback" 改为 "bind": "all"'));
|
|
777
|
+
console.log(colors.gray(` 2. 在云服务器控制台开放端口 ${port}`));
|
|
778
|
+
console.log(colors.gray(' 3. 重启 Gateway:openclaw gateway restart'));
|
|
779
|
+
console.log(colors.gray(` 4. 访问:http://${serverIp}:${port}/?token=...`));
|
|
780
|
+
} else {
|
|
781
|
+
console.log(colors.cyan('\nDashboard 访问:'));
|
|
782
|
+
console.log(` ${colors.yellow(dashboardUrl)}`);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
async function uninstallOpenClaw(existing) {
|
|
787
|
+
const cliName = existing?.name || 'openclaw';
|
|
788
|
+
const useSudo = needsSudo();
|
|
789
|
+
|
|
790
|
+
console.log(colors.cyan('\n开始卸载...'));
|
|
791
|
+
|
|
792
|
+
safeExec(`${cliName} gateway stop`);
|
|
793
|
+
|
|
794
|
+
if (useSudo) {
|
|
795
|
+
console.log(colors.yellow('\n请运行以下命令卸载:'));
|
|
796
|
+
console.log(colors.green(` sudo npm uninstall -g ${cliName}`));
|
|
797
|
+
console.log(colors.green(' rm -rf ~/.openclaw ~/.clawdbot\n'));
|
|
798
|
+
await waitForEnter('卸载完成后按回车继续...');
|
|
799
|
+
} else {
|
|
800
|
+
spawnSync('npm', ['uninstall', '-g', cliName], { stdio: 'inherit', shell: true });
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
const config = getConfigInfo();
|
|
804
|
+
if (config.configDir && existsSync(config.configDir)) {
|
|
805
|
+
rmSync(config.configDir, { recursive: true, force: true });
|
|
806
|
+
}
|
|
807
|
+
const otherDir = config.configDir?.endsWith('.openclaw') ? join(homedir(), '.clawdbot') : join(homedir(), '.openclaw');
|
|
808
|
+
if (existsSync(otherDir)) {
|
|
809
|
+
rmSync(otherDir, { recursive: true, force: true });
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
if (platform() === 'darwin') {
|
|
813
|
+
const plist = join(homedir(), 'Library/LaunchAgents/com.openclaw.gateway.plist');
|
|
814
|
+
safeExec(`launchctl unload "${plist}"`);
|
|
815
|
+
if (existsSync(plist)) rmSync(plist, { force: true });
|
|
816
|
+
} else if (platform() === 'linux') {
|
|
817
|
+
safeExec('systemctl --user stop openclaw');
|
|
818
|
+
safeExec('systemctl --user disable openclaw');
|
|
819
|
+
const service = join(homedir(), '.config/systemd/user/openclaw.service');
|
|
820
|
+
if (existsSync(service)) rmSync(service, { force: true });
|
|
821
|
+
safeExec('systemctl --user daemon-reload');
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
log.success('卸载完成');
|
|
825
|
+
}
|
|
826
|
+
|
|
692
827
|
// ============ 主函数 ============
|
|
693
828
|
|
|
694
829
|
async function main() {
|
|
@@ -716,27 +851,20 @@ async function main() {
|
|
|
716
851
|
process.exit(0);
|
|
717
852
|
}
|
|
718
853
|
|
|
854
|
+
if (options.uninstall) {
|
|
855
|
+
await uninstallOpenClaw(existing);
|
|
856
|
+
process.exit(0);
|
|
857
|
+
}
|
|
858
|
+
|
|
719
859
|
if (options.reinstall) {
|
|
720
|
-
|
|
721
|
-
safeExec(`${existing.name} gateway stop`);
|
|
722
|
-
|
|
723
|
-
if (needsSudo()) {
|
|
724
|
-
console.log(colors.yellow('\n请运行以下命令卸载:'));
|
|
725
|
-
console.log(colors.green(` sudo npm uninstall -g ${existing.name}`));
|
|
726
|
-
console.log(colors.green(` rm -rf ~/.openclaw ~/.clawdbot\n`));
|
|
727
|
-
await waitForEnter('卸载完成后按回车继续...');
|
|
728
|
-
} else {
|
|
729
|
-
spawnSync('npm', ['uninstall', '-g', existing.name], { stdio: 'inherit', shell: true });
|
|
730
|
-
if (existing.configDir && existsSync(existing.configDir)) {
|
|
731
|
-
rmSync(existing.configDir, { recursive: true, force: true });
|
|
732
|
-
}
|
|
733
|
-
log.success('卸载完成');
|
|
734
|
-
}
|
|
860
|
+
await uninstallOpenClaw(existing);
|
|
735
861
|
} else {
|
|
736
862
|
console.log(colors.cyan('\n已安装,可选操作:'));
|
|
737
863
|
console.log(` 更新: ${colors.yellow('npx openclawsetup --update')}`);
|
|
738
864
|
console.log(` 重装: ${colors.yellow('npx openclawsetup --reinstall')}`);
|
|
865
|
+
console.log(` 卸载: ${colors.yellow('npx openclawsetup --uninstall')}`);
|
|
739
866
|
console.log(` 配置模型: ${colors.yellow('npx openclawapi@latest preset-claude')}`);
|
|
867
|
+
showDashboardAccessInfo();
|
|
740
868
|
console.log('');
|
|
741
869
|
process.exit(0);
|
|
742
870
|
}
|
package/package.json
CHANGED
|
@@ -74,6 +74,9 @@ npx openclawsetup@latest --update
|
|
|
74
74
|
|
|
75
75
|
# 卸载后重新安装(会清除配置)
|
|
76
76
|
npx openclawsetup@latest --reinstall
|
|
77
|
+
|
|
78
|
+
# 直接卸载
|
|
79
|
+
npx openclawsetup@latest --uninstall
|
|
77
80
|
```
|
|
78
81
|
|
|
79
82
|
## 安装完成后
|
|
@@ -84,10 +87,9 @@ npx openclawsetup@latest --reinstall
|
|
|
84
87
|
```
|
|
85
88
|
|
|
86
89
|
2. **访问 Dashboard**
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
Token 在安装完成时会显示。
|
|
90
|
+
安装完成后会自动显示:
|
|
91
|
+
- 本机访问地址(含 token)
|
|
92
|
+
- 云服务器场景下的 SSH 隧道命令与说明
|
|
91
93
|
|
|
92
94
|
3. **配置聊天渠道(可选)**
|
|
93
95
|
```bash
|