@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/README.md ADDED
@@ -0,0 +1 @@
1
+ # Claw Launcher
package/debug.html ADDED
@@ -0,0 +1,440 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>claw-launcher 调试面板</title>
7
+ <style>
8
+ * { box-sizing: border-box; margin: 0; padding: 0; }
9
+ body {
10
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
11
+ background: #0f1117;
12
+ color: #e2e8f0;
13
+ min-height: 100vh;
14
+ padding: 24px;
15
+ }
16
+ h1 {
17
+ font-size: 22px;
18
+ font-weight: 700;
19
+ color: #7dd3fc;
20
+ margin-bottom: 6px;
21
+ }
22
+ .subtitle {
23
+ font-size: 13px;
24
+ color: #64748b;
25
+ margin-bottom: 28px;
26
+ }
27
+ .port-bar {
28
+ display: flex;
29
+ align-items: center;
30
+ gap: 10px;
31
+ margin-bottom: 28px;
32
+ background: #1e2330;
33
+ border: 1px solid #2d3748;
34
+ border-radius: 10px;
35
+ padding: 12px 16px;
36
+ }
37
+ .port-bar label { font-size: 13px; color: #94a3b8; white-space: nowrap; }
38
+ .port-bar input {
39
+ width: 100px;
40
+ background: #0f1117;
41
+ border: 1px solid #374151;
42
+ border-radius: 6px;
43
+ color: #e2e8f0;
44
+ padding: 5px 10px;
45
+ font-size: 14px;
46
+ }
47
+ .port-bar input:focus { outline: none; border-color: #7dd3fc; }
48
+ .base-url-display {
49
+ font-size: 13px;
50
+ color: #7dd3fc;
51
+ font-family: monospace;
52
+ }
53
+ .grid {
54
+ display: grid;
55
+ grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));
56
+ gap: 18px;
57
+ }
58
+ .card {
59
+ background: #1e2330;
60
+ border: 1px solid #2d3748;
61
+ border-radius: 12px;
62
+ padding: 20px;
63
+ display: flex;
64
+ flex-direction: column;
65
+ gap: 12px;
66
+ }
67
+ .card-header {
68
+ display: flex;
69
+ align-items: center;
70
+ gap: 10px;
71
+ }
72
+ .method-badge {
73
+ font-size: 11px;
74
+ font-weight: 700;
75
+ padding: 3px 8px;
76
+ border-radius: 5px;
77
+ letter-spacing: 0.5px;
78
+ }
79
+ .get { background: #064e3b; color: #34d399; }
80
+ .post { background: #1e3a5f; color: #60a5fa; }
81
+ .card-title {
82
+ font-size: 14px;
83
+ font-weight: 600;
84
+ color: #e2e8f0;
85
+ font-family: monospace;
86
+ }
87
+ .card-desc {
88
+ font-size: 12px;
89
+ color: #64748b;
90
+ line-height: 1.5;
91
+ }
92
+ .form-row {
93
+ display: flex;
94
+ flex-direction: column;
95
+ gap: 6px;
96
+ }
97
+ .form-row label {
98
+ font-size: 12px;
99
+ color: #94a3b8;
100
+ }
101
+ .form-row input, .form-row textarea {
102
+ background: #0f1117;
103
+ border: 1px solid #374151;
104
+ border-radius: 6px;
105
+ color: #e2e8f0;
106
+ padding: 7px 10px;
107
+ font-size: 13px;
108
+ font-family: monospace;
109
+ resize: vertical;
110
+ }
111
+ .form-row input:focus, .form-row textarea:focus {
112
+ outline: none;
113
+ border-color: #7dd3fc;
114
+ }
115
+ .btn {
116
+ padding: 8px 18px;
117
+ border: none;
118
+ border-radius: 7px;
119
+ font-size: 13px;
120
+ font-weight: 600;
121
+ cursor: pointer;
122
+ transition: opacity 0.15s;
123
+ align-self: flex-start;
124
+ }
125
+ .btn:hover { opacity: 0.85; }
126
+ .btn:disabled { opacity: 0.4; cursor: not-allowed; }
127
+ .btn-primary { background: #2563eb; color: #fff; }
128
+ .btn-warning { background: #d97706; color: #fff; }
129
+ .btn-danger { background: #dc2626; color: #fff; }
130
+ .output-box {
131
+ background: #0a0d14;
132
+ border: 1px solid #1e2330;
133
+ border-radius: 8px;
134
+ padding: 12px;
135
+ font-size: 12px;
136
+ font-family: 'Menlo', 'Consolas', monospace;
137
+ color: #a3e635;
138
+ white-space: pre-wrap;
139
+ word-break: break-all;
140
+ max-height: 260px;
141
+ overflow-y: auto;
142
+ min-height: 48px;
143
+ line-height: 1.6;
144
+ }
145
+ .output-box.error { color: #f87171; }
146
+ .output-box.info { color: #7dd3fc; }
147
+ .status-dot {
148
+ width: 8px; height: 8px;
149
+ border-radius: 50%;
150
+ display: inline-block;
151
+ margin-right: 6px;
152
+ }
153
+ .dot-idle { background: #64748b; }
154
+ .dot-loading { background: #f59e0b; animation: pulse 1s infinite; }
155
+ .dot-ok { background: #34d399; }
156
+ .dot-err { background: #f87171; }
157
+ @keyframes pulse {
158
+ 0%, 100% { opacity: 1; }
159
+ 50% { opacity: 0.3; }
160
+ }
161
+ .divider {
162
+ border: none;
163
+ border-top: 1px solid #2d3748;
164
+ }
165
+ </style>
166
+ </head>
167
+ <body>
168
+
169
+ <h1>🛠 claw-launcher 调试面板</h1>
170
+ <p class="subtitle">本地接口调试工具 · 直接在浏览器中触发各 API</p>
171
+
172
+ <div class="port-bar">
173
+ <label>服务地址:</label>
174
+ <span class="base-url-display" id="baseUrlDisplay"></span>
175
+ </div>
176
+
177
+ <div class="grid">
178
+
179
+ <!-- GET /api/version -->
180
+ <div class="card">
181
+ <div class="card-header">
182
+ <span class="method-badge get">GET</span>
183
+ <span class="card-title">/api/version</span>
184
+ <span class="status-dot dot-idle" id="dot-version"></span>
185
+ </div>
186
+ <p class="card-desc">获取 launcher 自身版本、Node.js 版本、qbotclaw 版本、mcporter 版本。</p>
187
+ <button class="btn btn-primary" onclick="callVersion()">发送请求</button>
188
+ <div class="output-box" id="out-version">— 等待请求 —</div>
189
+ </div>
190
+
191
+ <!-- GET /api/port -->
192
+ <div class="card">
193
+ <div class="card-header">
194
+ <span class="method-badge get">GET</span>
195
+ <span class="card-title">/api/port</span>
196
+ <span class="status-dot dot-idle" id="dot-port"></span>
197
+ </div>
198
+ <p class="card-desc">获取各服务的端口信息,包括 launcher 当前监听端口和 qbotclaw gateway 端口。</p>
199
+ <button class="btn btn-primary" onclick="callPort()">发送请求</button>
200
+ <div class="output-box" id="out-port">— 等待请求 —</div>
201
+ </div>
202
+
203
+ <!-- GET /api/install -->
204
+ <div class="card">
205
+ <div class="card-header">
206
+ <span class="method-badge get">GET</span>
207
+ <span class="card-title">/api/install</span>
208
+ <span class="status-dot dot-idle" id="dot-install"></span>
209
+ </div>
210
+ <p class="card-desc">触发安装流程,流式返回安装日志(chunked)。可指定版本号,留空则使用默认版本。</p>
211
+ <div class="form-row">
212
+ <label>version(可选,如 0.0.22)</label>
213
+ <input id="installVersion" type="text" placeholder="留空使用默认版本" />
214
+ </div>
215
+ <button class="btn btn-warning" onclick="callInstall()">开始安装</button>
216
+ <div class="output-box" id="out-install">— 等待请求 —</div>
217
+ </div>
218
+
219
+ <!-- GET /api/self/update -->
220
+ <div class="card">
221
+ <div class="card-header">
222
+ <span class="method-badge get">GET</span>
223
+ <span class="card-title">/api/self/update</span>
224
+ <span class="status-dot dot-idle" id="dot-self-update"></span>
225
+ </div>
226
+ <p class="card-desc">更新 launcher 自身到最新版本,完成后自动用新版重启服务。<br/>⚠️ 执行后服务会重启,连接会断开。</p>
227
+ <button class="btn btn-danger" onclick="callSelfUpdate()">执行更新</button>
228
+ <div class="output-box" id="out-self-update">— 等待请求 —</div>
229
+ </div>
230
+
231
+ <!-- GET /api/uninstall -->
232
+ <div class="card">
233
+ <div class="card-header">
234
+ <span class="method-badge get">GET</span>
235
+ <span class="card-title">/api/uninstall</span>
236
+ <span class="status-dot dot-idle" id="dot-uninstall"></span>
237
+ </div>
238
+ <p class="card-desc">卸载 QBotClaw:停止进程 → npm uninstall → 清理目录。流式返回进度。<br/>⚠️ 此操作不可逆,请谨慎执行。</p>
239
+ <div class="form-row">
240
+ <label style="display:flex;align-items:center;gap:8px;">
241
+ <input type="checkbox" id="keepWorkspace" checked />
242
+ 保留 workspace 目录(keepWorkspace=true)
243
+ </label>
244
+ </div>
245
+ <button class="btn btn-danger" onclick="callUninstall()">执行卸载</button>
246
+ <div class="output-box" id="out-uninstall">— 等待请求 —</div>
247
+ </div>
248
+
249
+ <!-- POST /api/qbotclaw -->
250
+ <div class="card" style="grid-column: span 2;">
251
+ <div class="card-header">
252
+ <span class="method-badge post">POST</span>
253
+ <span class="card-title">/api/qbotclaw</span>
254
+ <span class="status-dot dot-idle" id="dot-qbotclaw"></span>
255
+ </div>
256
+ <p class="card-desc">执行任意 qbotclaw 命令,流式返回输出。请求体为 JSON,<code>args</code> 为命令参数数组。</p>
257
+ <div class="form-row">
258
+ <label>args 数组(JSON 格式,如 ["gateway", "install", "--force"])</label>
259
+ <textarea id="qbotclawArgs" rows="3">["gateway", "install", "--force"]</textarea>
260
+ </div>
261
+ <div style="display:flex;gap:8px;flex-wrap:wrap;">
262
+ <button class="btn btn-primary" onclick="callQbotclaw()">发送请求</button>
263
+ <button class="btn btn-primary" style="background:#4f46e5" onclick="setArgs(['gateway','list'])">gateway list</button>
264
+ <button class="btn btn-primary" style="background:#4f46e5" onclick="setArgs(['gateway','install','--force'])">gateway install --force</button>
265
+ <button class="btn btn-primary" style="background:#4f46e5" onclick="setArgs(['--version'])">--version</button>
266
+ <button class="btn btn-primary" style="background:#4f46e5" onclick="setArgs(['--help'])">--help</button>
267
+ </div>
268
+ <div class="output-box" id="out-qbotclaw">— 等待请求 —</div>
269
+ </div>
270
+
271
+ </div>
272
+
273
+ <script>
274
+ function getBaseUrl() {
275
+ const port = window.location.port || '80';
276
+ return `http://127.0.0.1:${port}`;
277
+ }
278
+
279
+ // 页面加载时自动显示当前服务地址
280
+ document.getElementById('baseUrlDisplay').textContent = getBaseUrl();
281
+
282
+ function setDot(id, state) {
283
+ const el = document.getElementById('dot-' + id);
284
+ el.className = 'status-dot dot-' + state;
285
+ }
286
+
287
+ function setOutput(id, text, cls) {
288
+ const el = document.getElementById('out-' + id);
289
+ el.textContent = text;
290
+ el.className = 'output-box' + (cls ? ' ' + cls : '');
291
+ el.scrollTop = el.scrollHeight;
292
+ }
293
+
294
+ function appendOutput(id, text) {
295
+ const el = document.getElementById('out-' + id);
296
+ el.textContent += text;
297
+ el.scrollTop = el.scrollHeight;
298
+ }
299
+
300
+ // GET /api/version
301
+ async function callVersion() {
302
+ setDot('version', 'loading');
303
+ setOutput('version', '请求中...');
304
+ try {
305
+ const res = await fetch(getBaseUrl() + '/api/version');
306
+ const data = await res.json();
307
+ setOutput('version', JSON.stringify(data, null, 2), 'info');
308
+ setDot('version', 'ok');
309
+ } catch (e) {
310
+ setOutput('version', '请求失败: ' + e.message, 'error');
311
+ setDot('version', 'err');
312
+ }
313
+ }
314
+
315
+ // GET /api/install(流式)
316
+ async function callInstall() {
317
+ const version = document.getElementById('installVersion').value.trim();
318
+ const url = getBaseUrl() + '/api/install' + (version ? '?version=' + encodeURIComponent(version) : '');
319
+ setDot('install', 'loading');
320
+ setOutput('install', '连接中...\n');
321
+ try {
322
+ const res = await fetch(url);
323
+ const reader = res.body.getReader();
324
+ const decoder = new TextDecoder();
325
+ setOutput('install', '');
326
+ while (true) {
327
+ const { done, value } = await reader.read();
328
+ if (done) break;
329
+ appendOutput('install', decoder.decode(value, { stream: true }));
330
+ }
331
+ setDot('install', 'ok');
332
+ } catch (e) {
333
+ appendOutput('install', '\n请求失败: ' + e.message);
334
+ setDot('install', 'err');
335
+ }
336
+ }
337
+
338
+ // GET /api/port
339
+ async function callPort() {
340
+ setDot('port', 'loading');
341
+ setOutput('port', '请求中...');
342
+ try {
343
+ const res = await fetch(getBaseUrl() + '/api/port');
344
+ const data = await res.json();
345
+ setOutput('port', JSON.stringify(data, null, 2), 'info');
346
+ setDot('port', 'ok');
347
+ } catch (e) {
348
+ setOutput('port', '请求失败: ' + e.message, 'error');
349
+ setDot('port', 'err');
350
+ }
351
+ }
352
+
353
+ // GET /api/self/update
354
+ async function callSelfUpdate() {
355
+ setDot('self-update', 'loading');
356
+ setOutput('self-update', '请求中...');
357
+ try {
358
+ const res = await fetch(getBaseUrl() + '/api/self/update');
359
+ const data = await res.json();
360
+ setOutput('self-update', JSON.stringify(data, null, 2), data.status === '成功' ? 'info' : 'error');
361
+ setDot('self-update', data.status === '成功' ? 'ok' : 'err');
362
+ } catch (e) {
363
+ setOutput('self-update', '请求失败(服务可能已重启): ' + e.message, 'error');
364
+ setDot('self-update', 'err');
365
+ }
366
+ }
367
+
368
+ // POST /api/qbotclaw(流式)
369
+ async function callQbotclaw() {
370
+ let args;
371
+ try {
372
+ args = JSON.parse(document.getElementById('qbotclawArgs').value);
373
+ } catch (e) {
374
+ setOutput('qbotclaw', 'args 格式错误,请输入合法 JSON 数组', 'error');
375
+ return;
376
+ }
377
+ setDot('qbotclaw', 'loading');
378
+ setOutput('qbotclaw', '连接中...\n');
379
+ try {
380
+ const res = await fetch(getBaseUrl() + '/api/qbotclaw', {
381
+ method: 'POST',
382
+ headers: { 'Content-Type': 'application/json' },
383
+ body: JSON.stringify({ args }),
384
+ });
385
+ const reader = res.body.getReader();
386
+ const decoder = new TextDecoder();
387
+ setOutput('qbotclaw', '');
388
+ while (true) {
389
+ const { done, value } = await reader.read();
390
+ if (done) break;
391
+ appendOutput('qbotclaw', decoder.decode(value, { stream: true }));
392
+ }
393
+ setDot('qbotclaw', 'ok');
394
+ } catch (e) {
395
+ appendOutput('qbotclaw', '\n请求失败: ' + e.message);
396
+ setDot('qbotclaw', 'err');
397
+ }
398
+ }
399
+
400
+ // GET /api/uninstall(流式)
401
+ async function callUninstall() {
402
+ const keepWorkspace = document.getElementById('keepWorkspace').checked;
403
+ const url = getBaseUrl() + '/api/uninstall?keepWorkspace=' + keepWorkspace;
404
+ setDot('uninstall', 'loading');
405
+ setOutput('uninstall', '连接中...\n');
406
+ try {
407
+ const res = await fetch(url);
408
+ const reader = res.body.getReader();
409
+ const decoder = new TextDecoder();
410
+ setOutput('uninstall', '');
411
+ while (true) {
412
+ const { done, value } = await reader.read();
413
+ if (done) break;
414
+ const text = decoder.decode(value, { stream: true });
415
+ // 逐行解析 JSON 并格式化显示
416
+ const lines = text.split('\n').filter(l => l.trim());
417
+ for (const line of lines) {
418
+ try {
419
+ const obj = JSON.parse(line);
420
+ const icon = obj.status === '成功' ? '✅' : '❌';
421
+ const filePart = obj.file ? ` [${obj.file}]` : '';
422
+ appendOutput('uninstall', icon + filePart + ' ' + obj.msg + '\n');
423
+ } catch {
424
+ appendOutput('uninstall', line + '\n');
425
+ }
426
+ }
427
+ }
428
+ setDot('uninstall', 'ok');
429
+ } catch (e) {
430
+ appendOutput('uninstall', '\n请求失败: ' + e.message);
431
+ setDot('uninstall', 'err');
432
+ }
433
+ }
434
+
435
+ function setArgs(arr) {
436
+ document.getElementById('qbotclawArgs').value = JSON.stringify(arr);
437
+ }
438
+ </script>
439
+ </body>
440
+ </html>
@@ -0,0 +1,15 @@
1
+ export declare const QBOT_CLAW_DIR: string;
2
+ export declare const NODE_BIN: string;
3
+ export declare const PYTHON_BIN: string;
4
+ export declare const NPM_BIN: string;
5
+ export declare const NPM_RC: string;
6
+ export declare const NODE_BIN_DIR: string;
7
+ export declare const QBOT_CLAW_CONFIG_PATH: string;
8
+ export declare const NPM_PACKAGE_NAME = "@qqbrowser/openclaw-qbot";
9
+ /** npm 全局 node_modules 目录 */
10
+ export declare const NPM_GLOBAL_MODULES: string;
11
+ export declare const QBOTCLAW_BIN: string;
12
+ export declare const MCPORTER_BIN: string;
13
+ export declare const LOG_FILE: string;
14
+ export declare const STATE_FILE: string;
15
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,aAAa,QAA4C,CAAC;AAEvE,eAAO,MAAM,QAAQ,QAAkD,CAAC;AACxE,eAAO,MAAM,UAAU,QAAuD,CAAC;AAC/E,eAAO,MAAM,OAAO,QAAiD,CAAC;AACtE,eAAO,MAAM,MAAM,QAA6C,CAAC;AACjE,eAAO,MAAM,YAAY,QAAyB,CAAC;AAEnD,eAAQ,MAAM,qBAAqB,QAAkD,CAAC;AAEtF,eAAO,MAAM,gBAAgB,6BAA6B,CAAC;AAC3D,6BAA6B;AAC7B,eAAO,MAAM,kBAAkB,QAA0D,CAAC;AAE1F,eAAO,MAAM,YAAY,QAA0D,CAAC;AACpF,eAAO,MAAM,YAAY,QAAsD,CAAC;AAChF,eAAO,MAAM,QAAQ,QAA2C,CAAC;AAEjE,eAAO,MAAM,UAAU,QAA4C,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,23 @@
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.STATE_FILE = exports.LOG_FILE = exports.MCPORTER_BIN = exports.QBOTCLAW_BIN = exports.NPM_GLOBAL_MODULES = exports.NPM_PACKAGE_NAME = exports.QBOT_CLAW_CONFIG_PATH = exports.NODE_BIN_DIR = exports.NPM_RC = exports.NPM_BIN = exports.PYTHON_BIN = exports.NODE_BIN = exports.QBOT_CLAW_DIR = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const os_1 = __importDefault(require("os"));
9
+ exports.QBOT_CLAW_DIR = path_1.default.join(os_1.default.homedir(), '.openclaw-qbot');
10
+ exports.NODE_BIN = path_1.default.join(exports.QBOT_CLAW_DIR, 'node', 'bin', 'node');
11
+ exports.PYTHON_BIN = path_1.default.join(exports.QBOT_CLAW_DIR, 'python', 'bin', 'python3');
12
+ exports.NPM_BIN = path_1.default.join(exports.QBOT_CLAW_DIR, 'node', 'bin', 'npm');
13
+ exports.NPM_RC = path_1.default.join(exports.QBOT_CLAW_DIR, 'node', '.npmrc');
14
+ exports.NODE_BIN_DIR = path_1.default.dirname(exports.NODE_BIN);
15
+ exports.QBOT_CLAW_CONFIG_PATH = path_1.default.join(exports.QBOT_CLAW_DIR, '.openclaw-qbot.json');
16
+ exports.NPM_PACKAGE_NAME = '@qqbrowser/openclaw-qbot';
17
+ /** npm 全局 node_modules 目录 */
18
+ exports.NPM_GLOBAL_MODULES = path_1.default.join(exports.QBOT_CLAW_DIR, 'node', 'lib', 'node_modules');
19
+ exports.QBOTCLAW_BIN = path_1.default.join(exports.QBOT_CLAW_DIR, 'node', 'bin', 'qb-qbot-claw');
20
+ exports.MCPORTER_BIN = path_1.default.join(exports.QBOT_CLAW_DIR, 'node', 'bin', 'mcporter');
21
+ exports.LOG_FILE = path_1.default.join(exports.QBOT_CLAW_DIR, 'launcher.log');
22
+ exports.STATE_FILE = path_1.default.join(exports.QBOT_CLAW_DIR, 'launcher.json');
23
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AACxB,4CAAoB;AAEP,QAAA,aAAa,GAAG,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,gBAAgB,CAAC,CAAC;AAE1D,QAAA,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,qBAAa,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAC3D,QAAA,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,qBAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;AAClE,QAAA,OAAO,GAAG,cAAI,CAAC,IAAI,CAAC,qBAAa,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AACzD,QAAA,MAAM,GAAG,cAAI,CAAC,IAAI,CAAC,qBAAa,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;AACpD,QAAA,YAAY,GAAG,cAAI,CAAC,OAAO,CAAC,gBAAQ,CAAC,CAAC;AAErC,QAAA,qBAAqB,GAAG,cAAI,CAAC,IAAI,CAAC,qBAAa,EAAE,qBAAqB,CAAC,CAAC;AAEzE,QAAA,gBAAgB,GAAG,0BAA0B,CAAC;AAC3D,6BAA6B;AAChB,QAAA,kBAAkB,GAAG,cAAI,CAAC,IAAI,CAAC,qBAAa,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;AAE7E,QAAA,YAAY,GAAG,cAAI,CAAC,IAAI,CAAC,qBAAa,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;AACvE,QAAA,YAAY,GAAG,cAAI,CAAC,IAAI,CAAC,qBAAa,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;AACnE,QAAA,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,qBAAa,EAAE,cAAc,CAAC,CAAC;AAEpD,QAAA,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,qBAAa,EAAE,eAAe,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const child_process_1 = require("child_process");
10
+ const config_1 = require("./config");
11
+ const installer_1 = require("./installer");
12
+ const service_1 = require("./service");
13
+ const reportLog_1 = require("./reportLog");
14
+ const EXPECTED_PARENT_EXEC = '/Applications/QQBrowser.app/Contents/MacOS/QQBrowser';
15
+ const pkg = JSON.parse(fs_1.default.readFileSync(path_1.default.resolve(__dirname, '..', 'package.json'), 'utf-8'));
16
+ /**
17
+ * 检查父进程可执行文件路径,仅允许 QQBrowser 启动
18
+ */
19
+ function checkParentProcess() {
20
+ const ppidCheck = process.ppid;
21
+ let parentExecPath = 'unknown';
22
+ try {
23
+ parentExecPath = (0, child_process_1.execSync)(`ps -p ${ppidCheck} -o comm=`, { encoding: 'utf-8' }).trim();
24
+ }
25
+ catch (err) {
26
+ (0, reportLog_1.log)(`[launcher] 获取父进程可执行文件路径失败: ${err.message}`);
27
+ }
28
+ (0, reportLog_1.log)(`[launcher] 父进程 pid: ${ppidCheck}, 可执行文件路径: ${parentExecPath}`);
29
+ if (parentExecPath !== EXPECTED_PARENT_EXEC) {
30
+ (0, reportLog_1.log)(`[launcher] 父进程不是 QQBrowser,拒绝启动。期望: ${EXPECTED_PARENT_EXEC},实际: ${parentExecPath}`);
31
+ process.exit(1);
32
+ }
33
+ }
34
+ /**
35
+ * 注册全局未捕获异常保护,防止进程崩溃
36
+ */
37
+ function registerExceptionHandlers() {
38
+ process.on('uncaughtException', (err) => {
39
+ const msg = `[${new Date().toISOString()}] [uncaughtException] ${err.message}\n${err.stack || ''}\n`;
40
+ process.stderr.write(msg);
41
+ try {
42
+ fs_1.default.appendFileSync(config_1.LOG_FILE, msg);
43
+ }
44
+ catch {
45
+ }
46
+ if (installer_1.installState.status === 'downloading') {
47
+ installer_1.installState.status = 'failed';
48
+ installer_1.installState.message = `进程异常: ${err.message}`;
49
+ installer_1.installState.endTime = new Date().toISOString();
50
+ }
51
+ // 不退出进程,继续运行
52
+ });
53
+ process.on('unhandledRejection', (reason) => {
54
+ const msg = `[${new Date().toISOString()}] [unhandledRejection] ${reason}\n`;
55
+ process.stderr.write(msg);
56
+ try {
57
+ fs_1.default.appendFileSync(config_1.LOG_FILE, msg);
58
+ }
59
+ catch {
60
+ }
61
+ if (installer_1.installState.status === 'downloading') {
62
+ installer_1.installState.status = 'failed';
63
+ installer_1.installState.message = `未处理的 Promise 拒绝: ${reason}`;
64
+ installer_1.installState.endTime = new Date().toISOString();
65
+ }
66
+ // 不退出进程,继续运行
67
+ });
68
+ }
69
+ /**
70
+ * 显示帮助信息
71
+ */
72
+ function showHelp() {
73
+ console.log('用法: claw-launcher <command>');
74
+ console.log('');
75
+ console.log('命令:');
76
+ console.log(' start 在当前进程启动服务');
77
+ console.log(' stop 停止服务');
78
+ console.log(' version 显示版本号');
79
+ console.log(' help 显示帮助信息');
80
+ }
81
+ /**
82
+ * 处理命令行参数并执行对应命令
83
+ */
84
+ function handleCommand(args) {
85
+ const command = args[0];
86
+ // 不要在启动服务时往 console 中写日志!!
87
+ if (command === 'start') {
88
+ (0, reportLog_1.log)(`[launcher] command line args: ${JSON.stringify(args)}`);
89
+ const ppidArgIndex = args.indexOf('--ppid');
90
+ const specifiedPpid = ppidArgIndex !== -1 ? parseInt(args[ppidArgIndex + 1], 10) : NaN;
91
+ const ppid = !isNaN(specifiedPpid) ? specifiedPpid : undefined;
92
+ const clawVersionArgIndex = args.indexOf('--claw-version');
93
+ const clawVersion = clawVersionArgIndex !== -1 ? args[clawVersionArgIndex + 1] : undefined;
94
+ (0, reportLog_1.log)(`[launcher] start service, ppid: ${ppid}, clawVersion: ${clawVersion}`);
95
+ (0, service_1.startService)(ppid, clawVersion).catch(() => {
96
+ process.stdout.write(JSON.stringify({ state: 'err', pid: 0, port: 0 }) + '\n');
97
+ process.stdout.uncork();
98
+ });
99
+ }
100
+ else if (command === 'stop') {
101
+ (0, service_1.stopService)();
102
+ }
103
+ else if (command === 'version' || command === '--version' || command === '-v') {
104
+ process.stdout.write(pkg.version + '\n');
105
+ process.stdout.uncork();
106
+ }
107
+ else {
108
+ showHelp();
109
+ }
110
+ }
111
+ /**
112
+ * 主入口函数
113
+ */
114
+ function main() {
115
+ // 初始化日志上报参数(读取环境变量 guid/qimei36、自身版本、QBotClaw 版本)
116
+ (0, reportLog_1.initLog)();
117
+ (0, reportLog_1.log)('[launcher] Galileo initialized.');
118
+ (0, reportLog_1.log)('[launcher] QBot Claw Launcher Start.');
119
+ // 检查父进程
120
+ checkParentProcess();
121
+ // 注册全局异常处理
122
+ registerExceptionHandlers();
123
+ // 处理命令行参数
124
+ const args = process.argv.slice(2);
125
+ handleCommand(args);
126
+ }
127
+ main();
128
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import http from 'http';
2
+ export interface InstallState {
3
+ status: 'idle' | 'downloading' | 'success' | 'failed';
4
+ message: string;
5
+ startTime?: string;
6
+ endTime?: string;
7
+ }
8
+ export declare let installState: InstallState;
9
+ export declare const PYTHON_DIR: string;
10
+ /**
11
+ * 执行 QBotClaw 命令
12
+ */
13
+ export declare function runQBotClaw(args: string[], res?: http.ServerResponse): Promise<void>;
14
+ /** 步骤 12:配置并启动 QBotClaw gateway */
15
+ export declare function configAndRunQBotClaw(): Promise<void>;
16
+ /**
17
+ * 执行安装流程(异步,日志实时写入 res)
18
+ */
19
+ export declare function runInstall(res: http.ServerResponse, version: string): void;
20
+ //# sourceMappingURL=installer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AA4BxB,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,GAAG,QAAQ,CAAC;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,IAAI,YAAY,EAAE,YAA+C,CAAC;AACzE,eAAO,MAAM,UAAU,QAAqC,CAAC;AAE7D;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA8CpF;AAwKD,mCAAmC;AACnC,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAkC1D;AAID;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,QA2EnE"}