openclaw-vchat-plugin 0.0.1 → 0.0.2
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/openclaw-vchat.js +135 -16
- package/package.json +1 -1
package/bin/openclaw-vchat.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const path = require('path');
|
|
4
|
-
const { spawnSync } = require('child_process');
|
|
4
|
+
const { spawnSync, spawn } = require('child_process');
|
|
5
5
|
|
|
6
6
|
const packageRoot = path.resolve(__dirname, '..');
|
|
7
7
|
const distEntry = path.join(packageRoot, 'dist', 'index.js');
|
|
@@ -12,7 +12,8 @@ function printUsage() {
|
|
|
12
12
|
|
|
13
13
|
Usage:
|
|
14
14
|
openclaw-vchat start
|
|
15
|
-
openclaw-vchat install [--pm2]
|
|
15
|
+
openclaw-vchat install [--pm2] [--startup]
|
|
16
|
+
openclaw-vchat pair
|
|
16
17
|
openclaw-vchat doctor
|
|
17
18
|
openclaw-vchat version
|
|
18
19
|
`);
|
|
@@ -23,6 +24,68 @@ function hasCommand(cmd) {
|
|
|
23
24
|
return res.status === 0;
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
function getOpenClawHome() {
|
|
28
|
+
const home = process.env.HOME || process.env.USERPROFILE || '';
|
|
29
|
+
return process.env.OPENCLAW_HOME || path.join(home, '.openclaw');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getDeviceConfigPath() {
|
|
33
|
+
return path.join(getOpenClawHome(), 'wechat-device.json');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function hasDeviceConfig() {
|
|
37
|
+
return fs.existsSync(getDeviceConfigPath());
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function sleep(ms) {
|
|
41
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function waitForPairingViaPm2Logs(name, timeoutMs) {
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
const child = spawn('pm2', ['logs', name, '--lines', '80'], {
|
|
47
|
+
stdio: 'inherit',
|
|
48
|
+
env: process.env,
|
|
49
|
+
cwd: packageRoot,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
let settled = false;
|
|
53
|
+
const finish = (err) => {
|
|
54
|
+
if (settled) return;
|
|
55
|
+
settled = true;
|
|
56
|
+
clearInterval(checkTimer);
|
|
57
|
+
clearTimeout(timeoutTimer);
|
|
58
|
+
if (!child.killed) {
|
|
59
|
+
try {
|
|
60
|
+
child.kill('SIGINT');
|
|
61
|
+
} catch (_) {}
|
|
62
|
+
}
|
|
63
|
+
if (err) reject(err);
|
|
64
|
+
else resolve();
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const checkTimer = setInterval(() => {
|
|
68
|
+
if (hasDeviceConfig()) {
|
|
69
|
+
finish();
|
|
70
|
+
}
|
|
71
|
+
}, 1000);
|
|
72
|
+
|
|
73
|
+
const timeoutTimer = setTimeout(() => {
|
|
74
|
+
finish(new Error('等待二维码配对超时'));
|
|
75
|
+
}, timeoutMs);
|
|
76
|
+
|
|
77
|
+
child.on('error', (err) => finish(err));
|
|
78
|
+
child.on('exit', (code) => {
|
|
79
|
+
if (settled) return;
|
|
80
|
+
if (hasDeviceConfig()) {
|
|
81
|
+
finish();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
finish(new Error(`pm2 logs 退出,exit=${code || 0}`));
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
26
89
|
function runNodeEntry() {
|
|
27
90
|
if (!fs.existsSync(distEntry)) {
|
|
28
91
|
console.error('dist/index.js 不存在,请先执行 npm run build');
|
|
@@ -33,12 +96,17 @@ function runNodeEntry() {
|
|
|
33
96
|
}
|
|
34
97
|
|
|
35
98
|
function doctor() {
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
const deviceConfig = path.join(openclawHome, 'wechat-device.json');
|
|
99
|
+
const openclawHome = getOpenClawHome();
|
|
100
|
+
const deviceConfig = getDeviceConfigPath();
|
|
39
101
|
const issues = [];
|
|
40
102
|
|
|
41
103
|
if (!hasCommand('openclaw')) issues.push('未找到 openclaw CLI');
|
|
104
|
+
else {
|
|
105
|
+
const versionRes = spawnSync('openclaw', ['--version'], { encoding: 'utf8', env: process.env });
|
|
106
|
+
if (versionRes.status === 0) {
|
|
107
|
+
console.log(`openclaw version: ${versionRes.stdout.trim()}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
42
110
|
if (!fs.existsSync(deviceConfig)) issues.push('未找到 ~/.openclaw/wechat-device.json,设备尚未配对');
|
|
43
111
|
if (!process.env.WECHAT_BACKEND_URL) issues.push('未设置 WECHAT_BACKEND_URL,将使用内置默认值');
|
|
44
112
|
if (!process.env.PLUGIN_SECRET) issues.push('未设置 PLUGIN_SECRET,内部通信将依赖空密钥');
|
|
@@ -59,9 +127,17 @@ function doctor() {
|
|
|
59
127
|
console.log('\nDoctor OK');
|
|
60
128
|
}
|
|
61
129
|
|
|
62
|
-
function
|
|
130
|
+
function pair() {
|
|
131
|
+
console.log('启动前台配对模式...');
|
|
132
|
+
console.log('配对成功后会生成 ~/.openclaw/wechat-device.json');
|
|
133
|
+
runNodeEntry();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async function install() {
|
|
63
137
|
const args = new Set(process.argv.slice(3));
|
|
64
138
|
const usePm2 = args.has('--pm2');
|
|
139
|
+
const enableStartup = args.has('--startup');
|
|
140
|
+
const waitPair = args.has('--wait-pair') || !hasDeviceConfig();
|
|
65
141
|
|
|
66
142
|
if (!fs.existsSync(distEntry)) {
|
|
67
143
|
console.error('dist/index.js 不存在,请先执行 npm run build,或使用发布后的 npm 包。');
|
|
@@ -87,7 +163,38 @@ function install() {
|
|
|
87
163
|
process.exit(start.status || 1);
|
|
88
164
|
}
|
|
89
165
|
spawnSync('pm2', ['save'], { stdio: 'inherit', env: process.env, cwd: packageRoot });
|
|
166
|
+
if (enableStartup) {
|
|
167
|
+
const startup = spawnSync('pm2', ['startup'], {
|
|
168
|
+
stdio: 'inherit',
|
|
169
|
+
env: process.env,
|
|
170
|
+
cwd: packageRoot,
|
|
171
|
+
});
|
|
172
|
+
if (startup.status !== 0) {
|
|
173
|
+
console.error('\npm2 startup 执行失败,请手动执行:pm2 startup && pm2 save');
|
|
174
|
+
process.exit(startup.status || 1);
|
|
175
|
+
}
|
|
176
|
+
spawnSync('pm2', ['save'], { stdio: 'inherit', env: process.env, cwd: packageRoot });
|
|
177
|
+
console.log('\nStartup OK: 已尝试启用开机自启');
|
|
178
|
+
}
|
|
90
179
|
console.log('\nInstall OK: pm2 进程已创建');
|
|
180
|
+
if (!enableStartup) {
|
|
181
|
+
console.log('如需开机自启: openclaw-vchat install --pm2 --startup');
|
|
182
|
+
}
|
|
183
|
+
if (waitPair) {
|
|
184
|
+
console.log('\n检测到当前设备尚未配对,自动进入二维码配对环节...');
|
|
185
|
+
console.log(`配对文件: ${getDeviceConfigPath()}`);
|
|
186
|
+
console.log(`将实时输出二维码日志,配对成功后自动结束。`);
|
|
187
|
+
sleep(1500);
|
|
188
|
+
try {
|
|
189
|
+
await waitForPairingViaPm2Logs(name, 15 * 60 * 1000);
|
|
190
|
+
} catch (error) {
|
|
191
|
+
console.error(`\n${error.message || '等待配对失败'}`);
|
|
192
|
+
console.error(`可手动查看日志: pm2 logs ${name}`);
|
|
193
|
+
process.exit(1);
|
|
194
|
+
}
|
|
195
|
+
console.log('\n配对完成:已检测到 wechat-device.json');
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
91
198
|
console.log(`查看日志: pm2 logs ${name}`);
|
|
92
199
|
return;
|
|
93
200
|
}
|
|
@@ -95,16 +202,28 @@ function install() {
|
|
|
95
202
|
console.log('\nInstall OK');
|
|
96
203
|
console.log('直接启动: openclaw-vchat start');
|
|
97
204
|
console.log('若需守护进程: openclaw-vchat install --pm2');
|
|
205
|
+
console.log('若需守护进程 + 开机自启: openclaw-vchat install --pm2 --startup');
|
|
206
|
+
if (waitPair) {
|
|
207
|
+
console.log('当前设备尚未配对,建议直接执行: openclaw-vchat pair');
|
|
208
|
+
}
|
|
98
209
|
}
|
|
99
210
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
else if (cmd === '
|
|
104
|
-
else if (cmd === '
|
|
105
|
-
else if (cmd === '
|
|
106
|
-
else
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
211
|
+
async function main() {
|
|
212
|
+
const cmd = process.argv[2] || 'start';
|
|
213
|
+
if (cmd === 'start') runNodeEntry();
|
|
214
|
+
else if (cmd === 'install') await install();
|
|
215
|
+
else if (cmd === 'pair') pair();
|
|
216
|
+
else if (cmd === 'doctor') doctor();
|
|
217
|
+
else if (cmd === 'version' || cmd === '--version' || cmd === '-v') console.log(pkg.version);
|
|
218
|
+
else if (cmd === 'help' || cmd === '--help' || cmd === '-h') printUsage();
|
|
219
|
+
else {
|
|
220
|
+
console.error(`未知命令: ${cmd}`);
|
|
221
|
+
printUsage();
|
|
222
|
+
process.exit(1);
|
|
223
|
+
}
|
|
110
224
|
}
|
|
225
|
+
|
|
226
|
+
main().catch((error) => {
|
|
227
|
+
console.error(error.message || String(error));
|
|
228
|
+
process.exit(1);
|
|
229
|
+
});
|