@ryantest/openclaw-qqbot 1.6.7-beta.20 → 1.6.7-beta.22
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/dist/src/slash-commands.js +25 -3
- package/package.json +1 -1
- package/scripts/upgrade-via-source.sh +86 -8
- package/src/slash-commands.ts +23 -3
|
@@ -793,10 +793,15 @@ function fireHotUpgrade(targetVersion, pkg, useLocal) {
|
|
|
793
793
|
// 必须显式设置 cwd 为一个确定存在的目录(如 homeDir),
|
|
794
794
|
// 否则子进程继承 gateway 的 cwd,如果该目录在升级过程中被删除/移动,
|
|
795
795
|
// openclaw CLI 启动时 process.cwd() 会报 ENOENT: uv_cwd 错误。
|
|
796
|
-
|
|
797
|
-
|
|
796
|
+
// 超时设为 5 分钟:openclaw plugins install 需要下载 npm 包,
|
|
797
|
+
// 网络慢时(如国内访问 npm registry)可能需要 2-3 分钟。
|
|
798
|
+
// 120 秒超时会导致脚本被杀但 openclaw CLI 子进程继续运行,
|
|
799
|
+
// 同时 bash 的 cleanup_on_exit 回滚了备份目录,造成 "plugin already exists" 错误。
|
|
800
|
+
const child = execFile(shell, shellArgs, {
|
|
801
|
+
timeout: 300_000,
|
|
798
802
|
cwd: homeDir,
|
|
799
803
|
env: childEnv,
|
|
804
|
+
killSignal: "SIGTERM",
|
|
800
805
|
...(isWindows() ? { windowsHide: true } : {}),
|
|
801
806
|
}, (error, stdout, _stderr) => {
|
|
802
807
|
if (error) {
|
|
@@ -805,6 +810,24 @@ function fireHotUpgrade(targetVersion, pkg, useLocal) {
|
|
|
805
810
|
console.error(`[qqbot] fireHotUpgrade: stdout: ${stdout.slice(0, 2000)}`);
|
|
806
811
|
if (_stderr)
|
|
807
812
|
console.error(`[qqbot] fireHotUpgrade: stderr: ${_stderr.slice(0, 2000)}`);
|
|
813
|
+
// 超时时确保子进程树被清理,防止 openclaw plugins install 继续运行
|
|
814
|
+
// 与 cleanup_on_exit 的回滚逻辑冲突(回滚恢复了旧目录,install 又尝试写入)
|
|
815
|
+
if (error.killed || error.message.includes("TIMEOUT")) {
|
|
816
|
+
try {
|
|
817
|
+
// 尝试杀掉子进程树(SIGKILL 确保立即终止)
|
|
818
|
+
child.kill("SIGKILL");
|
|
819
|
+
// 额外尝试通过 pkill 杀掉可能残留的 openclaw plugins install 子进程
|
|
820
|
+
if (!isWindows()) {
|
|
821
|
+
try {
|
|
822
|
+
execFileSync("pkill", ["-9", "-f", "openclaw.*plugins.*install"], { timeout: 3000, stdio: "pipe" });
|
|
823
|
+
}
|
|
824
|
+
catch { /* ignore */ }
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
catch {
|
|
828
|
+
// 进程可能已退出
|
|
829
|
+
}
|
|
830
|
+
}
|
|
808
831
|
syncTempConfigAndCleanup();
|
|
809
832
|
cleanupTempScript();
|
|
810
833
|
_upgrading = false;
|
|
@@ -991,7 +1014,6 @@ elif [ -f "$BACKUP" ]; then
|
|
|
991
1014
|
# gateway 的 config file watcher 会检测到变更并热加载
|
|
992
1015
|
echo "[qqbot-upgrade] Restoring channels.qqbot to real config..."
|
|
993
1016
|
node -e "
|
|
994
|
-
const fs = require('fs');
|
|
995
1017
|
const fs = require('fs');
|
|
996
1018
|
const cfg = JSON.parse(fs.readFileSync(process.argv[1], 'utf8'));
|
|
997
1019
|
const qqbot = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
|
package/package.json
CHANGED
|
@@ -291,7 +291,25 @@ fi
|
|
|
291
291
|
# 由于 CJS/ESM 混用问题(Node 22 ERR_INTERNAL_ASSERTION),验证阶段可能失败
|
|
292
292
|
# 但文件已成功拷贝。因此不依赖退出码,而是检查安装目录中关键文件是否存在。
|
|
293
293
|
_INSTALL_DIR="$HOME/.openclaw/extensions/openclaw-qqbot"
|
|
294
|
+
|
|
295
|
+
# ── 优化:安装前临时移走 node_modules ──
|
|
296
|
+
# openclaw plugins install . 会把整个项目目录(含 node_modules/)复制到 extensions,
|
|
297
|
+
# 但运行时只需要 bundledDependencies 中的 3 个包 + openclaw symlink。
|
|
298
|
+
# 移走 node_modules 可避免复制数百个不必要的包,大幅加速安装。
|
|
299
|
+
_NM_BACKUP=""
|
|
300
|
+
if [ -d "$PROJ_DIR/node_modules" ]; then
|
|
301
|
+
echo " 临时移走 node_modules(避免整体复制到 extensions)..."
|
|
302
|
+
_NM_BACKUP="$PROJ_DIR/.node_modules_install_bak"
|
|
303
|
+
mv "$PROJ_DIR/node_modules" "$_NM_BACKUP"
|
|
304
|
+
fi
|
|
305
|
+
|
|
294
306
|
openclaw plugins install . 2>&1 | tee "$INSTALL_LOG" || true
|
|
307
|
+
|
|
308
|
+
# ── 恢复 node_modules ──
|
|
309
|
+
if [ -n "$_NM_BACKUP" ] && [ -d "$_NM_BACKUP" ]; then
|
|
310
|
+
mv "$_NM_BACKUP" "$PROJ_DIR/node_modules"
|
|
311
|
+
echo " 已恢复源码目录 node_modules"
|
|
312
|
+
fi
|
|
295
313
|
if [ ! -f "$_INSTALL_DIR/dist/index.js" ] || [ ! -f "$_INSTALL_DIR/preload.cjs" ]; then
|
|
296
314
|
echo ""
|
|
297
315
|
echo "❌ 插件安装失败!"
|
|
@@ -400,6 +418,12 @@ else
|
|
|
400
418
|
echo " 尝试自动修复: 清理残留并重试安装..."
|
|
401
419
|
find "$HOME/.openclaw/extensions/" -maxdepth 1 -name ".openclaw-install-stage-*" -exec rm -rf {} + 2>/dev/null || true
|
|
402
420
|
find "${TMPDIR:-/tmp}" -maxdepth 1 -name ".openclaw-install-stage-*" -exec rm -rf {} + 2>/dev/null || true
|
|
421
|
+
# 重试时同样移走 node_modules 避免整体复制
|
|
422
|
+
_NM_BACKUP=""
|
|
423
|
+
if [ -d "$PROJ_DIR/node_modules" ]; then
|
|
424
|
+
_NM_BACKUP="$PROJ_DIR/.node_modules_install_bak"
|
|
425
|
+
mv "$PROJ_DIR/node_modules" "$_NM_BACKUP"
|
|
426
|
+
fi
|
|
403
427
|
if openclaw plugins install . 2>&1 | tee -a "$INSTALL_LOG"; then
|
|
404
428
|
for _candidate_name in openclaw-qqbot qqbot openclaw-qq; do
|
|
405
429
|
if [ -d "$HOME/.openclaw/extensions/$_candidate_name" ]; then
|
|
@@ -409,6 +433,10 @@ else
|
|
|
409
433
|
fi
|
|
410
434
|
done
|
|
411
435
|
fi
|
|
436
|
+
# 恢复 node_modules
|
|
437
|
+
if [ -n "$_NM_BACKUP" ] && [ -d "$_NM_BACKUP" ]; then
|
|
438
|
+
mv "$_NM_BACKUP" "$PROJ_DIR/node_modules"
|
|
439
|
+
fi
|
|
412
440
|
if [ "$_plugin_dir_ok" -eq 0 ]; then
|
|
413
441
|
echo " ❌ 重试安装仍失败,插件目录不存在"
|
|
414
442
|
echo " 请手动排查: ls -la ~/.openclaw/extensions/"
|
|
@@ -442,18 +470,70 @@ else
|
|
|
442
470
|
fi
|
|
443
471
|
fi
|
|
444
472
|
|
|
445
|
-
#
|
|
446
|
-
#
|
|
447
|
-
# (
|
|
448
|
-
# 新版已修复,此处通过阈值判断:包数量 > 50 才触发清理,避免对新版做无用操作。
|
|
473
|
+
# ── 复制 bundledDependencies 到插件 node_modules ──
|
|
474
|
+
# 由于安装前移走了源码的 node_modules,extensions 中的插件目录没有依赖。
|
|
475
|
+
# 只需复制 bundledDependencies(ws, silk-wasm, mpg123-decoder)及其传递依赖即可。
|
|
449
476
|
PLUGIN_NM=""
|
|
450
477
|
for _candidate in openclaw-qqbot qqbot openclaw-qq; do
|
|
451
478
|
_nm="$HOME/.openclaw/extensions/$_candidate/node_modules"
|
|
452
|
-
|
|
479
|
+
_ext_dir="$HOME/.openclaw/extensions/$_candidate"
|
|
480
|
+
[ -d "$_ext_dir" ] && PLUGIN_NM="$_nm" && break
|
|
453
481
|
done
|
|
454
|
-
if [ -n "$PLUGIN_NM" ]; then
|
|
482
|
+
if [ -n "$PLUGIN_NM" ] && [ -d "$PROJ_DIR/node_modules" ]; then
|
|
483
|
+
# 如果 extensions 中已有大量包(旧版 openclaw 安装的 peerDeps),先清理
|
|
484
|
+
if [ -d "$PLUGIN_NM" ]; then
|
|
485
|
+
_before=$(ls -d "$PLUGIN_NM"/*/ "$PLUGIN_NM"/@*/*/ 2>/dev/null | wc -l | tr -d ' ')
|
|
486
|
+
if [ "$_before" -gt 50 ]; then
|
|
487
|
+
echo ""
|
|
488
|
+
echo "检测到 ${_before} 个包(超过阈值 50),清理多余的 peerDep 传递依赖..."
|
|
489
|
+
rm -rf "$PLUGIN_NM"
|
|
490
|
+
fi
|
|
491
|
+
fi
|
|
492
|
+
|
|
493
|
+
# 读取 bundledDependencies 及其传递依赖列表,只复制这些包
|
|
494
|
+
_deps_to_copy=$(node -e "
|
|
495
|
+
const fs = require('fs');
|
|
496
|
+
const path = require('path');
|
|
497
|
+
const pkgPath = path.join('$PROJ_DIR', 'package.json');
|
|
498
|
+
if (!fs.existsSync(pkgPath)) process.exit(0);
|
|
499
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
500
|
+
const bundled = pkg.bundledDependencies || pkg.bundleDependencies || [];
|
|
501
|
+
const keep = new Set();
|
|
502
|
+
const resolve = (name) => {
|
|
503
|
+
if (keep.has(name)) return;
|
|
504
|
+
keep.add(name);
|
|
505
|
+
const depPkg = path.join('$PROJ_DIR', 'node_modules', name, 'package.json');
|
|
506
|
+
if (!fs.existsSync(depPkg)) return;
|
|
507
|
+
const dep = JSON.parse(fs.readFileSync(depPkg, 'utf8'));
|
|
508
|
+
for (const d of Object.keys(dep.dependencies || {})) resolve(d);
|
|
509
|
+
};
|
|
510
|
+
bundled.forEach(resolve);
|
|
511
|
+
process.stdout.write([...keep].join('\\n'));
|
|
512
|
+
" 2>/dev/null || true)
|
|
513
|
+
|
|
514
|
+
if [ -n "$_deps_to_copy" ]; then
|
|
515
|
+
mkdir -p "$PLUGIN_NM"
|
|
516
|
+
_copied=0
|
|
517
|
+
echo "$_deps_to_copy" | while IFS= read -r _dep; do
|
|
518
|
+
_src="$PROJ_DIR/node_modules/$_dep"
|
|
519
|
+
_dst="$PLUGIN_NM/$_dep"
|
|
520
|
+
if [ -d "$_src" ] && [ ! -d "$_dst" ]; then
|
|
521
|
+
# 处理 scoped 包(如 @scope/pkg)
|
|
522
|
+
mkdir -p "$(dirname "$_dst")"
|
|
523
|
+
cp -r "$_src" "$_dst"
|
|
524
|
+
fi
|
|
525
|
+
done
|
|
526
|
+
_after=$(ls -d "$PLUGIN_NM"/*/ "$PLUGIN_NM"/@*/*/ 2>/dev/null | wc -l | tr -d ' ')
|
|
527
|
+
echo " ✅ 已复制 bundled 依赖到插件目录(${_after} 个包)"
|
|
528
|
+
else
|
|
529
|
+
echo " ⚠️ 未读取到 bundledDependencies,跳过依赖复制"
|
|
530
|
+
fi
|
|
531
|
+
elif [ -n "$PLUGIN_NM" ] && [ -d "$PLUGIN_NM" ]; then
|
|
532
|
+
# node_modules 已存在(可能是旧版 openclaw 安装的),检查是否需要清理
|
|
455
533
|
_before=$(ls -d "$PLUGIN_NM"/*/ "$PLUGIN_NM"/@*/*/ 2>/dev/null | wc -l | tr -d ' ')
|
|
456
534
|
if [ "$_before" -gt 50 ]; then
|
|
535
|
+
echo ""
|
|
536
|
+
echo "检测到 ${_before} 个包(超过阈值 50),清理多余的 peerDep 传递依赖..."
|
|
457
537
|
# 读取 bundledDependencies 列表,只保留这些包及其子依赖
|
|
458
538
|
_bundled_deps=$(node -e "
|
|
459
539
|
const fs = require('fs');
|
|
@@ -492,8 +572,6 @@ else
|
|
|
492
572
|
process.stdout.write(toRemove.join('\n'));
|
|
493
573
|
" 2>/dev/null || true)
|
|
494
574
|
if [ -n "$_bundled_deps" ]; then
|
|
495
|
-
echo ""
|
|
496
|
-
echo "检测到 ${_before} 个包(超过阈值 50),清理多余的 peerDep 传递依赖..."
|
|
497
575
|
echo "$_bundled_deps" | while IFS= read -r _pkg; do
|
|
498
576
|
rm -rf "$PLUGIN_NM/$_pkg"
|
|
499
577
|
done
|
package/src/slash-commands.ts
CHANGED
|
@@ -891,16 +891,37 @@ function fireHotUpgrade(targetVersion?: string, pkg?: string, useLocal?: boolean
|
|
|
891
891
|
// 必须显式设置 cwd 为一个确定存在的目录(如 homeDir),
|
|
892
892
|
// 否则子进程继承 gateway 的 cwd,如果该目录在升级过程中被删除/移动,
|
|
893
893
|
// openclaw CLI 启动时 process.cwd() 会报 ENOENT: uv_cwd 错误。
|
|
894
|
-
|
|
895
|
-
|
|
894
|
+
// 超时设为 5 分钟:openclaw plugins install 需要下载 npm 包,
|
|
895
|
+
// 网络慢时(如国内访问 npm registry)可能需要 2-3 分钟。
|
|
896
|
+
// 120 秒超时会导致脚本被杀但 openclaw CLI 子进程继续运行,
|
|
897
|
+
// 同时 bash 的 cleanup_on_exit 回滚了备份目录,造成 "plugin already exists" 错误。
|
|
898
|
+
const child = execFile(shell, shellArgs, {
|
|
899
|
+
timeout: 300_000,
|
|
896
900
|
cwd: homeDir,
|
|
897
901
|
env: childEnv,
|
|
902
|
+
killSignal: "SIGTERM",
|
|
898
903
|
...(isWindows() ? { windowsHide: true } : {}),
|
|
899
904
|
}, (error, stdout, _stderr) => {
|
|
900
905
|
if (error) {
|
|
901
906
|
console.error(`[qqbot] fireHotUpgrade: script failed: ${error.message}`);
|
|
902
907
|
if (stdout) console.error(`[qqbot] fireHotUpgrade: stdout: ${stdout.slice(0, 2000)}`);
|
|
903
908
|
if (_stderr) console.error(`[qqbot] fireHotUpgrade: stderr: ${_stderr.slice(0, 2000)}`);
|
|
909
|
+
|
|
910
|
+
// 超时时确保子进程树被清理,防止 openclaw plugins install 继续运行
|
|
911
|
+
// 与 cleanup_on_exit 的回滚逻辑冲突(回滚恢复了旧目录,install 又尝试写入)
|
|
912
|
+
if ((error as any).killed || error.message.includes("TIMEOUT")) {
|
|
913
|
+
try {
|
|
914
|
+
// 尝试杀掉子进程树(SIGKILL 确保立即终止)
|
|
915
|
+
child.kill("SIGKILL");
|
|
916
|
+
// 额外尝试通过 pkill 杀掉可能残留的 openclaw plugins install 子进程
|
|
917
|
+
if (!isWindows()) {
|
|
918
|
+
try { execFileSync("pkill", ["-9", "-f", "openclaw.*plugins.*install"], { timeout: 3000, stdio: "pipe" }); } catch { /* ignore */ }
|
|
919
|
+
}
|
|
920
|
+
} catch {
|
|
921
|
+
// 进程可能已退出
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
|
|
904
925
|
syncTempConfigAndCleanup();
|
|
905
926
|
cleanupTempScript();
|
|
906
927
|
_upgrading = false;
|
|
@@ -1092,7 +1113,6 @@ elif [ -f "$BACKUP" ]; then
|
|
|
1092
1113
|
# gateway 的 config file watcher 会检测到变更并热加载
|
|
1093
1114
|
echo "[qqbot-upgrade] Restoring channels.qqbot to real config..."
|
|
1094
1115
|
node -e "
|
|
1095
|
-
const fs = require('fs');
|
|
1096
1116
|
const fs = require('fs');
|
|
1097
1117
|
const cfg = JSON.parse(fs.readFileSync(process.argv[1], 'utf8'));
|
|
1098
1118
|
const qqbot = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
|