@qqbrowser/qbot-claw-launcher 0.9.32

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.
Files changed (90) hide show
  1. package/README.md +1 -0
  2. package/debug.html +440 -0
  3. package/dist/config.d.ts +15 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +23 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +128 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/installer.d.ts +20 -0
  12. package/dist/installer.d.ts.map +1 -0
  13. package/dist/installer.js +335 -0
  14. package/dist/installer.js.map +1 -0
  15. package/dist/quarantine.d.ts +37 -0
  16. package/dist/quarantine.d.ts.map +1 -0
  17. package/dist/quarantine.js +315 -0
  18. package/dist/quarantine.js.map +1 -0
  19. package/dist/reportLog.d.ts +28 -0
  20. package/dist/reportLog.d.ts.map +1 -0
  21. package/dist/reportLog.js +262 -0
  22. package/dist/reportLog.js.map +1 -0
  23. package/dist/server.d.ts +4 -0
  24. package/dist/server.d.ts.map +1 -0
  25. package/dist/server.js +425 -0
  26. package/dist/server.js.map +1 -0
  27. package/dist/service.d.ts +11 -0
  28. package/dist/service.d.ts.map +1 -0
  29. package/dist/service.js +197 -0
  30. package/dist/service.js.map +1 -0
  31. package/dist/state.d.ts +21 -0
  32. package/dist/state.d.ts.map +1 -0
  33. package/dist/state.js +62 -0
  34. package/dist/state.js.map +1 -0
  35. package/dist/utils.d.ts +25 -0
  36. package/dist/utils.d.ts.map +1 -0
  37. package/dist/utils.js +101 -0
  38. package/dist/utils.js.map +1 -0
  39. package/node_modules/@parcel/watcher/LICENSE +21 -0
  40. package/node_modules/@parcel/watcher/README.md +136 -0
  41. package/node_modules/@parcel/watcher/index.d.ts +49 -0
  42. package/node_modules/@parcel/watcher/index.js +42 -0
  43. package/node_modules/@parcel/watcher/index.js.flow +48 -0
  44. package/node_modules/@parcel/watcher/node_modules/picomatch/LICENSE +21 -0
  45. package/node_modules/@parcel/watcher/node_modules/picomatch/README.md +738 -0
  46. package/node_modules/@parcel/watcher/node_modules/picomatch/index.js +17 -0
  47. package/node_modules/@parcel/watcher/node_modules/picomatch/lib/constants.js +180 -0
  48. package/node_modules/@parcel/watcher/node_modules/picomatch/lib/parse.js +1085 -0
  49. package/node_modules/@parcel/watcher/node_modules/picomatch/lib/picomatch.js +341 -0
  50. package/node_modules/@parcel/watcher/node_modules/picomatch/lib/scan.js +391 -0
  51. package/node_modules/@parcel/watcher/node_modules/picomatch/lib/utils.js +72 -0
  52. package/node_modules/@parcel/watcher/node_modules/picomatch/package.json +83 -0
  53. package/node_modules/@parcel/watcher/node_modules/picomatch/posix.js +3 -0
  54. package/node_modules/@parcel/watcher/package.json +39 -0
  55. package/node_modules/@parcel/watcher/wrapper.js +74 -0
  56. package/node_modules/@parcel/watcher-darwin-arm64/LICENSE +21 -0
  57. package/node_modules/@parcel/watcher-darwin-arm64/README.md +1 -0
  58. package/node_modules/@parcel/watcher-darwin-arm64/package.json +30 -0
  59. package/node_modules/@parcel/watcher-darwin-arm64/watcher.node +0 -0
  60. package/node_modules/fs-xattr/LICENSE +21 -0
  61. package/node_modules/fs-xattr/build/Makefile +347 -0
  62. package/node_modules/fs-xattr/build/Release/.deps/Release/obj.target/xattr/src/async.o.d +15 -0
  63. package/node_modules/fs-xattr/build/Release/.deps/Release/obj.target/xattr/src/error.o.d +12 -0
  64. package/node_modules/fs-xattr/build/Release/.deps/Release/obj.target/xattr/src/sync.o.d +15 -0
  65. package/node_modules/fs-xattr/build/Release/.deps/Release/obj.target/xattr/src/util.o.d +12 -0
  66. package/node_modules/fs-xattr/build/Release/.deps/Release/obj.target/xattr/src/xattr.o.d +14 -0
  67. package/node_modules/fs-xattr/build/Release/.deps/Release/xattr.node.d +1 -0
  68. package/node_modules/fs-xattr/build/Release/obj.target/xattr/src/async.o +0 -0
  69. package/node_modules/fs-xattr/build/Release/obj.target/xattr/src/error.o +0 -0
  70. package/node_modules/fs-xattr/build/Release/obj.target/xattr/src/sync.o +0 -0
  71. package/node_modules/fs-xattr/build/Release/obj.target/xattr/src/util.o +0 -0
  72. package/node_modules/fs-xattr/build/Release/obj.target/xattr/src/xattr.o +0 -0
  73. package/node_modules/fs-xattr/build/Release/xattr.node +0 -0
  74. package/node_modules/fs-xattr/build/binding.Makefile +6 -0
  75. package/node_modules/fs-xattr/build/config.gypi +530 -0
  76. package/node_modules/fs-xattr/build/gyp-mac-tool +772 -0
  77. package/node_modules/fs-xattr/build/xattr.target.mk +185 -0
  78. package/node_modules/fs-xattr/index.d.ts +47 -0
  79. package/node_modules/fs-xattr/index.js +80 -0
  80. package/node_modules/fs-xattr/package.json +29 -0
  81. package/node_modules/fs-xattr/readme.md +101 -0
  82. package/node_modules/is-extglob/LICENSE +21 -0
  83. package/node_modules/is-extglob/README.md +107 -0
  84. package/node_modules/is-extglob/index.js +20 -0
  85. package/node_modules/is-extglob/package.json +69 -0
  86. package/node_modules/is-glob/LICENSE +21 -0
  87. package/node_modules/is-glob/README.md +206 -0
  88. package/node_modules/is-glob/index.js +150 -0
  89. package/node_modules/is-glob/package.json +81 -0
  90. package/package.json +45 -0
package/dist/server.js ADDED
@@ -0,0 +1,425 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.server = void 0;
7
+ exports.watchParentProcess = watchParentProcess;
8
+ const http_1 = __importDefault(require("http"));
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const config_1 = require("./config");
12
+ const utils_1 = require("./utils");
13
+ const reportLog_1 = require("./reportLog");
14
+ const installer_1 = require("./installer");
15
+ const state_1 = require("./state");
16
+ const child_process_1 = require("child_process");
17
+ // CORS 响应头
18
+ const CORS_HEADERS = {
19
+ 'Access-Control-Allow-Origin': '*',
20
+ 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
21
+ 'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Requested-With',
22
+ 'Access-Control-Max-Age': '86400',
23
+ };
24
+ // 设置 CORS 响应头
25
+ function setCorsHeaders(res) {
26
+ for (const [key, value] of Object.entries(CORS_HEADERS)) {
27
+ res.setHeader(key, value);
28
+ }
29
+ }
30
+ exports.server = http_1.default.createServer(async (req, res) => {
31
+ const url = req.url || '';
32
+ // 为所有响应设置 CORS 头
33
+ setCorsHeaders(res);
34
+ // 处理 OPTIONS 预检请求
35
+ if (req.method === 'OPTIONS') {
36
+ res.writeHead(204, CORS_HEADERS);
37
+ res.end();
38
+ return;
39
+ }
40
+ // GET /api/version:返回自身版本、node 版本、qbotclaw 版本
41
+ if (url === '/api/version') {
42
+ // 自身版本:从 package.json 读取
43
+ let selfVersion = 'unknown';
44
+ try {
45
+ const pkgPath = path_1.default.join(__dirname, '..', 'package.json');
46
+ const pkg = JSON.parse(fs_1.default.readFileSync(pkgPath, 'utf-8'));
47
+ selfVersion = pkg.version || 'unknown';
48
+ }
49
+ catch { }
50
+ // node 版本
51
+ let nodeVersion = 'unknown';
52
+ try {
53
+ nodeVersion = (await (0, utils_1.execCommand)(`"${config_1.NODE_BIN}" -v`)).trim();
54
+ (0, reportLog_1.log)(`[version] node 版本: ${nodeVersion}`);
55
+ }
56
+ catch (err) {
57
+ (0, reportLog_1.log)(`[version] 获取 node 版本失败: ${err.message}`);
58
+ nodeVersion = `error: ${err.message}`;
59
+ }
60
+ // qbotclaw 版本
61
+ const qbotclawVersion = (await (0, utils_1.getQBotClawVersion)()) ?? '0.0.0';
62
+ (0, reportLog_1.log)(`[version] qbotclaw 版本: ${qbotclawVersion}`);
63
+ // mcporter 版本
64
+ let mcporterVersion = '0.0.0';
65
+ if (fs_1.default.existsSync(config_1.MCPORTER_BIN)) {
66
+ try {
67
+ mcporterVersion = (await (0, utils_1.execCommand)(`"${config_1.NODE_BIN}" "${config_1.MCPORTER_BIN}" --version`)).trim();
68
+ (0, reportLog_1.log)(`[version] mcporter 版本: ${mcporterVersion}`);
69
+ }
70
+ catch (err) {
71
+ (0, reportLog_1.log)(`[version] 获取 mcporter 版本失败: ${err.message}`);
72
+ mcporterVersion = `error: ${err.message}`;
73
+ }
74
+ }
75
+ // python 版本
76
+ let pythonVersion = '0.0.0';
77
+ if (fs_1.default.existsSync(config_1.PYTHON_BIN)) {
78
+ try {
79
+ pythonVersion = (await (0, utils_1.execCommand)(`"${config_1.PYTHON_BIN}" --version`)).trim();
80
+ (0, reportLog_1.log)(`[version] python 版本: ${pythonVersion}`);
81
+ }
82
+ catch (err) {
83
+ (0, reportLog_1.log)(`[version] 获取 python 版本失败: ${err.message}`);
84
+ pythonVersion = `error: ${err.message}`;
85
+ }
86
+ }
87
+ (0, utils_1.sendJSON)(res, 200, {
88
+ status: '成功',
89
+ launcher: selfVersion,
90
+ node: nodeVersion,
91
+ qbotclaw: qbotclawVersion,
92
+ mcporter: mcporterVersion,
93
+ python: pythonVersion,
94
+ });
95
+ return;
96
+ }
97
+ // GET /api/port:返回各服务的端口信息
98
+ if (url === '/api/port') {
99
+ const addr = exports.server.address();
100
+ const launcherPort = addr && typeof addr === 'object' ? addr.port : null;
101
+ const state = (0, state_1.readState)();
102
+ (0, utils_1.sendJSON)(res, 200, {
103
+ status: '成功',
104
+ launcher: launcherPort,
105
+ qbotclaw: state.gatewayPort ?? 2000,
106
+ mcpHttp: state.mcpHttpPort ?? 18081,
107
+ mcpWs: state.mcpWsPort ?? 8765,
108
+ });
109
+ return;
110
+ }
111
+ // GET /api/install:流式响应,实时推送安装日志
112
+ if (url.startsWith('/api/install') && !url.startsWith('/api/install/')) {
113
+ if (installer_1.installState.status === 'downloading') {
114
+ (0, utils_1.sendJSON)(res, 200, { ok: 'downloading', message: '正在安装中...' });
115
+ return;
116
+ }
117
+ const parsedUrl = new URL(url, 'http://localhost');
118
+ const version = parsedUrl.searchParams.get('version') || undefined;
119
+ if (!version) {
120
+ (0, utils_1.sendJSON)(res, 400, { status: '失败', message: '缺少必要参数 version,用法: GET /api/install?version=x.x.x' });
121
+ return;
122
+ }
123
+ res.writeHead(200, {
124
+ ...CORS_HEADERS,
125
+ 'Content-Type': 'text/plain; charset=utf-8',
126
+ 'Transfer-Encoding': 'chunked',
127
+ 'Cache-Control': 'no-cache',
128
+ });
129
+ (0, installer_1.runInstall)(res, version);
130
+ return;
131
+ }
132
+ // GET /api/watch?ppid=xxx:动态注册父进程监控
133
+ if (url.startsWith('/api/watch')) {
134
+ const parsedWatchUrl = new URL(url, 'http://localhost');
135
+ const watchPpid = parsedWatchUrl.searchParams.get('ppid');
136
+ if (!watchPpid || isNaN(Number(watchPpid))) {
137
+ (0, utils_1.sendJSON)(res, 400, { status: '失败', message: '缺少有效的 ppid 参数,用法: GET /api/watch?ppid=12345' });
138
+ return;
139
+ }
140
+ const ppidNum = parseInt(watchPpid, 10);
141
+ // 检查目标进程是否存在
142
+ try {
143
+ process.kill(ppidNum, 0);
144
+ }
145
+ catch {
146
+ (0, utils_1.sendJSON)(res, 400, { status: '失败', message: `进程 ${ppidNum} 不存在` });
147
+ return;
148
+ }
149
+ // 将 ppid 写入 state 持久化
150
+ const currentState = (0, state_1.readState)();
151
+ (0, state_1.writeState)({ ...currentState, ppid: ppidNum });
152
+ // 启动(或更新)父进程存活检测
153
+ watchParentProcess(ppidNum);
154
+ (0, utils_1.sendJSON)(res, 200, { status: '成功', message: `已开始监控父进程 ppid: ${ppidNum}` });
155
+ return;
156
+ }
157
+ // POST /api/qbotclaw:通用的 qbotclaw 命令执行,通过 POST body 传入 args 数组
158
+ if (url === '/api/qbotclaw' && req.method === 'POST') {
159
+ let body = '';
160
+ req.on('data', (chunk) => {
161
+ body += chunk.toString();
162
+ });
163
+ req.on('end', () => {
164
+ let args;
165
+ try {
166
+ const parsed = JSON.parse(body);
167
+ if (!Array.isArray(parsed.args) || parsed.args.length === 0) {
168
+ (0, utils_1.sendJSON)(res, 400, { status: '失败', message: '参数 args 必须是非空数组' });
169
+ return;
170
+ }
171
+ args = parsed.args.map((arg) => String(arg));
172
+ }
173
+ catch {
174
+ (0, utils_1.sendJSON)(res, 400, { status: '失败', message: '请求体必须是合法的 JSON' });
175
+ return;
176
+ }
177
+ if (!fs_1.default.existsSync(config_1.QBOTCLAW_BIN)) {
178
+ (0, utils_1.sendJSON)(res, 404, { status: '失败', message: `qbotclaw 可执行文件不存在: ${config_1.QBOTCLAW_BIN}` });
179
+ return;
180
+ }
181
+ res.writeHead(200, {
182
+ ...CORS_HEADERS,
183
+ 'Content-Type': 'text/plain; charset=utf-8',
184
+ 'Transfer-Encoding': 'chunked',
185
+ 'Cache-Control': 'no-cache',
186
+ });
187
+ (0, installer_1.runQBotClaw)(args, res).then(() => {
188
+ res.end('\n[执行成功]\n');
189
+ }).catch((err) => {
190
+ res.end(`\n[启动失败: ${err.message}]\n`);
191
+ });
192
+ });
193
+ return;
194
+ }
195
+ // GET /api/uninstall:流式卸载接口
196
+ if (url.startsWith('/api/uninstall')) {
197
+ const parsedUrl = new URL(url, 'http://localhost');
198
+ const keepWorkspace = parsedUrl.searchParams.get('keepWorkspace') === 'true';
199
+ res.writeHead(200, {
200
+ ...CORS_HEADERS,
201
+ 'Content-Type': 'text/plain; charset=utf-8',
202
+ 'Transfer-Encoding': 'chunked',
203
+ 'Cache-Control': 'no-cache',
204
+ });
205
+ const sendEvent = (status, file, msg) => {
206
+ if (res.writable) {
207
+ try {
208
+ res.write(JSON.stringify({ status, file, msg }) + '\n');
209
+ }
210
+ catch { }
211
+ }
212
+ };
213
+ try {
214
+ // 1. 停止 QBotClaw
215
+ sendEvent('成功', '', '正在停止 QBotClaw...');
216
+ const state = (0, state_1.readState)();
217
+ if (state.gatewayPid) {
218
+ try {
219
+ process.kill(state.gatewayPid, 'SIGTERM');
220
+ (0, reportLog_1.log)(`[uninstall] 已停止 QBotClaw gateway 进程 pid: ${state.gatewayPid}`);
221
+ sendEvent('成功', '', `已停止 QBotClaw gateway 进程 pid: ${state.gatewayPid}`);
222
+ }
223
+ catch {
224
+ (0, reportLog_1.log)(`[uninstall] QBotClaw gateway 进程 ${state.gatewayPid} 可能已退出`);
225
+ sendEvent('成功', '', `QBotClaw gateway 进程 ${state.gatewayPid} 可能已退出`);
226
+ }
227
+ }
228
+ else {
229
+ sendEvent('成功', '', 'QBotClaw 未在运行');
230
+ }
231
+ // 2. npm uninstall -g @qqbrowser/openclaw-qbot
232
+ sendEvent('成功', '', `正在执行 npm uninstall -g ${config_1.NPM_PACKAGE_NAME}...`);
233
+ try {
234
+ await new Promise((resolve, reject) => {
235
+ const child = (0, child_process_1.spawn)(config_1.NPM_BIN, ['--userconfig', config_1.NPM_RC, 'uninstall', '-g', config_1.NPM_PACKAGE_NAME], {
236
+ env: { ...process.env, PATH: `${config_1.NODE_BIN_DIR}:${process.env.PATH}` },
237
+ });
238
+ child.stdout?.on('data', (chunk) => {
239
+ (0, reportLog_1.log)(`[uninstall] npm: ${chunk.toString().trim()}`);
240
+ });
241
+ child.stderr?.on('data', (chunk) => {
242
+ (0, reportLog_1.log)(`[uninstall] npm stderr: ${chunk.toString().trim()}`);
243
+ });
244
+ child.on('close', (code) => {
245
+ if (code === 0)
246
+ resolve();
247
+ else
248
+ reject(new Error(`npm uninstall 退出码: ${code}`));
249
+ });
250
+ child.on('error', (err) => reject(err));
251
+ });
252
+ (0, reportLog_1.log)(`[uninstall] npm uninstall -g ${config_1.NPM_PACKAGE_NAME} 成功`);
253
+ sendEvent('成功', '', `npm uninstall -g ${config_1.NPM_PACKAGE_NAME} 成功`);
254
+ }
255
+ catch (err) {
256
+ (0, reportLog_1.log)(`[uninstall] npm uninstall 失败: ${err.message}`);
257
+ sendEvent('失败', '', `npm uninstall 失败: ${err.message}`);
258
+ }
259
+ // 3. 删除 QBOT_CLAW_DIR 下的所有文件和目录
260
+ sendEvent('成功', '', `正在清理目录 ${config_1.QBOT_CLAW_DIR}...`);
261
+ const failedItems = [];
262
+ if (fs_1.default.existsSync(config_1.QBOT_CLAW_DIR)) {
263
+ const entries = fs_1.default.readdirSync(config_1.QBOT_CLAW_DIR);
264
+ for (const entry of entries) {
265
+ const fullPath = path_1.default.join(config_1.QBOT_CLAW_DIR, entry);
266
+ // 如果 keepWorkspace=true,跳过 workspace 目录
267
+ if (keepWorkspace && entry === 'workspace') {
268
+ sendEvent('成功', fullPath, '保留 workspace 目录');
269
+ continue;
270
+ }
271
+ try {
272
+ const stat = fs_1.default.statSync(fullPath);
273
+ if (stat.isDirectory()) {
274
+ fs_1.default.rmSync(fullPath, { recursive: true, force: true });
275
+ }
276
+ else {
277
+ fs_1.default.unlinkSync(fullPath);
278
+ }
279
+ sendEvent('成功', fullPath, '已删除');
280
+ }
281
+ catch (err) {
282
+ (0, reportLog_1.log)(`[uninstall] 删除失败: ${fullPath} - ${err.message}`);
283
+ sendEvent('失败', fullPath, `删除失败: ${err.message}`);
284
+ failedItems.push(fullPath);
285
+ }
286
+ }
287
+ // 4. 对删除失败的项目使用系统 rm 命令重试
288
+ if (failedItems.length > 0) {
289
+ sendEvent('成功', '', `${failedItems.length} 个项目删除失败,使用 rm 命令重试...`);
290
+ for (const item of failedItems) {
291
+ try {
292
+ (0, child_process_1.execSync)(`rm -rf "${item}"`);
293
+ (0, reportLog_1.log)(`[uninstall] rm -rf 重试成功: ${item}`);
294
+ sendEvent('成功', item, 'rm 重试删除成功');
295
+ }
296
+ catch (err) {
297
+ (0, reportLog_1.log)(`[uninstall] rm -rf 重试也失败: ${item} - ${err.message}`);
298
+ sendEvent('失败', item, `rm 重试也失败: ${err.message}`);
299
+ }
300
+ }
301
+ }
302
+ // 5. 如果 keepWorkspace=false,删除 QBOT_CLAW_DIR 本身
303
+ if (!keepWorkspace) {
304
+ try {
305
+ fs_1.default.rmSync(config_1.QBOT_CLAW_DIR, { recursive: true, force: true });
306
+ sendEvent('成功', config_1.QBOT_CLAW_DIR, '已删除根目录');
307
+ }
308
+ catch (err) {
309
+ (0, reportLog_1.log)(`[uninstall] 删除根目录失败: ${err.message}`);
310
+ // 使用 rm 重试
311
+ try {
312
+ (0, child_process_1.execSync)(`rm -rf "${config_1.QBOT_CLAW_DIR}"`);
313
+ sendEvent('成功', config_1.QBOT_CLAW_DIR, 'rm 重试删除根目录成功');
314
+ }
315
+ catch (err2) {
316
+ sendEvent('失败', config_1.QBOT_CLAW_DIR, `删除根目录失败: ${err2.message}`);
317
+ }
318
+ }
319
+ }
320
+ else {
321
+ // keepWorkspace=true 时,尝试删除空的根目录(如果只剩 workspace)
322
+ sendEvent('成功', config_1.QBOT_CLAW_DIR, '保留根目录(workspace 模式)');
323
+ }
324
+ }
325
+ else {
326
+ sendEvent('成功', config_1.QBOT_CLAW_DIR, '目录不存在,无需清理');
327
+ }
328
+ sendEvent('成功', '', '卸载完成');
329
+ }
330
+ catch (err) {
331
+ (0, reportLog_1.log)(`[uninstall] 卸载过程异常: ${err.message}`);
332
+ sendEvent('失败', '', `卸载过程异常: ${err.message}`);
333
+ }
334
+ res.end();
335
+ // 卸载完成后,延迟退出进程,确保响应已发送完毕
336
+ setTimeout(() => {
337
+ (0, reportLog_1.log)('[uninstall] 卸载流程结束,launcher 进程退出');
338
+ process.exit(0);
339
+ }, 500);
340
+ return;
341
+ }
342
+ // GET /debug:返回本地调试面板页面
343
+ if (url === '/debug' || url === '/debug.html') {
344
+ const debugHtmlPath = path_1.default.join(__dirname, '..', 'debug.html');
345
+ try {
346
+ const html = fs_1.default.readFileSync(debugHtmlPath, 'utf-8');
347
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
348
+ res.end(html);
349
+ }
350
+ catch {
351
+ (0, utils_1.sendJSON)(res, 404, { status: '失败', message: 'debug.html 文件不存在' });
352
+ }
353
+ return;
354
+ }
355
+ // 未匹配的路由
356
+ (0, utils_1.sendJSON)(res, 404, { status: '失败', message: '接口不存在' });
357
+ });
358
+ // 父进程存活检测:监控指定 ppid 的进程是否存活,若已退出则自动退出
359
+ // 若未传入 ppid,则不做监控
360
+ let parentWatchTimer = null;
361
+ let parentWatchPpid = null;
362
+ function watchParentProcess(ppid) {
363
+ if (!ppid) {
364
+ return;
365
+ }
366
+ // 如果已在监控同一个父进程,则跳过
367
+ if (parentWatchTimer && parentWatchPpid === ppid) {
368
+ (0, reportLog_1.log)(`[watchParentProcess] 已在监控父进程 ppid: ${ppid},跳过重复监听`);
369
+ return;
370
+ }
371
+ // 如果已在监控其他父进程,先停止旧的 timer
372
+ if (parentWatchTimer) {
373
+ (0, reportLog_1.log)(`[watchParentProcess] 已有监控(ppid: ${parentWatchPpid}),停止旧的监控,重新监控 ppid: ${ppid}`);
374
+ clearInterval(parentWatchTimer);
375
+ parentWatchTimer = null;
376
+ parentWatchPpid = null;
377
+ }
378
+ else {
379
+ (0, reportLog_1.log)(`[watchParentProcess] 开始监控父进程 ppid: ${ppid}`);
380
+ }
381
+ const timer = setInterval(() => {
382
+ try {
383
+ process.kill(ppid, 0);
384
+ }
385
+ catch {
386
+ // 父进程已退出
387
+ (0, reportLog_1.log)(`[watchParentProcess] 父进程 ${ppid} 已退出,开始清理并退出`);
388
+ clearInterval(timer);
389
+ parentWatchTimer = null;
390
+ parentWatchPpid = null;
391
+ // 杀掉 qbotclaw 子进程
392
+ const currentState = (0, state_1.readState)();
393
+ if (currentState.gatewayPid) {
394
+ try {
395
+ process.kill(currentState.gatewayPid, 'SIGTERM');
396
+ (0, reportLog_1.log)(`[watchParentProcess] 已发送 SIGTERM 给 qbotclaw 进程 pid: ${currentState.gatewayPid}`);
397
+ }
398
+ catch {
399
+ // 进程可能已退出,忽略
400
+ (0, reportLog_1.log)(`[watchParentProcess] qbotclaw 进程 ${currentState.gatewayPid} 可能已退出,忽略`);
401
+ }
402
+ }
403
+ // 清理状态文件
404
+ (0, state_1.clearState)();
405
+ (0, reportLog_1.log)(`[watchParentProcess] 状态已清理,关闭 server 并退出`);
406
+ // 先关闭 server,停止接受新连接,再强制退出
407
+ exports.server.close(() => {
408
+ (0, reportLog_1.log)(`[watchParentProcess] server 已关闭,进程退出`);
409
+ process.exit(0);
410
+ });
411
+ // 兜底:3 秒后强制退出,防止 server.close 回调因活跃连接迟迟不触发
412
+ setTimeout(() => {
413
+ (0, reportLog_1.log)(`[watchParentProcess] server.close 超时,强制退出`);
414
+ process.exit(0);
415
+ }, 3000).unref();
416
+ }
417
+ }, 3000);
418
+ // timer 调用 unref,事件循环由 server.listen 保持
419
+ {
420
+ timer.unref();
421
+ }
422
+ parentWatchTimer = timer;
423
+ parentWatchPpid = ppid;
424
+ }
425
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * 启动服务(在当前进程直接监听)
3
+ * @param ppid
4
+ * @param clawVersion 可选,期望的 qbotclaw 版本号;若传入且与本地安装版本不一致,则不启动 qbotclaw
5
+ */
6
+ export declare function startService(ppid?: number, clawVersion?: string): Promise<void>;
7
+ /**
8
+ * 停止服务
9
+ */
10
+ export declare function stopService(): void;
11
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAiGA;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoErF;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAsBlC"}
@@ -0,0 +1,197 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.startService = startService;
7
+ exports.stopService = stopService;
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const http_1 = __importDefault(require("http"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const server_1 = require("./server");
12
+ const state_1 = require("./state");
13
+ const config_1 = require("./config");
14
+ const installer_1 = require("./installer");
15
+ const utils_1 = require("./utils");
16
+ const reportLog_1 = require("./reportLog");
17
+ /** 获取当前 launcher 自身版本号 */
18
+ function getSelfVersion() {
19
+ try {
20
+ const pkgPath = path_1.default.join(__dirname, '..', 'package.json');
21
+ const pkg = JSON.parse(fs_1.default.readFileSync(pkgPath, 'utf-8'));
22
+ return pkg.version || 'unknown';
23
+ }
24
+ catch {
25
+ return 'unknown';
26
+ }
27
+ }
28
+ /**
29
+ * 查询正在运行的服务版本,失败返回 null
30
+ */
31
+ function fetchRunningVersion(port) {
32
+ return new Promise((resolve) => {
33
+ const req = http_1.default.get(`http://127.0.0.1:${port}/api/version`, (res) => {
34
+ let data = '';
35
+ res.on('data', (chunk) => {
36
+ data += chunk.toString();
37
+ });
38
+ res.on('end', () => {
39
+ try {
40
+ const json = JSON.parse(data);
41
+ resolve(json.launcher ?? null);
42
+ }
43
+ catch {
44
+ resolve(null);
45
+ }
46
+ });
47
+ });
48
+ req.on('error', () => resolve(null));
49
+ req.setTimeout(3000, () => {
50
+ req.destroy();
51
+ resolve(null);
52
+ });
53
+ });
54
+ }
55
+ /**
56
+ * 检测正在运行的服务版本是否与当前版本一致。
57
+ * 若版本一致,返回 false(调用方应复用已有服务)。
58
+ * 若版本不一致,杀掉旧服务并清理状态,返回 true(调用方应重新启动)。
59
+ * 若服务未在运行,返回 null(调用方应继续正常启动流程)。
60
+ */
61
+ async function restartIfOutdated() {
62
+ const state = (0, state_1.readState)();
63
+ if (!state.pid || !state.port)
64
+ return null;
65
+ try {
66
+ process.kill(state.pid, 0);
67
+ }
68
+ catch {
69
+ // 进程不存在,清除过期状态
70
+ (0, state_1.clearState)();
71
+ return null;
72
+ }
73
+ // 进程存在,检查端口是否真的在监听
74
+ const available = await (0, state_1.isPortAvailable)(state.port);
75
+ if (available) {
76
+ (0, reportLog_1.log)('端口未被占用,说明状态文件过期');
77
+ (0, state_1.clearState)();
78
+ return null;
79
+ }
80
+ // 端口被占用(即服务正在监听),检查版本是否一致
81
+ const runningVersion = await fetchRunningVersion(state.port);
82
+ const selfVersion = getSelfVersion();
83
+ (0, reportLog_1.log)(`[service] 检测到正在运行的服务版本: ${runningVersion ?? 'unknown'},当前版本: ${selfVersion}`);
84
+ if (runningVersion === selfVersion) {
85
+ // 版本一致,复用已有服务
86
+ (0, reportLog_1.log)(`[service] 版本一致,复用已有服务 (pid: ${state.pid}, port: ${state.port})`);
87
+ return false;
88
+ }
89
+ // 版本不一致,杀掉旧服务
90
+ (0, reportLog_1.log)(`[service] 版本不一致 (运行中: ${runningVersion ?? 'unknown'}, 当前: ${selfVersion}),杀掉旧进程 pid: ${state.pid},重新启动`);
91
+ try {
92
+ process.kill(state.pid, 'SIGTERM');
93
+ }
94
+ catch {
95
+ // 进程可能已退出,忽略
96
+ }
97
+ (0, state_1.clearState)();
98
+ return true;
99
+ }
100
+ /**
101
+ * 启动服务(在当前进程直接监听)
102
+ * @param ppid
103
+ * @param clawVersion 可选,期望的 qbotclaw 版本号;若传入且与本地安装版本不一致,则不启动 qbotclaw
104
+ */
105
+ async function startService(ppid, clawVersion) {
106
+ // 检查服务是否已在运行,必要时重启旧版本
107
+ const restartResult = await restartIfOutdated();
108
+ if (restartResult === false) {
109
+ // 版本符合要求,复用已有服务
110
+ const state = (0, state_1.readState)();
111
+ process.stdout.write(JSON.stringify({ state: 'success', pid: state.pid, port: state.port }) + '\n');
112
+ process.stdout.uncork();
113
+ return;
114
+ }
115
+ // restartResult === true:旧版本已被杀掉,继续往下重新 listen
116
+ // restartResult === null:服务未在运行,继续往下正常启动
117
+ const listenPort = await (0, state_1.findAvailablePort)();
118
+ server_1.server.listen(listenPort, '127.0.0.1', () => {
119
+ (0, state_1.writeState)({ pid: process.pid, port: listenPort, ...(ppid ? { ppid } : {}) });
120
+ // 不要往 console 中输入任何内容,chrome 需要读取此 json,返回给前端
121
+ process.stdout.write(JSON.stringify({ state: 'success', pid: process.pid, port: listenPort }) + '\n');
122
+ process.stdout.uncork();
123
+ // 启动父进程存活检测,父进程退出时自动退出(仅在传入 ppid 时生效)
124
+ (0, server_1.watchParentProcess)(ppid);
125
+ // 若 qbotclaw 已安装,则自动启动 gateway 并更新状态文件
126
+ if (!fs_1.default.existsSync(config_1.QBOTCLAW_BIN)) {
127
+ (0, reportLog_1.log)(`[service] qbotclaw 未安装,不自动启动`);
128
+ return;
129
+ }
130
+ // 若传入了期望版本,则校验本地版本是否匹配
131
+ (0, utils_1.getQBotClawVersion)().then((localVersion) => {
132
+ const currentState = (0, state_1.readState)();
133
+ if (localVersion !== clawVersion) {
134
+ (0, reportLog_1.log)(`[service] qbotclaw 本地版本 (${localVersion ?? 'unknown'}) 与期望版本 (${clawVersion}) 不一致,停止当前 qbotclaw 进程`);
135
+ // 停止当前正在运行的 qbotclaw 进程
136
+ if (currentState.gatewayPid) {
137
+ try {
138
+ process.kill(currentState.gatewayPid, 'SIGTERM');
139
+ (0, reportLog_1.log)(`[service] 已发送 SIGTERM 给 qbotclaw 进程 pid: ${currentState.gatewayPid}`);
140
+ }
141
+ catch {
142
+ (0, reportLog_1.log)(`[service] qbotclaw 进程 ${currentState.gatewayPid} 可能已退出,忽略`);
143
+ }
144
+ // 清除状态中的 gateway 相关信息
145
+ const { gatewayPid, gatewayPort, mcpHttpPort, mcpWsPort, ...restState } = currentState;
146
+ (0, state_1.writeState)(restState);
147
+ }
148
+ return;
149
+ }
150
+ else {
151
+ if (currentState.gatewayPid && currentState.gatewayPort) {
152
+ (0, reportLog_1.log)(`[service] qbotclaw 已在运行,pid: ${currentState.gatewayPid}, port: ${currentState.gatewayPort}`);
153
+ }
154
+ else {
155
+ (0, reportLog_1.log)('[service] 检测到 qbotclaw,版本匹配,自动启动 gateway...');
156
+ (0, installer_1.configAndRunQBotClaw)().catch((err) => {
157
+ (0, reportLog_1.log)(`[service] 自动启动 gateway 失败: ${err.message}`);
158
+ });
159
+ }
160
+ }
161
+ });
162
+ });
163
+ // 监听退出信号,清理状态文件,并将排队日志全部上传
164
+ process.on('SIGTERM', () => {
165
+ (0, state_1.clearState)();
166
+ (0, reportLog_1.flushLogs)().finally(() => {
167
+ process.exit(0);
168
+ });
169
+ });
170
+ }
171
+ /**
172
+ * 停止服务
173
+ */
174
+ function stopService() {
175
+ const state = (0, state_1.readState)();
176
+ if (!state.pid) {
177
+ process.stdout.write(JSON.stringify({ state: 'err', pid: 0, port: 0 }) + '\n');
178
+ process.stdout.uncork();
179
+ return;
180
+ }
181
+ try {
182
+ process.kill(state.pid, 'SIGTERM');
183
+ const stoppedPid = state.pid;
184
+ const stoppedPort = state.port ?? 0;
185
+ (0, state_1.clearState)();
186
+ process.stdout.write(JSON.stringify({ state: 'success', pid: stoppedPid, port: stoppedPort }) + '\n');
187
+ process.stdout.uncork();
188
+ }
189
+ catch (err) {
190
+ if (err.code === 'ESRCH') {
191
+ (0, state_1.clearState)();
192
+ }
193
+ process.stdout.write(JSON.stringify({ state: 'err', pid: 0, port: 0 }) + '\n');
194
+ process.stdout.uncork();
195
+ }
196
+ }
197
+ //# sourceMappingURL=service.js.map